aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan D2015-05-23 12:34:45 +0200
committerJan D2015-05-23 12:34:45 +0200
commitc03c730481bd2dc7bc857d9b4f1c41eea9bd495e (patch)
treea34eb6ad435ab877848f7464374570549ca55ec5
parent7ac84a2570e1268cc040fcd529508307b2b22c01 (diff)
parent6aaa489dc112f51f6045f79b37cb78dd513e398f (diff)
downloademacs-c03c730481bd2dc7bc857d9b4f1c41eea9bd495e.tar.gz
emacs-c03c730481bd2dc7bc857d9b4f1c41eea9bd495e.zip
Merge branch 'cairo'.
Main work done by YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>. Small fixes and image work by Jan D. <jan.h.d@swipnet.se>.
-rw-r--r--ChangeLog.121
-rw-r--r--configure.ac30
-rw-r--r--lisp/ChangeLog.176
-rw-r--r--lisp/version.el7
-rw-r--r--lwlib/ChangeLog.13
-rw-r--r--lwlib/Makefile.in2
-rw-r--r--src/ChangeLog.13236
-rw-r--r--src/Makefile.in8
-rw-r--r--src/dispextern.h7
-rw-r--r--src/font.c4
-rw-r--r--src/font.h4
-rw-r--r--src/fringe.c24
-rw-r--r--src/ftcrfont.c320
-rw-r--r--src/ftfont.c26
-rw-r--r--src/ftfont.h5
-rw-r--r--src/gtkutil.c128
-rw-r--r--src/gtkutil.h6
-rw-r--r--src/image.c379
-rw-r--r--src/xfns.c193
-rw-r--r--src/xterm.c998
-rw-r--r--src/xterm.h53
21 files changed, 2320 insertions, 140 deletions
diff --git a/ChangeLog.1 b/ChangeLog.1
index d1b8d0ffb98..565c85bbcf1 100644
--- a/ChangeLog.1
+++ b/ChangeLog.1
@@ -1,9 +1,23 @@
12015-04-11 Jan Djärv <jan.h.d@swipnet.se>
2
3 * configure.ac: Allow jpeg with cairo.
4 Allow tiff and gif with cairo.
5
12015-04-07 Paul Eggert <eggert@cs.ucla.edu> 62015-04-07 Paul Eggert <eggert@cs.ucla.edu>
2 7
3 Merge from gnulib 8 Merge from gnulib
4 * lib/stddef.in.h: Update from gnulib, incorporating: 9 * lib/stddef.in.h: Update from gnulib, incorporating:
5 2015-04-02 stddef: port to pre-C11 GCC on x86 10 2015-04-02 stddef: port to pre-C11 GCC on x86
6 11
122015-04-05 Jan Djärv <jan.h.d@swipnet.se>
13
14 * configure.ac: Allow rsvg with cairo. Move back HAVE_RSVG.
15
162015-04-03 Jan Djärv <jan.h.d@swipnet.se>
17
18 * configure.ac (HAVE_RSVG): Move after cairo.
19 (USE_CAIRO): Disable rsvg, don't disable Xpm.
20
72015-04-03 Paul Eggert <eggert@cs.ucla.edu> 212015-04-03 Paul Eggert <eggert@cs.ucla.edu>
8 22
9 Port 'configure' to clang 3.5 23 Port 'configure' to clang 3.5
@@ -108,6 +122,13 @@
108 * configure.ac: Set locallisppath to empty for NS self contained, 122 * configure.ac: Set locallisppath to empty for NS self contained,
109 unless --enable-loadllisppath was given (Bug#19850). 123 unless --enable-loadllisppath was given (Bug#19850).
110 124
1252015-02-11 Jan Djärv <jan.h.d@swipnet.se>
126
127 * configure.ac (with-cairo): New option.
128 (USE_CAIRO): Default to yes for Gtk+ 3. Add code to test for cairo,
129 set CAIRO_CFLAGS, CAIRO_LIBS. Add ftcrfonto to FONT_OBJ if cairo.
130 Output "Does Emacs use cairo?".
131
1112015-02-09 Paul Eggert <eggert@cs.ucla.edu> 1322015-02-09 Paul Eggert <eggert@cs.ucla.edu>
112 133
113 * configure.ac (HAVE_LIBXML2): Add missing comma. 134 * configure.ac (HAVE_LIBXML2): Add missing comma.
diff --git a/configure.ac b/configure.ac
index 752204c3a8c..a9fe0952b16 100644
--- a/configure.ac
+++ b/configure.ac
@@ -330,6 +330,7 @@ OPTION_DEFAULT_ON([tiff],[don't compile with TIFF image support])
330OPTION_DEFAULT_ON([gif],[don't compile with GIF image support]) 330OPTION_DEFAULT_ON([gif],[don't compile with GIF image support])
331OPTION_DEFAULT_ON([png],[don't compile with PNG image support]) 331OPTION_DEFAULT_ON([png],[don't compile with PNG image support])
332OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support]) 332OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support])
333OPTION_DEFAULT_OFF([cairo],[compile with Cairo drawing])
333OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support]) 334OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support])
334OPTION_DEFAULT_ON([imagemagick],[don't compile with ImageMagick image support]) 335OPTION_DEFAULT_ON([imagemagick],[don't compile with ImageMagick image support])
335 336
@@ -2407,6 +2408,7 @@ if test "${opsys}" != "mingw32"; then
2407 AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.]) 2408 AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.])
2408 GTK_OBJ=emacsgtkfixed.o 2409 GTK_OBJ=emacsgtkfixed.o
2409 gtk_term_header=gtkutil.h 2410 gtk_term_header=gtkutil.h
2411 USE_CAIRO=yes
2410 USE_GTK_TOOLKIT="GTK3" 2412 USE_GTK_TOOLKIT="GTK3"
2411 if test "x$ac_enable_gtk_deprecation_warnings" = x; then 2413 if test "x$ac_enable_gtk_deprecation_warnings" = x; then
2412 AC_DEFINE([GDK_DISABLE_DEPRECATION_WARNINGS], [1], 2414 AC_DEFINE([GDK_DISABLE_DEPRECATION_WARNINGS], [1],
@@ -3075,6 +3077,25 @@ AC_SUBST(LIBOTF_LIBS)
3075AC_SUBST(M17N_FLT_CFLAGS) 3077AC_SUBST(M17N_FLT_CFLAGS)
3076AC_SUBST(M17N_FLT_LIBS) 3078AC_SUBST(M17N_FLT_LIBS)
3077 3079
3080USE_CAIRO=no
3081if test "${HAVE_X11}" = "yes"; then
3082 if test "${with_cairo}" != "no"; then
3083 CAIRO_REQUIRED=1.12.0
3084 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
3085 PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
3086 if test $USE_CAIRO = yes; then
3087 AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
3088 else
3089 AC_MSG_ERROR([cairo requested but not found.])
3090 fi
3091
3092 CFLAGS="$CFLAGS $CAIRO_CFLAGS"
3093 LIBS="$LIBS $CAIRO_LIBS"
3094 AC_SUBST(CAIRO_CFLAGS)
3095 AC_SUBST(CAIRO_LIBS)
3096 fi
3097fi
3098
3078### Use -lXpm if available, unless '--with-xpm=no'. 3099### Use -lXpm if available, unless '--with-xpm=no'.
3079### mingw32 doesn't use -lXpm, since it loads the library dynamically. 3100### mingw32 doesn't use -lXpm, since it loads the library dynamically.
3080### In the Cygwin-w32 build, we need to use /usr/include/noX/X11/xpm.h 3101### In the Cygwin-w32 build, we need to use /usr/include/noX/X11/xpm.h
@@ -4009,8 +4030,8 @@ OLDCFLAGS="$CFLAGS"
4009OLDLIBS="$LIBS" 4030OLDLIBS="$LIBS"
4010CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS" 4031CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS"
4011LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS" 4032LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS"
4012CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS" 4033CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS $CAIRO_CFLAGS"
4013LIBS="$LIBS $GFILENOTIFY_LIBS" 4034LIBS="$LIBS $GFILENOTIFY_LIBS $CAIRO_LIBS"
4014AC_MSG_CHECKING([whether GLib is linked in]) 4035AC_MSG_CHECKING([whether GLib is linked in])
4015AC_LINK_IFELSE([AC_LANG_PROGRAM( 4036AC_LINK_IFELSE([AC_LANG_PROGRAM(
4016 [[#include <glib.h> 4037 [[#include <glib.h>
@@ -4776,7 +4797,9 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then
4776 XMENU_OBJ=xmenu.o 4797 XMENU_OBJ=xmenu.o
4777 XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o" 4798 XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o"
4778 FONT_OBJ=xfont.o 4799 FONT_OBJ=xfont.o
4779 if test "$HAVE_XFT" = "yes"; then 4800 if test "$USE_CAIRO" = "yes"; then
4801 FONT_OBJ="ftfont.o ftcrfont.o"
4802 elif test "$HAVE_XFT" = "yes"; then
4780 FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o" 4803 FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o"
4781 elif test "$HAVE_FREETYPE" = "yes"; then 4804 elif test "$HAVE_FREETYPE" = "yes"; then
4782 FONT_OBJ="$FONT_OBJ ftfont.o ftxfont.o" 4805 FONT_OBJ="$FONT_OBJ ftfont.o ftxfont.o"
@@ -5142,6 +5165,7 @@ echo " Does Emacs use -ltiff? ${HAVE_TIFF}"
5142echo " Does Emacs use a gif library? ${HAVE_GIF} $LIBGIF" 5165echo " Does Emacs use a gif library? ${HAVE_GIF} $LIBGIF"
5143echo " Does Emacs use a png library? ${HAVE_PNG} $LIBPNG" 5166echo " Does Emacs use a png library? ${HAVE_PNG} $LIBPNG"
5144echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}" 5167echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
5168echo " Does Emacs use cairo? ${USE_CAIRO}"
5145echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}" 5169echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}"
5146 5170
5147echo " Does Emacs support sound? ${HAVE_SOUND}" 5171echo " Does Emacs support sound? ${HAVE_SOUND}"
diff --git a/lisp/ChangeLog.17 b/lisp/ChangeLog.17
index a40f8f3d67a..2408ad2d832 100644
--- a/lisp/ChangeLog.17
+++ b/lisp/ChangeLog.17
@@ -1750,6 +1750,12 @@
1750 1750
17512015-02-11 Martin Rudalics <rudalics@gmx.at> 17512015-02-11 Martin Rudalics <rudalics@gmx.at>
1752 1752
17532015-02-11 Jan Djärv <jan.h.d@swipnet.se>
1754
1755 * version.el (emacs-version): Add cairo version.
1756
17572015-02-11 Martin Rudalics <rudalics@gmx.at>
1758
1753 * frame.el (toggle-frame-maximized, toggle-frame-fullscreen): 1759 * frame.el (toggle-frame-maximized, toggle-frame-fullscreen):
1754 Rename frame parameter `maximized' to `fullscreen-restore'. 1760 Rename frame parameter `maximized' to `fullscreen-restore'.
1755 Restore fullwidth/-height after fullboth state. Update doc-strings. 1761 Restore fullwidth/-height after fullboth state. Update doc-strings.
diff --git a/lisp/version.el b/lisp/version.el
index 1837cbf0a85..b8555cbb2f5 100644
--- a/lisp/version.el
+++ b/lisp/version.el
@@ -56,8 +56,8 @@ to the system configuration; look at `system-configuration' instead."
56 (interactive "P") 56 (interactive "P")
57 (let ((version-string 57 (let ((version-string
58 (format (if (not (called-interactively-p 'interactive)) 58 (format (if (not (called-interactively-p 'interactive))
59 "GNU Emacs %s (%s%s%s)\n of %s on %s" 59 "GNU Emacs %s (%s%s%s%s)\n of %s on %s"
60 "GNU Emacs %s (%s%s%s) of %s on %s") 60 "GNU Emacs %s (%s%s%s%s) of %s on %s")
61 emacs-version 61 emacs-version
62 system-configuration 62 system-configuration
63 (cond ((featurep 'motif) 63 (cond ((featurep 'motif)
@@ -68,6 +68,9 @@ to the system configuration; look at `system-configuration' instead."
68 ((featurep 'ns) 68 ((featurep 'ns)
69 (format ", NS %s" ns-version-string)) 69 (format ", NS %s" ns-version-string))
70 (t "")) 70 (t ""))
71 (if (featurep 'cairo)
72 (format ", cairo version %s" cairo-version-string)
73 "")
71 (if (and (boundp 'x-toolkit-scroll-bars) 74 (if (and (boundp 'x-toolkit-scroll-bars)
72 (memq x-toolkit-scroll-bars '(xaw xaw3d))) 75 (memq x-toolkit-scroll-bars '(xaw xaw3d)))
73 (format ", %s scroll bars" 76 (format ", %s scroll bars"
diff --git a/lwlib/ChangeLog.1 b/lwlib/ChangeLog.1
index e5dfed2342a..2e317dd2f66 100644
--- a/lwlib/ChangeLog.1
+++ b/lwlib/ChangeLog.1
@@ -1,3 +1,6 @@
12015-04-03 Jan Djärv <jan.h.d@swipnet.se>
2
3 * Makefile.in (CAIRO_CFLAGS): Add.
12015-03-18 Stefan Monnier <monnier@iro.umontreal.ca> 42015-03-18 Stefan Monnier <monnier@iro.umontreal.ca>
2 5
3 * xlwmenu.c (pop_up_menu): Remove debugging code. 6 * xlwmenu.c (pop_up_menu): Remove debugging code.
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
index 2fd59598e3e..cbc747cbbac 100644
--- a/lwlib/Makefile.in
+++ b/lwlib/Makefile.in
@@ -33,6 +33,7 @@ C_SWITCH_MACHINE=@C_SWITCH_MACHINE@
33PROFILING_CFLAGS = @PROFILING_CFLAGS@ 33PROFILING_CFLAGS = @PROFILING_CFLAGS@
34WARN_CFLAGS = `echo @WARN_CFLAGS@ | sed 's/ -Wwrite-strings//'` 34WARN_CFLAGS = `echo @WARN_CFLAGS@ | sed 's/ -Wwrite-strings//'`
35WERROR_CFLAGS = @WERROR_CFLAGS@ 35WERROR_CFLAGS = @WERROR_CFLAGS@
36CAIRO_CFLAGS= @CAIRO_CFLAGS@
36 37
37CC=@CC@ 38CC=@CC@
38CFLAGS=@CFLAGS@ 39CFLAGS=@CFLAGS@
@@ -88,6 +89,7 @@ endif
88ALL_CFLAGS= $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ 89ALL_CFLAGS= $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
89 $(C_SWITCH_MACHINE) $(DEPFLAGS) \ 90 $(C_SWITCH_MACHINE) $(DEPFLAGS) \
90 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(PROFILING_CFLAGS) $(CFLAGS) \ 91 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(PROFILING_CFLAGS) $(CFLAGS) \
92 $(CAIRO_CFLAGS) \
91 -Demacs -I../src \ 93 -Demacs -I../src \
92 -I$(srcdir) -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib 94 -I$(srcdir) -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib
93 95
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index 328f7982e6b..8057b6e75d6 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -1,9 +1,51 @@
12015-04-26 Jan Djärv <jan.h.d@swipnet.se>
2
3 * image.c (xcolor_to_argb32): New function.
4 (get_spec_bg_or_alpha_as_argb): Call xcolor_to_argb32.
5 (pbm_load, png_load_body, jpeg_load_body, gif_load): Only use
6 XImagePtr if ! USE_CAIRO.
7 (pbm_load): Add cairo support.
8
92015-04-12 Jan Djärv <jan.h.d@swipnet.se>
10
11 * xterm.c (x_draw_image_glyph_string): Added missing USE_CAIRO.
12 (x_free_cr_resources): Renamed from x_prepare_for_xlibdraw.
13 (x_cr_draw_frame, x_cr_export_frames, x_shift_glyphs_for_insert)
14 (x_free_frame_resources): Rename x_prepare_for_xlibdraw to
15 x_free_cr_resources.
16
17 * image.c (get_spec_bg_or_alpha_as_argb)
18 (create_cairo_image_surface): New functions when USE_CAIRO.
19 (xpm_load): Call the above functions. Handle XPM without mask
20 when USE_CAIRO.
21 (png_load_body): Handle USE_CAIRO case.
22 (png_load): Remove USE_CAIRO specific fuction, modify png_load_body
23 instead.
24 (jpeg_load_body): Call create_cairo_image_surface.
25 (gif_load, svg_load_image): Handle specified background, call
26 create_cairo_image_surface.
27
282015-04-11 Jan Djärv <jan.h.d@swipnet.se>
29
30 * image.c (jpeg_load_body): Create cairo image surface if USE_CAIRO.
31 (tiff_load): Create cairo image surface if USE_CAIRO.
32 (gif_load): Ditto.
33
12015-04-06 Koichi Arakawa <arakawa@pp.iij4u.or.jp> (tiny change) 342015-04-06 Koichi Arakawa <arakawa@pp.iij4u.or.jp> (tiny change)
2 35
3 * w32proc.c (w32_executable_type): Look for the DLL name in the 36 * w32proc.c (w32_executable_type): Look for the DLL name in the
4 correct section. This avoids segfaults with some executables. 37 correct section. This avoids segfaults with some executables.
5 (Bug#20264) 38 (Bug#20264)
6 39
402015-04-05 Jan Djärv <jan.h.d@swipnet.se>
41
42 * image.c: #undef COLOR_TABLE_SUPPORT when USE_CAIRO.
43 (x_clear_image): Free cr_data and cr_data2 if set.
44 (xpm_load): Assign data to cr_data2.
45 (svg_load_image): Convert from GdkPixbuf to CAIRO_FORMAT_ARGB32.
46
47 * dispextern.h (struct image): add cr_data2 if cairo.
48
72015-04-04 Jan Djärv <jan.h.d@swipnet.se> 492015-04-04 Jan Djärv <jan.h.d@swipnet.se>
8 50
9 * xselect.c (x_reply_selection_request) 51 * xselect.c (x_reply_selection_request)
@@ -15,8 +57,17 @@
15 57
162015-04-03 Jan Djärv <jan.h.d@swipnet.se> 582015-04-03 Jan Djärv <jan.h.d@swipnet.se>
17 59
60 * image.c (prepare_image_for_display): Don't load if USE_CAIRO.
61 (x_clear_image): If USE_CAIRO, also free possible img->ximg->obdata and
62 don't return early.
63 (ALLOC_XPM_COLORS): Don't define when USE_CAIRO.
64 (xpm_load): Convert simple Xpms (32 bit ZPixmap) to CAIRO_FORMAT_ARGB32
65 and create a surface.
66
18 * xterm.c (handle_one_xevent): Always redraw tool tips on 67 * xterm.c (handle_one_xevent): Always redraw tool tips on
19 MapNotify. Update tool tip frame sizes on ConfigureNotify. 68 MapNotify. Update tool tip frame sizes on ConfigureNotify.
69 (x_update_begin): Don't create any surface for non-visible
70 tip frames, the geometry may be wrong.
20 71
212015-03-31 Eli Zaretskii <eliz@gnu.org> 722015-03-31 Eli Zaretskii <eliz@gnu.org>
22 73
@@ -559,6 +610,191 @@
559 DEFINE_LISP_SYMBOL_BEGIN / DEFINE_LISP_SYMBOL_END. All uses changed. 610 DEFINE_LISP_SYMBOL_BEGIN / DEFINE_LISP_SYMBOL_END. All uses changed.
560 (DEFINE_NONNIL_Q_SYMBOL_MACROS): New macro, defaulting to true. 611 (DEFINE_NONNIL_Q_SYMBOL_MACROS): New macro, defaulting to true.
561 612
6132015-02-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
614
615 * ftcrfont.c (ftcrfont_draw): Don't flush when drawing to screen.
616
6172015-02-17 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
618
619 * xterm.c [USE_CAIRO]: Include math.h.
620 (enum corners) [USE_CAIRO]: New enum.
621 (x_erase_corners_for_relief) [USE_CAIRO]: New function.
622 (x_draw_relief_rect) [USE_CAIRO]: Use it. If box width is larger
623 than 1, draw the outermost line using the black relief.
624
6252015-02-16 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
626
627 * gtkutil.c (xg_page_setup_dialog, xg_get_page_setup, draw_page)
628 (xg_print_frames_dialog): Modernize k&r declarations.
629
630 * xfns.c (Fx_export_frames, Fx_page_setup_dialog, Fx_get_page_setup)
631 (Fx_print_frames_dialog): Modernize k&r declarations.
632
633 * xterm.c (x_draw_window_divider): Use x_fill_rectangle instead of
634 XFillRectangle.
635 (x_draw_horizontal_wave) [USE_CAIRO]: New function.
636 (x_draw_underwave) [USE_CAIRO]: Use it.
637 (x_gc_get_ext_data, x_extension_initialize, x_begin_cr_clip)
638 (x_end_cr_clip, x_set_cr_source_with_gc_foreground)
639 (x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap)
640 (x_cr_destroy_fringe_bitmap, x_cr_draw_frame, x_cr_accumulate_data)
641 (x_cr_destroy, x_cr_export_frames, x_prepare_for_xlibdraw)
642 (x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle)
643 (x_draw_rectangle, x_clear_window, x_fill_trapezoid_for_relief)
644 (x_clear_area): Modernize k&r declarations.
645 (x_cr_draw_image, x_fill_rectangle, x_draw_rectangle)
646 (x_fill_trapezoid_for_relief): Use int instead of unsigned int for
647 width and height args.
648 (x_draw_stretch_glyph_string): Call x_reset_clip_rectangles instead
649 of XSetClipMask.
650 (x_draw_relief_rect) [USE_CAIRO]: Reset clipping.
651 (x_fill_trapezoid_for_relief): Remove unnecessary cairo_close_path.
652
6532015-02-14 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
654
655 * fringe.c (init_fringe_bitmap) [USE_CAIRO]: Adjust bitmap data for
656 cairo image surface.
657
658 * xterm.c (x_cr_define_fringe_bitmap): Call cairo_surface_mark_dirty.
659
6602015-02-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
661 Jan Djärv <jan.h.d@swipnet.se>
662
663 * xterm.h: Add include of cairo header files.
664 (x_bitmap_record): Add img if cairo.
665 (x_gc_ext_data): New struct for cairo.
666 (x_display_info): Add ext_codes for cairo.
667 (x_output): Add cr_context and cr_surface for cairo.
668 (x_clear_area): Change arguments from Display*/Window to frame pointer.
669 (x_query_color, x_begin_cr_clip, x_end_cr_clip)
670 (x_set_cr_source_with_gc_foreground, x_set_cr_source_with_gc_background)
671 (x_cr_draw_frame, x_cr_export_frames): Declare.
672
673 * xterm.c (x_clear_area1, x_prepare_for_xlibdraw)
674 (x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle)
675 (x_draw_rectangle, x_fill_trapezoid_for_relief, x_clear_window)
676 (x_gc_get_ext_data, x_extension_initialize, x_cr_accumulate_data):
677 Declare.
678 (FRAME_CR_CONTEXT, FRAME_CR_SURFACE): New macros.
679 (max_fringe_bmp, fringe_bmp): New variables.
680 (x_gc_get_ext_data, x_extension_initialize)
681 (x_cr_destroy_surface, x_begin_cr_clip, x_end_cr_clip)
682 (x_set_cr_source_with_gc_foreground)
683 (x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap)
684 (x_cr_destroy_fringe_bitmap, x_cr_draw_image, x_cr_draw_frame)
685 (x_cr_accumulate_data, x_cr_destroy, x_cr_export_frames)
686 (x_prepare_for_xlibdraw, x_set_clip_rectangles)
687 (x_reset_clip_rectangles, x_fill_rectangle, x_draw_rectangle)
688 (x_clear_window, x_fill_trapezoid_for_relief): New functions.
689 (x_update_begin): Create cairo surface if needed.
690 (x_draw_vertical_window_border): Call x_fill_rectangle for cairo.
691 (x_update_end): Paint cairo drawing surface to xlib surface.
692 (x_clear_under_internal_border, x_after_update_window_line): Adjust
693 arguments to x_clear_area.
694 (x_draw_fringe_bitmap): Call x_fill_rectangle. Get GC values and
695 call x_cr_draw_image for cairo. Call x_reset_clip_rectangles instead
696 of XSetClipMask.
697 (x_set_glyph_string_clipping)
698 (x_set_glyph_string_clipping_exactly): Use x_set_clip_rectangles
699 instead of XSetClipRectangles.
700 (x_clear_glyph_string_rect, x_draw_glyph_string_background): Use
701 x_fill_rectangle instead of XFillRectangle.
702 (x_draw_glyph_string_foreground)
703 (x_draw_composite_glyph_string_foreground)
704 (x_draw_glyphless_glyph_string_foreground): Use x_draw_rectangle instead
705 of XDrawRectangle.
706 (x_draw_relief_rect): Add code for USE_CAIRO.
707 Call x_reset_clip_rectangles instead of XSetClipMask.
708 (x_draw_box_rect): x_set_clip_rectangles instead of XSetClipRectangles,
709 x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles
710 instead of XSetClipMask.
711 (x_draw_image_foreground, x_draw_image_foreground_1):
712 x_draw_rectangle instead of XDrawRectangle.
713 (x_draw_glyph_string_bg_rect): x_fill_rectangle instead of
714 XFillRectangle.
715 (x_draw_image_glyph_string): If img has cr_data, use it as
716 a cairo surface.
717 (x_draw_stretch_glyph_string): x_set_clip_rectangles instead of
718 XSetClipRectangles, x_fill_rectangle instead of XFillRectangle.
719 (x_draw_glyph_string): x_fill_rectangle instead of XFillRectangle.,
720 x_reset_clip_rectangles instead of XSetClipMask.
721 (x_shift_glyphs_for_insert): Call x_prepare_for_xlibdraw.
722 (x_clear_area1): New function that calls XClearArea.
723 (x_clear_area): Takes frame as parameter, calls x_clear_area1 for
724 non-cairo.
725 (x_clear_frame): x_clear_window instead of XClearWindow.
726 (x_scroll_run): Set frame garbaged if cairo.
727 (XTmouse_position): Initialize *part to 0.
728 (x_scroll_bar_create): Adjust arguments to x_clear_area.
729 (x_scroll_bar_set_handle): x_clear_area1 instead of x_clear_area,
730 x_fill_rectangle instead of XFillRectangle.
731 (XTset_vertical_scroll_bar, XTset_horizontal_scroll_bar): Adjust
732 arguments to x_clear_area.
733 (x_scroll_bar_expose): x_draw_rectangle instead of XDrawRectangle.
734 (handle_one_xevent): Adjust arguments to x_clear_area.
735 Destroy cairo surface for frame if ConfigureNotify.
736 (x_clip_to_row): x_set_clip_rectangles instead of XSetClipRectangles.
737 (x_draw_hollow_cursor): x_draw_rectangle instead of XDrawRectangle,
738 x_reset_clip_rectangles instead of XSetClipMask.
739 (x_draw_bar_cursor): x_fill_rectangle instead of XFillRectangle,
740 x_reset_clip_rectangles instead of XSetClipMask.
741 (x_clear_frame_area): Adjust arguments to x_clear_area.
742 (x_free_frame_resources): Call x_prepare_for_xlibdraw.
743 (x_term_init): Call x_extension_initialize if cairo.
744 (x_redisplay_interface): Add x_cr_define_fringe_bitmap,
745 x_cr_destroy_fringe_bitmap for cairo.
746 (x_initialize): Call x_cr_init_fringe for cairo.
747
748 * xfns.c: New section Printing.
749 (x-export-frames, x-page-setup-dialog, x-get-page-setup)
750 (x-print-frames-dialog): New printing functions.
751 (Fx_create_frame, x_create_tip_frame): Register ftcrfont if
752 cairo.
753 (syms_of_xfns): Defsym Qorientation, Qtop_margin, Qbottom_margin,
754 Qportrait, Qlandscape, Qreverse_portrait, Qreverse_landscape).
755 (syms_of_xfns): Provide cairo and defvar cairo-version-string.
756 defsubr Sx_page_setup_dialog, Sx_get_page_setup, Sx_print_frames_dialog.
757
758 * image.c: Add defined (USE_CAIRO) for PNG.
759 Add !defined USE_CAIRO for W32 PNG code.
760 (x_clear_image): If cairo, destroy the surface in cr_data.
761 (png_load): Add new cairo compatible implementation.
762 (lookup_image_type): Add defined (USE_CAIRO) for define png_type.
763
764 * gtkutil.h (xg_page_setup_dialog, xg_get_page_setup)
765 (xg_print_frames_dialog): Declare.
766
767 * gtkutil.c (xg_clear_under_internal_border)
768 (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Only
769 queue_draw if not cairo. Change args to x_clear_area.
770 (xg_get_font): Use Qftcr when using cairo, Qxft otherwise.
771 (xg_page_setup_dialog, xg_get_page_setup, draw_page)
772 (xg_print_frames_dialog): New functions for printing.
773
774 * ftfont.h (ftfont_open2, ftfont_info_size): Declare.
775
776 * ftfont.c (ftfont_info_size); New global variable.
777 (ftfont_open2): New extern function almost the same as old ftfont_open,
778 but takes the font_object as argument.
779 (ftfont_open): Build font object and call ftfont_open2.
780
781 * ftcrfont.c: New font driver for cairo, based on the ftfont driver.
782
783 * fringe.c (x_cr_init_fringe): New function name that shares code
784 with w32_init_fringe.
785
786 * font.h (ftcrfont_driver, syms_of_ftcrfont): Declare
787
788 * font.c (syms_of_font): Call syms_of_ftcrfont for cairo.
789
790 * dispextern.h (struct image): Add cr_data for cairo.
791 (x_cr_init_fringe): Declare.
792
793 * Makefile.in (CAIRO_CFLAGS, CAIRO_LIBS): New variables.
794 (FONT_OBJ): Add comment about ftcrfont.
795 (ALL_CFLAGS): Add CAIRO_CFLAGS.
796 (LIBES): Add CAIRO_LIBS.
797
5622015-02-11 Martin Rudalics <rudalics@gmx.at> 7982015-02-11 Martin Rudalics <rudalics@gmx.at>
563 799
564 * w32term.c (w32_read_socket): In SIZE_MAXIMIZED and 800 * w32term.c (w32_read_socket): In SIZE_MAXIMIZED and
diff --git a/src/Makefile.in b/src/Makefile.in
index 57417fcb3fa..d0df3260356 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -218,6 +218,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
218RSVG_LIBS= @RSVG_LIBS@ 218RSVG_LIBS= @RSVG_LIBS@
219RSVG_CFLAGS= @RSVG_CFLAGS@ 219RSVG_CFLAGS= @RSVG_CFLAGS@
220 220
221CAIRO_LIBS= @CAIRO_LIBS@
222CAIRO_CFLAGS= @CAIRO_CFLAGS@
223
221IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ 224IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@
222IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ 225IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
223 226
@@ -273,6 +276,7 @@ W32_RES_LINK=@W32_RES_LINK@
273## Empty if !HAVE_X_WINDOWS 276## Empty if !HAVE_X_WINDOWS
274## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT 277## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT
275## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE 278## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
279## ftfont.o ftcrfont.o if USE_CAIRO
276## else xfont.o 280## else xfont.o
277FONT_OBJ=@FONT_OBJ@ 281FONT_OBJ=@FONT_OBJ@
278 282
@@ -350,7 +354,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
350 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ 354 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
351 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 355 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
352 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 356 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
353 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \ 357 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
354 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS) 358 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
355ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) 359ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
356 360
@@ -456,7 +460,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
456 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ 460 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
457 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 461 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
458 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ 462 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
459 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 463 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
460 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 464 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
461 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 465 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
462 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ 466 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
diff --git a/src/dispextern.h b/src/dispextern.h
index 329572eda22..d9d4d2300fa 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2941,6 +2941,10 @@ struct image
2941 /* Pixmaps of the image. */ 2941 /* Pixmaps of the image. */
2942 Pixmap pixmap, mask; 2942 Pixmap pixmap, mask;
2943 2943
2944#ifdef USE_CAIRO
2945 void *cr_data;
2946 void *cr_data2;
2947#endif
2944#ifdef HAVE_X_WINDOWS 2948#ifdef HAVE_X_WINDOWS
2945 /* X images of the image, corresponding to the above Pixmaps. 2949 /* X images of the image, corresponding to the above Pixmaps.
2946 Non-NULL means it and its Pixmap counterpart may be out of sync 2950 Non-NULL means it and its Pixmap counterpart may be out of sync
@@ -3302,6 +3306,9 @@ bool update_window_fringes (struct window *, bool);
3302void w32_init_fringe (struct redisplay_interface *); 3306void w32_init_fringe (struct redisplay_interface *);
3303void w32_reset_fringes (void); 3307void w32_reset_fringes (void);
3304#endif 3308#endif
3309#ifdef USE_CAIRO
3310void x_cr_init_fringe (struct redisplay_interface *);
3311#endif
3305 3312
3306extern unsigned row_hash (struct glyph_row *); 3313extern unsigned row_hash (struct glyph_row *);
3307 3314
diff --git a/src/font.c b/src/font.c
index 2ade45fd73a..2ccfd15d436 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5280,11 +5280,15 @@ EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5280#ifdef HAVE_FREETYPE 5280#ifdef HAVE_FREETYPE
5281 syms_of_ftfont (); 5281 syms_of_ftfont ();
5282#ifdef HAVE_X_WINDOWS 5282#ifdef HAVE_X_WINDOWS
5283#ifdef USE_CAIRO
5284 syms_of_ftcrfont ();
5285#else
5283 syms_of_xfont (); 5286 syms_of_xfont ();
5284 syms_of_ftxfont (); 5287 syms_of_ftxfont ();
5285#ifdef HAVE_XFT 5288#ifdef HAVE_XFT
5286 syms_of_xftfont (); 5289 syms_of_xftfont ();
5287#endif /* HAVE_XFT */ 5290#endif /* HAVE_XFT */
5291#endif /* not USE_CAIRO */
5288#endif /* HAVE_X_WINDOWS */ 5292#endif /* HAVE_X_WINDOWS */
5289#else /* not HAVE_FREETYPE */ 5293#else /* not HAVE_FREETYPE */
5290#ifdef HAVE_X_WINDOWS 5294#ifdef HAVE_X_WINDOWS
diff --git a/src/font.h b/src/font.h
index efc184eef77..43e67e98c06 100644
--- a/src/font.h
+++ b/src/font.h
@@ -844,6 +844,10 @@ extern struct font_driver nsfont_driver;
844extern void syms_of_nsfont (void); 844extern void syms_of_nsfont (void);
845extern void syms_of_macfont (void); 845extern void syms_of_macfont (void);
846#endif /* HAVE_NS */ 846#endif /* HAVE_NS */
847#ifdef USE_CAIRO
848extern struct font_driver ftcrfont_driver;
849extern void syms_of_ftcrfont (void);
850#endif
847 851
848#ifndef FONT_DEBUG 852#ifndef FONT_DEBUG
849#define FONT_DEBUG 853#define FONT_DEBUG
diff --git a/src/fringe.c b/src/fringe.c
index 5e5ec60a48f..fcc5207b062 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1405,6 +1405,21 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
1405 unsigned short *bits = fb->bits; 1405 unsigned short *bits = fb->bits;
1406 int j; 1406 int j;
1407 1407
1408#ifdef USE_CAIRO
1409 for (j = 0; j < fb->height; j++)
1410 {
1411 unsigned short b = *bits;
1412#ifdef WORDS_BIGENDIAN
1413 *bits++ = (b << (16 - fb->width));
1414#else
1415 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1416 | (swap_nibble[(b>>4) & 0xf] << 8)
1417 | (swap_nibble[(b>>8) & 0xf] << 4)
1418 | (swap_nibble[(b>>12) & 0xf]));
1419 *bits++ = (b >> (16 - fb->width));
1420#endif
1421 }
1422#else /* not USE_CAIRO */
1408 if (fb->width <= 8) 1423 if (fb->width <= 8)
1409 { 1424 {
1410 unsigned char *cbits = (unsigned char *)fb->bits; 1425 unsigned char *cbits = (unsigned char *)fb->bits;
@@ -1433,6 +1448,7 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
1433 *bits++ = b; 1448 *bits++ = b;
1434 } 1449 }
1435 } 1450 }
1451#endif /* not USE_CAIRO */
1436#endif /* HAVE_X_WINDOWS */ 1452#endif /* HAVE_X_WINDOWS */
1437 1453
1438 } 1454 }
@@ -1731,10 +1747,14 @@ init_fringe (void)
1731 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces); 1747 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
1732} 1748}
1733 1749
1734#ifdef HAVE_NTGUI 1750#if defined (HAVE_NTGUI) || defined (USE_CAIRO)
1735 1751
1736void 1752void
1753#ifdef HAVE_NTGUI
1737w32_init_fringe (struct redisplay_interface *rif) 1754w32_init_fringe (struct redisplay_interface *rif)
1755#else
1756x_cr_init_fringe (struct redisplay_interface *rif)
1757#endif
1738{ 1758{
1739 int bt; 1759 int bt;
1740 1760
@@ -1747,7 +1767,9 @@ w32_init_fringe (struct redisplay_interface *rif)
1747 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width); 1767 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1748 } 1768 }
1749} 1769}
1770#endif
1750 1771
1772#ifdef HAVE_NTGUI
1751void 1773void
1752w32_reset_fringes (void) 1774w32_reset_fringes (void)
1753{ 1775{
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
new file mode 100644
index 00000000000..fc4e6dae873
--- /dev/null
+++ b/src/ftcrfont.c
@@ -0,0 +1,320 @@
1/* ftcrfont.c -- FreeType font driver on cairo.
2 Copyright (C) 2015 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19
20#include <config.h>
21#include <stdio.h>
22#include <cairo-ft.h>
23
24#include "lisp.h"
25#include "dispextern.h"
26#include "xterm.h"
27#include "frame.h"
28#include "blockinput.h"
29#include "character.h"
30#include "charset.h"
31#include "fontset.h"
32#include "font.h"
33#include "ftfont.h"
34
35/* FTCR font driver. */
36
37/* The actual structure for ftcr font that can be casted to struct
38 font. */
39
40struct ftcrfont_info
41{
42 struct font font;
43 /* The following six members must be here in this order to be
44 compatible with struct ftfont_info (in ftfont.c). */
45#ifdef HAVE_LIBOTF
46 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
47 OTF *otf;
48#endif /* HAVE_LIBOTF */
49 FT_Size ft_size;
50 int index;
51 FT_Matrix matrix;
52
53 cairo_font_face_t *cr_font_face;
54 /* To prevent cairo from cluttering the activated FT_Size maintained
55 in ftfont.c, we activate this special FT_Size before drawing. */
56 FT_Size ft_size_draw;
57 /* Font metrics cache. */
58 struct font_metrics **metrics;
59 short metrics_nrows;
60};
61
62#define METRICS_NCOLS_PER_ROW (128)
63
64enum metrics_status
65 {
66 METRICS_INVALID = -1, /* metrics entry is invalid */
67 };
68
69#define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
70#define METRICS_SET_STATUS(metrics, status) \
71 ((metrics)->ascent = 0, (metrics)->descent = (status))
72
73/* Prototypes for helper function. */
74static int ftcrfont_glyph_extents (struct font *, unsigned,
75 struct font_metrics *);
76
77/* Prototypes for font-driver methods. */
78static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object);
79static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object);
80static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int);
81static void ftcrfont_close (struct font *);
82static void ftcrfont_text_extents (struct font *, unsigned *, int,
83 struct font_metrics *);
84static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool);
85
86struct font_driver ftcrfont_driver;
87
88static int
89ftcrfont_glyph_extents (struct font *font,
90 unsigned glyph,
91 struct font_metrics *metrics)
92{
93 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
94 int row, col;
95 struct font_metrics *cache;
96
97 row = glyph / METRICS_NCOLS_PER_ROW;
98 col = glyph % METRICS_NCOLS_PER_ROW;
99 if (row >= ftcrfont_info->metrics_nrows)
100 {
101 ftcrfont_info->metrics =
102 xrealloc (ftcrfont_info->metrics,
103 sizeof (struct font_metrics *) * (row + 1));
104 bzero (ftcrfont_info->metrics + ftcrfont_info->metrics_nrows,
105 (sizeof (struct font_metrics *)
106 * (row + 1 - ftcrfont_info->metrics_nrows)));
107 ftcrfont_info->metrics_nrows = row + 1;
108 }
109 if (ftcrfont_info->metrics[row] == NULL)
110 {
111 struct font_metrics *new;
112 int i;
113
114 new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
115 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
116 METRICS_SET_STATUS (new + i, METRICS_INVALID);
117 ftcrfont_info->metrics[row] = new;
118 }
119 cache = ftcrfont_info->metrics[row] + col;
120
121 if (METRICS_STATUS (cache) == METRICS_INVALID)
122 ftfont_driver.text_extents (font, &glyph, 1, cache);
123
124 if (metrics)
125 *metrics = *cache;
126
127 return cache->width;
128}
129
130static Lisp_Object
131ftcrfont_list (struct frame *f, Lisp_Object spec)
132{
133 Lisp_Object list = ftfont_driver.list (f, spec), tail;
134
135 for (tail = list; CONSP (tail); tail = XCDR (tail))
136 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
137 return list;
138}
139
140static Lisp_Object
141ftcrfont_match (struct frame *f, Lisp_Object spec)
142{
143 Lisp_Object entity = ftfont_driver.match (f, spec);
144
145 if (VECTORP (entity))
146 ASET (entity, FONT_TYPE_INDEX, Qftcr);
147 return entity;
148}
149
150extern FT_Face ftfont_get_ft_face (Lisp_Object);
151
152static Lisp_Object
153ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
154{
155 Lisp_Object font_object;
156 struct font *font;
157 struct ftcrfont_info *ftcrfont_info;
158 FT_Face ft_face;
159 FT_UInt size;
160
161 block_input ();
162 size = XINT (AREF (entity, FONT_SIZE_INDEX));
163 if (size == 0)
164 size = pixel_size;
165 font_object = font_build_object (VECSIZE (struct ftcrfont_info),
166 Qftcr, entity, size);
167 font_object = ftfont_open2 (f, entity, pixel_size, font_object);
168 if (NILP (font_object)) return Qnil;
169
170 font = XFONT_OBJECT (font_object);
171 font->driver = &ftcrfont_driver;
172 ftcrfont_info = (struct ftcrfont_info *) font;
173 ft_face = ftcrfont_info->ft_size->face;
174 FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
175 FT_Activate_Size (ftcrfont_info->ft_size_draw);
176 FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
177 ftcrfont_info->cr_font_face =
178 cairo_ft_font_face_create_for_ft_face (ft_face, 0);
179 ftcrfont_info->metrics = NULL;
180 ftcrfont_info->metrics_nrows = 0;
181 unblock_input ();
182
183 return font_object;
184}
185
186static void
187ftcrfont_close (struct font *font)
188{
189 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
190 int i;
191
192 block_input ();
193 for (i = 0; i < ftcrfont_info->metrics_nrows; i++)
194 if (ftcrfont_info->metrics[i])
195 xfree (ftcrfont_info->metrics[i]);
196 if (ftcrfont_info->metrics)
197 xfree (ftcrfont_info->metrics);
198 FT_Done_Size (ftcrfont_info->ft_size_draw);
199 cairo_font_face_destroy (ftcrfont_info->cr_font_face);
200 unblock_input ();
201
202 ftfont_driver.close (font);
203}
204
205static void
206ftcrfont_text_extents (struct font *font,
207 unsigned *code,
208 int nglyphs,
209 struct font_metrics *metrics)
210{
211 int width, i;
212
213 block_input ();
214 width = ftcrfont_glyph_extents (font, code[0], metrics);
215 for (i = 1; i < nglyphs; i++)
216 {
217 struct font_metrics m;
218 int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL);
219
220 if (metrics)
221 {
222 if (width + m.lbearing < metrics->lbearing)
223 metrics->lbearing = width + m.lbearing;
224 if (width + m.rbearing > metrics->rbearing)
225 metrics->rbearing = width + m.rbearing;
226 if (m.ascent > metrics->ascent)
227 metrics->ascent = m.ascent;
228 if (m.descent > metrics->descent)
229 metrics->descent = m.descent;
230 }
231 width += w;
232 }
233 unblock_input ();
234
235 if (metrics)
236 metrics->width = width;
237}
238
239static int
240ftcrfont_draw (struct glyph_string *s,
241 int from, int to, int x, int y, bool with_background)
242{
243 struct frame *f = s->f;
244 struct face *face = s->face;
245 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) s->font;
246 cairo_t *cr;
247 cairo_glyph_t *glyphs;
248 cairo_surface_t *surface;
249 cairo_surface_type_t surface_type;
250 int len = to - from;
251 int i;
252
253 block_input ();
254
255 cr = x_begin_cr_clip (f, s->gc);
256
257 if (with_background)
258 {
259 x_set_cr_source_with_gc_background (f, s->gc);
260 cairo_rectangle (cr, x, y - FONT_BASE (face->font),
261 s->width, FONT_HEIGHT (face->font));
262 cairo_fill (cr);
263 }
264
265 glyphs = alloca (sizeof (cairo_glyph_t) * len);
266 for (i = 0; i < len; i++)
267 {
268 unsigned code = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
269 | XCHAR2B_BYTE2 (s->char2b + from + i));
270
271 glyphs[i].index = code;
272 glyphs[i].x = x;
273 glyphs[i].y = y;
274 x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, code, NULL));
275 }
276
277 x_set_cr_source_with_gc_foreground (f, s->gc);
278 cairo_set_font_face (cr, ftcrfont_info->cr_font_face);
279 cairo_set_font_size (cr, s->font->pixel_size);
280 /* cairo_set_font_matrix */
281 /* cairo_set_font_options */
282
283 FT_Activate_Size (ftcrfont_info->ft_size_draw);
284 cairo_show_glyphs (cr, glyphs, len);
285 surface = cairo_get_target (cr);
286 /* XXX: It used to be necessary to flush when exporting. It might
287 be the case that this is no longer necessary. */
288 surface_type = cairo_surface_get_type (surface);
289 if (surface_type != CAIRO_SURFACE_TYPE_XLIB
290 && (surface_type != CAIRO_SURFACE_TYPE_IMAGE
291 || cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32))
292 cairo_surface_flush (surface);
293
294 x_end_cr_clip (f);
295
296 unblock_input ();
297
298 return len;
299}
300
301
302
303void
304syms_of_ftcrfont (void)
305{
306 if (ftfont_info_size != offsetof (struct ftcrfont_info, cr_font_face))
307 abort ();
308
309 DEFSYM (Qftcr, "ftcr");
310
311 ftcrfont_driver = ftfont_driver;
312 ftcrfont_driver.type = Qftcr;
313 ftcrfont_driver.list = ftcrfont_list;
314 ftcrfont_driver.match = ftcrfont_match;
315 ftcrfont_driver.open = ftcrfont_open;
316 ftcrfont_driver.close = ftcrfont_close;
317 ftcrfont_driver.text_extents = ftcrfont_text_extents;
318 ftcrfont_driver.draw = ftcrfont_draw;
319 register_font_driver (&ftcrfont_driver, NULL);
320}
diff --git a/src/ftfont.c b/src/ftfont.c
index 26740c263ce..f19933c7ef2 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -67,6 +67,8 @@ struct ftfont_info
67 FT_Matrix matrix; 67 FT_Matrix matrix;
68}; 68};
69 69
70size_t ftfont_info_size = sizeof (struct ftfont_info);
71
70enum ftfont_cache_for 72enum ftfont_cache_for
71 { 73 {
72 FTFONT_CACHE_FOR_FACE, 74 FTFONT_CACHE_FOR_FACE,
@@ -1161,8 +1163,11 @@ ftfont_list_family (struct frame *f)
1161} 1163}
1162 1164
1163 1165
1164static Lisp_Object 1166Lisp_Object
1165ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) 1167ftfont_open2 (struct frame *f,
1168 Lisp_Object entity,
1169 int pixel_size,
1170 Lisp_Object font_object)
1166{ 1171{
1167 struct ftfont_info *ftfont_info; 1172 struct ftfont_info *ftfont_info;
1168 struct font *font; 1173 struct font *font;
@@ -1170,7 +1175,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1170 FT_Face ft_face; 1175 FT_Face ft_face;
1171 FT_Size ft_size; 1176 FT_Size ft_size;
1172 FT_UInt size; 1177 FT_UInt size;
1173 Lisp_Object val, filename, idx, cache, font_object; 1178 Lisp_Object val, filename, idx, cache;
1174 bool scalable; 1179 bool scalable;
1175 int spacing; 1180 int spacing;
1176 int i; 1181 int i;
@@ -1210,8 +1215,6 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1210 return Qnil; 1215 return Qnil;
1211 } 1216 }
1212 1217
1213 font_object = font_build_object (VECSIZE (struct ftfont_info),
1214 Qfreetype, entity, size);
1215 ASET (font_object, FONT_FILE_INDEX, filename); 1218 ASET (font_object, FONT_FILE_INDEX, filename);
1216 font = XFONT_OBJECT (font_object); 1219 font = XFONT_OBJECT (font_object);
1217 ftfont_info = (struct ftfont_info *) font; 1220 ftfont_info = (struct ftfont_info *) font;
@@ -1294,6 +1297,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1294 return font_object; 1297 return font_object;
1295} 1298}
1296 1299
1300static Lisp_Object
1301ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1302{
1303 Lisp_Object font_object;
1304 FT_UInt size;
1305 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1306 if (size == 0)
1307 size = pixel_size;
1308 font_object = font_build_object (VECSIZE (struct ftfont_info),
1309 Qfreetype, entity, size);
1310 return ftfont_open2 (f, entity, pixel_size, font_object);
1311}
1312
1297static void 1313static void
1298ftfont_close (struct font *font) 1314ftfont_close (struct font *font)
1299{ 1315{
diff --git a/src/ftfont.h b/src/ftfont.h
index 210b634c094..0cfa0ae3e33 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -37,6 +37,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
37#endif /* HAVE_LIBOTF */ 37#endif /* HAVE_LIBOTF */
38 38
39extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); 39extern FcCharSet *ftfont_get_fc_charset (Lisp_Object);
40extern Lisp_Object ftfont_open2 (struct frame *f,
41 Lisp_Object entity,
42 int pixel_size,
43 Lisp_Object font_object);
44extern size_t ftfont_info_size;
40 45
41#endif /* EMACS_FTFONT_H */ 46#endif /* EMACS_FTFONT_H */
42 47
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 61bc5ee245a..a4b4331c039 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -847,22 +847,23 @@ xg_clear_under_internal_border (struct frame *f)
847{ 847{
848 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) 848 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
849 { 849 {
850#ifndef USE_CAIRO
850 GtkWidget *wfixed = f->output_data.x->edit_widget; 851 GtkWidget *wfixed = f->output_data.x->edit_widget;
851 852
852 gtk_widget_queue_draw (wfixed); 853 gtk_widget_queue_draw (wfixed);
853 gdk_window_process_all_updates (); 854 gdk_window_process_all_updates ();
854 855#endif
855 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, 856 x_clear_area (f, 0, 0,
856 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); 857 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
857 858
858 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, 859 x_clear_area (f, 0, 0,
859 FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); 860 FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
860 861
861 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 862 x_clear_area (f, 0,
862 FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f), 863 FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
863 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); 864 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
864 865
865 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 866 x_clear_area (f,
866 FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f), 867 FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
867 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); 868 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
868 } 869 }
@@ -2141,12 +2142,18 @@ xg_get_font (struct frame *f, const char *default_name)
2141 PangoWeight weight = pango_font_description_get_weight (desc); 2142 PangoWeight weight = pango_font_description_get_weight (desc);
2142 PangoStyle style = pango_font_description_get_style (desc); 2143 PangoStyle style = pango_font_description_get_style (desc);
2143 2144
2145#ifdef USE_CAIRO
2146#define FONT_TYPE_WANTED (Qftcr)
2147#else
2148#define FONT_TYPE_WANTED (Qxft)
2149#endif
2144 font = CALLN (Ffont_spec, 2150 font = CALLN (Ffont_spec,
2145 QCname, build_string (name), 2151 QCname, build_string (name),
2146 QCsize, make_float (pango_units_to_double (size)), 2152 QCsize, make_float (pango_units_to_double (size)),
2147 QCweight, XG_WEIGHT_TO_SYMBOL (weight), 2153 QCweight, XG_WEIGHT_TO_SYMBOL (weight),
2148 QCslant, XG_STYLE_TO_SYMBOL (style), 2154 QCslant, XG_STYLE_TO_SYMBOL (style),
2149 QCtype, Qxft); 2155 QCtype,
2156 FONT_TYPE_WANTED);
2150 2157
2151 pango_font_description_free (desc); 2158 pango_font_description_free (desc);
2152 dupstring (&x_last_font_name, name); 2159 dupstring (&x_last_font_name, name);
@@ -3806,8 +3813,10 @@ xg_update_scrollbar_pos (struct frame *f,
3806 gtk_widget_show_all (wparent); 3813 gtk_widget_show_all (wparent);
3807 gtk_widget_set_size_request (wscroll, width, height); 3814 gtk_widget_set_size_request (wscroll, width, height);
3808 } 3815 }
3816#ifndef USE_CAIRO
3809 gtk_widget_queue_draw (wfixed); 3817 gtk_widget_queue_draw (wfixed);
3810 gdk_window_process_all_updates (); 3818 gdk_window_process_all_updates ();
3819#endif
3811 if (oldx != -1 && oldw > 0 && oldh > 0) 3820 if (oldx != -1 && oldw > 0 && oldh > 0)
3812 { 3821 {
3813 /* Clear under old scroll bar position. This must be done after 3822 /* Clear under old scroll bar position. This must be done after
@@ -3815,8 +3824,7 @@ xg_update_scrollbar_pos (struct frame *f,
3815 above. */ 3824 above. */
3816 oldw += (scale - 1) * oldw; 3825 oldw += (scale - 1) * oldw;
3817 oldx -= (scale - 1) * oldw; 3826 oldx -= (scale - 1) * oldw;
3818 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3827 x_clear_area (f, oldx, oldy, oldw, oldh);
3819 oldx, oldy, oldw, oldh);
3820 } 3828 }
3821 3829
3822 /* GTK does not redraw until the main loop is entered again, but 3830 /* GTK does not redraw until the main loop is entered again, but
@@ -3882,7 +3890,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
3882 /* Clear under old scroll bar position. This must be done after 3890 /* Clear under old scroll bar position. This must be done after
3883 the gtk_widget_queue_draw and gdk_window_process_all_updates 3891 the gtk_widget_queue_draw and gdk_window_process_all_updates
3884 above. */ 3892 above. */
3885 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3893 x_clear_area (f,
3886 oldx, oldy, oldw, oldh); 3894 oldx, oldy, oldw, oldh);
3887 3895
3888 /* GTK does not redraw until the main loop is entered again, but 3896 /* GTK does not redraw until the main loop is entered again, but
@@ -4059,6 +4067,108 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event)
4059 return retval; 4067 return retval;
4060} 4068}
4061 4069
4070
4071/***********************************************************************
4072 Printing
4073 ***********************************************************************/
4074#ifdef USE_CAIRO
4075static GtkPrintSettings *print_settings = NULL;
4076static GtkPageSetup *page_setup = NULL;
4077
4078void
4079xg_page_setup_dialog (void)
4080{
4081 GtkPageSetup *new_page_setup = NULL;
4082
4083 if (print_settings == NULL)
4084 print_settings = gtk_print_settings_new ();
4085 new_page_setup = gtk_print_run_page_setup_dialog (NULL, page_setup,
4086 print_settings);
4087 if (page_setup)
4088 g_object_unref (page_setup);
4089 page_setup = new_page_setup;
4090}
4091
4092Lisp_Object
4093xg_get_page_setup (void)
4094{
4095 Lisp_Object result, orientation_symbol;
4096 GtkPageOrientation orientation;
4097
4098 if (page_setup == NULL)
4099 page_setup = gtk_page_setup_new ();
4100 result = list4 (Fcons (Qleft_margin,
4101 make_float (gtk_page_setup_get_left_margin (page_setup,
4102 GTK_UNIT_POINTS))),
4103 Fcons (Qright_margin,
4104 make_float (gtk_page_setup_get_right_margin (page_setup,
4105 GTK_UNIT_POINTS))),
4106 Fcons (Qtop_margin,
4107 make_float (gtk_page_setup_get_top_margin (page_setup,
4108 GTK_UNIT_POINTS))),
4109 Fcons (Qbottom_margin,
4110 make_float (gtk_page_setup_get_bottom_margin (page_setup,
4111 GTK_UNIT_POINTS))));
4112 result = Fcons (Fcons (Qheight,
4113 make_float (gtk_page_setup_get_page_height (page_setup,
4114 GTK_UNIT_POINTS))),
4115 result);
4116 result = Fcons (Fcons (Qwidth,
4117 make_float (gtk_page_setup_get_page_width (page_setup,
4118 GTK_UNIT_POINTS))),
4119 result);
4120 orientation = gtk_page_setup_get_orientation (page_setup);
4121 if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT)
4122 orientation_symbol = Qportrait;
4123 else if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE)
4124 orientation_symbol = Qlandscape;
4125 else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
4126 orientation_symbol = Qreverse_portrait;
4127 else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
4128 orientation_symbol = Qreverse_landscape;
4129 result = Fcons (Fcons (Qorientation, orientation_symbol), result);
4130
4131 return result;
4132}
4133
4134static void
4135draw_page (GtkPrintOperation *operation, GtkPrintContext *context,
4136 gint page_nr, gpointer user_data)
4137{
4138 Lisp_Object frames = *((Lisp_Object *) user_data);
4139 struct frame *f = XFRAME (Fnth (make_number (page_nr), frames));
4140 cairo_t *cr = gtk_print_context_get_cairo_context (context);
4141
4142 x_cr_draw_frame (cr, f);
4143}
4144
4145void
4146xg_print_frames_dialog (Lisp_Object frames)
4147{
4148 GtkPrintOperation *print;
4149 GtkPrintOperationResult res;
4150
4151 print = gtk_print_operation_new ();
4152 if (print_settings != NULL)
4153 gtk_print_operation_set_print_settings (print, print_settings);
4154 if (page_setup != NULL)
4155 gtk_print_operation_set_default_page_setup (print, page_setup);
4156 gtk_print_operation_set_n_pages (print, XINT (Flength (frames)));
4157 g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), &frames);
4158 res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
4159 NULL, NULL);
4160 if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
4161 {
4162 if (print_settings != NULL)
4163 g_object_unref (print_settings);
4164 print_settings =
4165 g_object_ref (gtk_print_operation_get_print_settings (print));
4166 }
4167 g_object_unref (print);
4168}
4169
4170#endif /* USE_CAIRO */
4171
4062 4172
4063 4173
4064/*********************************************************************** 4174/***********************************************************************
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 0ac49ca7db5..34338db58fb 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -180,6 +180,12 @@ extern bool xg_prepare_tooltip (struct frame *f,
180extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); 180extern void xg_show_tooltip (struct frame *f, int root_x, int root_y);
181extern bool xg_hide_tooltip (struct frame *f); 181extern bool xg_hide_tooltip (struct frame *f);
182 182
183#ifdef USE_CAIRO
184extern void xg_page_setup_dialog (void);
185extern Lisp_Object xg_get_page_setup (void);
186extern void xg_print_frames_dialog (Lisp_Object);
187#endif
188
183/* Mark all callback data that are Lisp_object:s during GC. */ 189/* Mark all callback data that are Lisp_object:s during GC. */
184extern void xg_mark_data (void); 190extern void xg_mark_data (void);
185 191
diff --git a/src/image.c b/src/image.c
index d7f48bd81dd..87029bfa1b0 100644
--- a/src/image.c
+++ b/src/image.c
@@ -88,6 +88,10 @@ typedef struct w32_bitmap_record Bitmap_Record;
88 88
89#endif /* HAVE_NTGUI */ 89#endif /* HAVE_NTGUI */
90 90
91#ifdef USE_CAIRO
92#undef COLOR_TABLE_SUPPORT
93#endif
94
91#ifdef HAVE_NS 95#ifdef HAVE_NS
92#undef COLOR_TABLE_SUPPORT 96#undef COLOR_TABLE_SUPPORT
93 97
@@ -514,7 +518,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
514 518
515#endif /* HAVE_X_WINDOWS */ 519#endif /* HAVE_X_WINDOWS */
516 520
517
518/*********************************************************************** 521/***********************************************************************
519 Image types 522 Image types
520 ***********************************************************************/ 523 ***********************************************************************/
@@ -1019,6 +1022,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
1019 /* We're about to display IMG, so set its timestamp to `now'. */ 1022 /* We're about to display IMG, so set its timestamp to `now'. */
1020 img->timestamp = current_timespec (); 1023 img->timestamp = current_timespec ();
1021 1024
1025#ifndef USE_CAIRO
1022 /* If IMG doesn't have a pixmap yet, load it now, using the image 1026 /* If IMG doesn't have a pixmap yet, load it now, using the image
1023 type dependent loader function. */ 1027 type dependent loader function. */
1024 if (img->pixmap == NO_PIXMAP && !img->load_failed_p) 1028 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
@@ -1032,6 +1036,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
1032 unblock_input (); 1036 unblock_input ();
1033 } 1037 }
1034#endif 1038#endif
1039#endif
1035} 1040}
1036 1041
1037 1042
@@ -1078,6 +1083,54 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
1078 return ascent; 1083 return ascent;
1079} 1084}
1080 1085
1086#ifdef USE_CAIRO
1087static uint32_t
1088xcolor_to_argb32 (XColor xc)
1089{
1090 return (0xff << 24) | ((xc.red / 256) << 16)
1091 | ((xc.green / 256) << 8) | (xc.blue / 256);
1092}
1093
1094static uint32_t
1095get_spec_bg_or_alpha_as_argb (struct image *img,
1096 struct frame *f)
1097{
1098 uint32_t bgcolor = 0;
1099 XColor xbgcolor;
1100 Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
1101
1102 if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
1103 FRAME_X_COLORMAP (f),
1104 SSDATA (bg),
1105 &xbgcolor))
1106 bgcolor = xcolor_to_argb32 (xbgcolor);
1107
1108 return bgcolor;
1109}
1110
1111static void
1112create_cairo_image_surface (struct image *img,
1113 unsigned char *data,
1114 int width,
1115 int height)
1116{
1117 cairo_surface_t *surface;
1118 cairo_format_t format = CAIRO_FORMAT_ARGB32;
1119 int stride = cairo_format_stride_for_width (format, width);
1120 surface = cairo_image_surface_create_for_data (data,
1121 format,
1122 width,
1123 height,
1124 stride);
1125 img->width = width;
1126 img->height = height;
1127 img->cr_data = surface;
1128 img->cr_data2 = data;
1129 img->pixmap = 0;
1130}
1131#endif
1132
1133
1081 1134
1082/* Image background colors. */ 1135/* Image background colors. */
1083 1136
@@ -1299,6 +1352,11 @@ static void
1299x_clear_image (struct frame *f, struct image *img) 1352x_clear_image (struct frame *f, struct image *img)
1300{ 1353{
1301 block_input (); 1354 block_input ();
1355#ifdef USE_CAIRO
1356 if (img->cr_data)
1357 cairo_surface_destroy ((cairo_surface_t *)img->cr_data);
1358 if (img->cr_data2) xfree (img->cr_data2);
1359#endif
1302 x_clear_image_1 (f, img, 1360 x_clear_image_1 (f, img,
1303 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS); 1361 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
1304 unblock_input (); 1362 unblock_input ();
@@ -3154,9 +3212,11 @@ static struct image_type xpm_type =
3154 color allocation failures more gracefully than the ones on the XPM 3212 color allocation failures more gracefully than the ones on the XPM
3155 lib. */ 3213 lib. */
3156 3214
3215#ifndef USE_CAIRO
3157#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure 3216#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3158#define ALLOC_XPM_COLORS 3217#define ALLOC_XPM_COLORS
3159#endif 3218#endif
3219#endif /* USE_CAIRO */
3160#endif /* HAVE_X_WINDOWS */ 3220#endif /* HAVE_X_WINDOWS */
3161 3221
3162#ifdef ALLOC_XPM_COLORS 3222#ifdef ALLOC_XPM_COLORS
@@ -3617,6 +3677,44 @@ xpm_load (struct frame *f, struct image *img)
3617#endif /* HAVE_NTGUI */ 3677#endif /* HAVE_NTGUI */
3618 } 3678 }
3619 3679
3680#ifdef USE_CAIRO
3681 // Load very specific Xpm:s.
3682 if (rc == XpmSuccess
3683 && img->ximg->format == ZPixmap
3684 && img->ximg->bits_per_pixel == 32
3685 && (! img->mask_img || img->mask_img->bits_per_pixel == 1))
3686 {
3687 int width = img->ximg->width;
3688 int height = img->ximg->height;
3689 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
3690 int i;
3691 uint32_t *od = (uint32_t *)data;
3692 uint32_t *id = (uint32_t *)img->ximg->data;
3693 unsigned char *mid = img->mask_img ? img->mask_img->data : 0;
3694 uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
3695
3696 for (i = 0; i < height; ++i)
3697 {
3698 int k;
3699 for (k = 0; k < width; ++k)
3700 {
3701 int idx = i * img->ximg->bytes_per_line/4 + k;
3702 int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0;
3703 int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1;
3704
3705 if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha
3706 else od[idx] = bgcolor;
3707 }
3708 }
3709
3710 create_cairo_image_surface (img, data, width, height);
3711 }
3712 else
3713 {
3714 rc = XpmFileInvalid;
3715 x_clear_image (f, img);
3716 }
3717#else
3620#ifdef HAVE_X_WINDOWS 3718#ifdef HAVE_X_WINDOWS
3621 if (rc == XpmSuccess) 3719 if (rc == XpmSuccess)
3622 { 3720 {
@@ -3642,6 +3740,7 @@ xpm_load (struct frame *f, struct image *img)
3642 } 3740 }
3643 } 3741 }
3644#endif 3742#endif
3743#endif /* ! USE_CAIRO */
3645 3744
3646 if (rc == XpmSuccess) 3745 if (rc == XpmSuccess)
3647 { 3746 {
@@ -5148,12 +5247,17 @@ pbm_load (struct frame *f, struct image *img)
5148 bool raw_p; 5247 bool raw_p;
5149 int x, y; 5248 int x, y;
5150 int width, height, max_color_idx = 0; 5249 int width, height, max_color_idx = 0;
5151 XImagePtr ximg;
5152 Lisp_Object file, specified_file; 5250 Lisp_Object file, specified_file;
5153 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; 5251 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5154 unsigned char *contents = NULL; 5252 unsigned char *contents = NULL;
5155 unsigned char *end, *p; 5253 unsigned char *end, *p;
5156 ptrdiff_t size; 5254 ptrdiff_t size;
5255#ifdef USE_CAIRO
5256 unsigned char *data = 0;
5257 uint32_t *dataptr;
5258#else
5259 XImagePtr ximg;
5260#endif
5157 5261
5158 specified_file = image_spec_value (img->spec, QCfile, NULL); 5262 specified_file = image_spec_value (img->spec, QCfile, NULL);
5159 5263
@@ -5235,6 +5339,11 @@ pbm_load (struct frame *f, struct image *img)
5235 width = pbm_scan_number (&p, end); 5339 width = pbm_scan_number (&p, end);
5236 height = pbm_scan_number (&p, end); 5340 height = pbm_scan_number (&p, end);
5237 5341
5342#ifdef USE_CAIRO
5343 data = (unsigned char *) xmalloc (width * height * 4);
5344 dataptr = (uint32_t *) data;
5345#endif
5346
5238 if (type != PBM_MONO) 5347 if (type != PBM_MONO)
5239 { 5348 {
5240 max_color_idx = pbm_scan_number (&p, end); 5349 max_color_idx = pbm_scan_number (&p, end);
@@ -5251,8 +5360,10 @@ pbm_load (struct frame *f, struct image *img)
5251 goto error; 5360 goto error;
5252 } 5361 }
5253 5362
5363#ifndef USE_CAIRO
5254 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 5364 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5255 goto error; 5365 goto error;
5366#endif
5256 5367
5257 /* Initialize the color hash table. */ 5368 /* Initialize the color hash table. */
5258 init_color_table (); 5369 init_color_table ();
@@ -5263,12 +5374,34 @@ pbm_load (struct frame *f, struct image *img)
5263 struct image_keyword fmt[PBM_LAST]; 5374 struct image_keyword fmt[PBM_LAST];
5264 unsigned long fg = FRAME_FOREGROUND_PIXEL (f); 5375 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5265 unsigned long bg = FRAME_BACKGROUND_PIXEL (f); 5376 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5266 5377#ifdef USE_CAIRO
5378 XColor xfg, xbg;
5379 int fga32, bga32;
5380#endif
5267 /* Parse the image specification. */ 5381 /* Parse the image specification. */
5268 memcpy (fmt, pbm_format, sizeof fmt); 5382 memcpy (fmt, pbm_format, sizeof fmt);
5269 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm); 5383 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5270 5384
5271 /* Get foreground and background colors, maybe allocate colors. */ 5385 /* Get foreground and background colors, maybe allocate colors. */
5386#ifdef USE_CAIRO
5387 if (! fmt[PBM_FOREGROUND].count
5388 || ! STRINGP (fmt[PBM_FOREGROUND].value)
5389 || ! x_defined_color (f, SSDATA (fmt[PBM_FOREGROUND].value), &xfg, 0))
5390 {
5391 xfg.pixel = fg;
5392 x_query_color (f, &xfg);
5393 }
5394 fga32 = xcolor_to_argb32 (xfg);
5395
5396 if (! fmt[PBM_BACKGROUND].count
5397 || ! STRINGP (fmt[PBM_BACKGROUND].value)
5398 || ! x_defined_color (f, SSDATA (fmt[PBM_BACKGROUND].value), &xbg, 0))
5399 {
5400 xbg.pixel = bg;
5401 x_query_color (f, &xbg);
5402 }
5403 bga32 = xcolor_to_argb32 (xbg);
5404#else
5272 if (fmt[PBM_FOREGROUND].count 5405 if (fmt[PBM_FOREGROUND].count
5273 && STRINGP (fmt[PBM_FOREGROUND].value)) 5406 && STRINGP (fmt[PBM_FOREGROUND].value))
5274 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg); 5407 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
@@ -5279,6 +5412,7 @@ pbm_load (struct frame *f, struct image *img)
5279 img->background = bg; 5412 img->background = bg;
5280 img->background_valid = 1; 5413 img->background_valid = 1;
5281 } 5414 }
5415#endif
5282 5416
5283 for (y = 0; y < height; ++y) 5417 for (y = 0; y < height; ++y)
5284 for (x = 0; x < width; ++x) 5418 for (x = 0; x < width; ++x)
@@ -5289,7 +5423,11 @@ pbm_load (struct frame *f, struct image *img)
5289 { 5423 {
5290 if (p >= end) 5424 if (p >= end)
5291 { 5425 {
5426#ifdef USE_CAIRO
5427 xfree (data);
5428#else
5292 x_destroy_x_image (ximg); 5429 x_destroy_x_image (ximg);
5430#endif
5293 x_clear_image (f, img); 5431 x_clear_image (f, img);
5294 image_error ("Invalid image size in image `%s'", 5432 image_error ("Invalid image size in image `%s'",
5295 img->spec, Qnil); 5433 img->spec, Qnil);
@@ -5303,7 +5441,11 @@ pbm_load (struct frame *f, struct image *img)
5303 else 5441 else
5304 g = pbm_scan_number (&p, end); 5442 g = pbm_scan_number (&p, end);
5305 5443
5444#ifdef USE_CAIRO
5445 *dataptr++ = g ? fga32 : bga32;
5446#else
5306 XPutPixel (ximg, x, y, g ? fg : bg); 5447 XPutPixel (ximg, x, y, g ? fg : bg);
5448#endif
5307 } 5449 }
5308 } 5450 }
5309 else 5451 else
@@ -5316,7 +5458,11 @@ pbm_load (struct frame *f, struct image *img)
5316 5458
5317 if (raw_p && p + expected_size > end) 5459 if (raw_p && p + expected_size > end)
5318 { 5460 {
5461#ifdef USE_CAIRO
5462 xfree (data);
5463#else
5319 x_destroy_x_image (ximg); 5464 x_destroy_x_image (ximg);
5465#endif
5320 x_clear_image (f, img); 5466 x_clear_image (f, img);
5321 image_error ("Invalid image size in image `%s'", 5467 image_error ("Invalid image size in image `%s'",
5322 img->spec, Qnil); 5468 img->spec, Qnil);
@@ -5357,18 +5503,29 @@ pbm_load (struct frame *f, struct image *img)
5357 5503
5358 if (r < 0 || g < 0 || b < 0) 5504 if (r < 0 || g < 0 || b < 0)
5359 { 5505 {
5506#ifdef USE_CAIRO
5507 xfree (data);
5508#else
5360 x_destroy_x_image (ximg); 5509 x_destroy_x_image (ximg);
5510#endif
5361 image_error ("Invalid pixel value in image `%s'", 5511 image_error ("Invalid pixel value in image `%s'",
5362 img->spec, Qnil); 5512 img->spec, Qnil);
5363 goto error; 5513 goto error;
5364 } 5514 }
5365 5515
5516#ifdef USE_CAIRO
5517 r = (double) r * 255 / max_color_idx;
5518 g = (double) g * 255 / max_color_idx;
5519 b = (double) b * 255 / max_color_idx;
5520 *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
5521#else
5366 /* RGB values are now in the range 0..max_color_idx. 5522 /* RGB values are now in the range 0..max_color_idx.
5367 Scale this to the range 0..0xffff supported by X. */ 5523 Scale this to the range 0..0xffff supported by X. */
5368 r = (double) r * 65535 / max_color_idx; 5524 r = (double) r * 65535 / max_color_idx;
5369 g = (double) g * 65535 / max_color_idx; 5525 g = (double) g * 65535 / max_color_idx;
5370 b = (double) b * 65535 / max_color_idx; 5526 b = (double) b * 65535 / max_color_idx;
5371 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); 5527 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5528#endif
5372 } 5529 }
5373 } 5530 }
5374 5531
@@ -5384,12 +5541,16 @@ pbm_load (struct frame *f, struct image *img)
5384 5541
5385 /* Maybe fill in the background field while we have ximg handy. */ 5542 /* Maybe fill in the background field while we have ximg handy. */
5386 5543
5544#ifdef USE_CAIRO
5545 create_cairo_image_surface (img, data, width, height);
5546#else
5387 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 5547 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5388 /* Casting avoids a GCC warning. */ 5548 /* Casting avoids a GCC warning. */
5389 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 5549 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5390 5550
5391 /* Put ximg into the image. */ 5551 /* Put ximg into the image. */
5392 image_put_x_image (f, img, ximg, 0); 5552 image_put_x_image (f, img, ximg, 0);
5553#endif
5393 5554
5394 /* X and W32 versions did it here, MAC version above. ++kfs 5555 /* X and W32 versions did it here, MAC version above. ++kfs
5395 img->width = width; 5556 img->width = width;
@@ -5404,7 +5565,7 @@ pbm_load (struct frame *f, struct image *img)
5404 PNG 5565 PNG
5405 ***********************************************************************/ 5566 ***********************************************************************/
5406 5567
5407#if defined (HAVE_PNG) || defined (HAVE_NS) 5568#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
5408 5569
5409/* Function prototypes. */ 5570/* Function prototypes. */
5410 5571
@@ -5478,7 +5639,7 @@ png_image_p (Lisp_Object object)
5478 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; 5639 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5479} 5640}
5480 5641
5481#endif /* HAVE_PNG || HAVE_NS */ 5642#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
5482 5643
5483 5644
5484#if defined HAVE_PNG && !defined HAVE_NS 5645#if defined HAVE_PNG && !defined HAVE_NS
@@ -5713,7 +5874,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5713 Lisp_Object specified_data; 5874 Lisp_Object specified_data;
5714 int x, y; 5875 int x, y;
5715 ptrdiff_t i; 5876 ptrdiff_t i;
5716 XImagePtr ximg, mask_img = NULL;
5717 png_struct *png_ptr; 5877 png_struct *png_ptr;
5718 png_info *info_ptr = NULL, *end_info = NULL; 5878 png_info *info_ptr = NULL, *end_info = NULL;
5719 FILE *fp = NULL; 5879 FILE *fp = NULL;
@@ -5727,6 +5887,13 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5727 bool transparent_p; 5887 bool transparent_p;
5728 struct png_memory_storage tbr; /* Data to be read */ 5888 struct png_memory_storage tbr; /* Data to be read */
5729 5889
5890#ifdef USE_CAIRO
5891 unsigned char *data = 0;
5892 uint32_t *dataptr;
5893#else
5894 XImagePtr ximg, mask_img = NULL;
5895#endif
5896
5730 /* Find out what file to load. */ 5897 /* Find out what file to load. */
5731 specified_file = image_spec_value (img->spec, QCfile, NULL); 5898 specified_file = image_spec_value (img->spec, QCfile, NULL);
5732 specified_data = image_spec_value (img->spec, QCdata, NULL); 5899 specified_data = image_spec_value (img->spec, QCdata, NULL);
@@ -5847,10 +6014,12 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5847 goto error; 6014 goto error;
5848 } 6015 }
5849 6016
6017#ifndef USE_CAIRO
5850 /* Create the X image and pixmap now, so that the work below can be 6018 /* Create the X image and pixmap now, so that the work below can be
5851 omitted if the image is too large for X. */ 6019 omitted if the image is too large for X. */
5852 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 6020 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5853 goto error; 6021 goto error;
6022#endif
5854 6023
5855 /* If image contains simply transparency data, we prefer to 6024 /* If image contains simply transparency data, we prefer to
5856 construct a clipping mask. */ 6025 construct a clipping mask. */
@@ -5937,6 +6106,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5937 c->fp = NULL; 6106 c->fp = NULL;
5938 } 6107 }
5939 6108
6109#ifdef USE_CAIRO
6110 data = (unsigned char *) xmalloc (width * height * 4);
6111 dataptr = (uint32_t *) data;
6112#else
5940 /* Create an image and pixmap serving as mask if the PNG image 6113 /* Create an image and pixmap serving as mask if the PNG image
5941 contains an alpha channel. */ 6114 contains an alpha channel. */
5942 if (channels == 4 6115 if (channels == 4
@@ -5948,6 +6121,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5948 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); 6121 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
5949 goto error; 6122 goto error;
5950 } 6123 }
6124#endif
5951 6125
5952 /* Fill the X image and mask from PNG data. */ 6126 /* Fill the X image and mask from PNG data. */
5953 init_color_table (); 6127 init_color_table ();
@@ -5960,6 +6134,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5960 { 6134 {
5961 int r, g, b; 6135 int r, g, b;
5962 6136
6137#ifdef USE_CAIRO
6138 int a = 0xff;
6139 r = *p++;
6140 g = *p++;
6141 b = *p++;
6142 if (channels == 4) a = *p++;
6143 *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
6144#else
5963 r = *p++ << 8; 6145 r = *p++ << 8;
5964 g = *p++ << 8; 6146 g = *p++ << 8;
5965 b = *p++ << 8; 6147 b = *p++ << 8;
@@ -5986,6 +6168,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5986 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN); 6168 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
5987 ++p; 6169 ++p;
5988 } 6170 }
6171#endif
5989 } 6172 }
5990 } 6173 }
5991 6174
@@ -6015,6 +6198,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6015 img->width = width; 6198 img->width = width;
6016 img->height = height; 6199 img->height = height;
6017 6200
6201#ifdef USE_CAIRO
6202 create_cairo_image_surface (img, data, width, height);
6203#else
6018 /* Maybe fill in the background field while we have ximg handy. 6204 /* Maybe fill in the background field while we have ximg handy.
6019 Casting avoids a GCC warning. */ 6205 Casting avoids a GCC warning. */
6020 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6206 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
@@ -6031,6 +6217,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
6031 6217
6032 image_put_x_image (f, img, mask_img, 1); 6218 image_put_x_image (f, img, mask_img, 1);
6033 } 6219 }
6220#endif
6034 6221
6035 return 1; 6222 return 1;
6036} 6223}
@@ -6052,6 +6239,7 @@ png_load (struct frame *f, struct image *img)
6052 image_spec_value (img->spec, QCdata, NULL)); 6239 image_spec_value (img->spec, QCdata, NULL));
6053} 6240}
6054 6241
6242
6055#endif /* HAVE_NS */ 6243#endif /* HAVE_NS */
6056 6244
6057 6245
@@ -6463,9 +6651,12 @@ jpeg_load_body (struct frame *f, struct image *img,
6463 FILE * IF_LINT (volatile) fp = NULL; 6651 FILE * IF_LINT (volatile) fp = NULL;
6464 JSAMPARRAY buffer; 6652 JSAMPARRAY buffer;
6465 int row_stride, x, y; 6653 int row_stride, x, y;
6466 XImagePtr ximg = NULL;
6467 unsigned long *colors; 6654 unsigned long *colors;
6468 int width, height; 6655 int width, height;
6656 int i, ir, ig, ib;
6657#ifndef USE_CAIRO
6658 XImagePtr ximg = NULL;
6659#endif
6469 6660
6470 /* Open the JPEG file. */ 6661 /* Open the JPEG file. */
6471 specified_file = image_spec_value (img->spec, QCfile, NULL); 6662 specified_file = image_spec_value (img->spec, QCfile, NULL);
@@ -6525,8 +6716,9 @@ jpeg_load_body (struct frame *f, struct image *img,
6525 jpeg_destroy_decompress (&mgr->cinfo); 6716 jpeg_destroy_decompress (&mgr->cinfo);
6526 6717
6527 /* If we already have an XImage, free that. */ 6718 /* If we already have an XImage, free that. */
6719#ifndef USE_CAIRO
6528 x_destroy_x_image (ximg); 6720 x_destroy_x_image (ximg);
6529 6721#endif
6530 /* Free pixmap and colors. */ 6722 /* Free pixmap and colors. */
6531 x_clear_image (f, img); 6723 x_clear_image (f, img);
6532 return 0; 6724 return 0;
@@ -6560,12 +6752,14 @@ jpeg_load_body (struct frame *f, struct image *img,
6560 sys_longjmp (mgr->setjmp_buffer, 1); 6752 sys_longjmp (mgr->setjmp_buffer, 1);
6561 } 6753 }
6562 6754
6755#ifndef USE_CAIRO
6563 /* Create X image and pixmap. */ 6756 /* Create X image and pixmap. */
6564 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 6757 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
6565 { 6758 {
6566 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; 6759 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
6567 sys_longjmp (mgr->setjmp_buffer, 1); 6760 sys_longjmp (mgr->setjmp_buffer, 1);
6568 } 6761 }
6762#endif
6569 6763
6570 /* Allocate colors. When color quantization is used, 6764 /* Allocate colors. When color quantization is used,
6571 mgr->cinfo.actual_number_of_colors has been set with the number of 6765 mgr->cinfo.actual_number_of_colors has been set with the number of
@@ -6574,8 +6768,6 @@ jpeg_load_body (struct frame *f, struct image *img,
6574 No more than 255 colors will be generated. */ 6768 No more than 255 colors will be generated. */
6575 USE_SAFE_ALLOCA; 6769 USE_SAFE_ALLOCA;
6576 { 6770 {
6577 int i, ir, ig, ib;
6578
6579 if (mgr->cinfo.out_color_components > 2) 6771 if (mgr->cinfo.out_color_components > 2)
6580 ir = 0, ig = 1, ib = 2; 6772 ir = 0, ig = 1, ib = 2;
6581 else if (mgr->cinfo.out_color_components > 1) 6773 else if (mgr->cinfo.out_color_components > 1)
@@ -6583,6 +6775,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6583 else 6775 else
6584 ir = 0, ig = 0, ib = 0; 6776 ir = 0, ig = 0, ib = 0;
6585 6777
6778#ifndef CAIRO
6586 /* Use the color table mechanism because it handles colors that 6779 /* Use the color table mechanism because it handles colors that
6587 cannot be allocated nicely. Such colors will be replaced with 6780 cannot be allocated nicely. Such colors will be replaced with
6588 a default color, and we don't have to care about which colors 6781 a default color, and we don't have to care about which colors
@@ -6599,6 +6792,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6599 int b = mgr->cinfo.colormap[ib][i] << 8; 6792 int b = mgr->cinfo.colormap[ib][i] << 8;
6600 colors[i] = lookup_rgb_color (f, r, g, b); 6793 colors[i] = lookup_rgb_color (f, r, g, b);
6601 } 6794 }
6795#endif
6602 6796
6603#ifdef COLOR_TABLE_SUPPORT 6797#ifdef COLOR_TABLE_SUPPORT
6604 /* Remember those colors actually allocated. */ 6798 /* Remember those colors actually allocated. */
@@ -6611,12 +6805,36 @@ jpeg_load_body (struct frame *f, struct image *img,
6611 row_stride = width * mgr->cinfo.output_components; 6805 row_stride = width * mgr->cinfo.output_components;
6612 buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo, 6806 buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
6613 JPOOL_IMAGE, row_stride, 1); 6807 JPOOL_IMAGE, row_stride, 1);
6808#ifdef USE_CAIRO
6809 {
6810 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
6811 uint32_t *dataptr = (uint32_t *) data;
6812 int r, g, b;
6813
6814 for (y = 0; y < height; ++y)
6815 {
6816 jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
6817
6818 for (x = 0; x < width; ++x)
6819 {
6820 i = buffer[0][x];
6821 r = mgr->cinfo.colormap[ir][i];
6822 g = mgr->cinfo.colormap[ig][i];
6823 b = mgr->cinfo.colormap[ib][i];
6824 *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
6825 }
6826 }
6827
6828 create_cairo_image_surface (img, data, width, height);
6829 }
6830#else
6614 for (y = 0; y < height; ++y) 6831 for (y = 0; y < height; ++y)
6615 { 6832 {
6616 jpeg_read_scanlines (&mgr->cinfo, buffer, 1); 6833 jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
6617 for (x = 0; x < mgr->cinfo.output_width; ++x) 6834 for (x = 0; x < mgr->cinfo.output_width; ++x)
6618 XPutPixel (ximg, x, y, colors[buffer[0][x]]); 6835 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6619 } 6836 }
6837#endif
6620 6838
6621 /* Clean up. */ 6839 /* Clean up. */
6622 jpeg_finish_decompress (&mgr->cinfo); 6840 jpeg_finish_decompress (&mgr->cinfo);
@@ -6624,6 +6842,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6624 if (fp) 6842 if (fp)
6625 fclose (fp); 6843 fclose (fp);
6626 6844
6845#ifndef USE_CAIRO
6627 /* Maybe fill in the background field while we have ximg handy. */ 6846 /* Maybe fill in the background field while we have ximg handy. */
6628 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 6847 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6629 /* Casting avoids a GCC warning. */ 6848 /* Casting avoids a GCC warning. */
@@ -6631,6 +6850,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6631 6850
6632 /* Put ximg into the image. */ 6851 /* Put ximg into the image. */
6633 image_put_x_image (f, img, ximg, 0); 6852 image_put_x_image (f, img, ximg, 0);
6853#endif
6634 SAFE_FREE (); 6854 SAFE_FREE ();
6635 return 1; 6855 return 1;
6636} 6856}
@@ -7063,6 +7283,29 @@ tiff_load (struct frame *f, struct image *img)
7063 return 0; 7283 return 0;
7064 } 7284 }
7065 7285
7286#ifdef USE_CAIRO
7287 {
7288 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
7289 uint32_t *dataptr = (uint32_t *) data;
7290 int r, g, b, a;
7291
7292 for (y = 0; y < height; ++y)
7293 {
7294 uint32 *row = buf + (height - 1 - y) * width;
7295 for (x = 0; x < width; ++x)
7296 {
7297 uint32 abgr = row[x];
7298 int r = TIFFGetR (abgr);
7299 int g = TIFFGetG (abgr);
7300 int b = TIFFGetB (abgr);
7301 int a = TIFFGetA (abgr);
7302 *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
7303 }
7304 }
7305
7306 create_cairo_image_surface (img, data, width, height);
7307 }
7308#else
7066 /* Initialize the color table. */ 7309 /* Initialize the color table. */
7067 init_color_table (); 7310 init_color_table ();
7068 7311
@@ -7097,8 +7340,10 @@ tiff_load (struct frame *f, struct image *img)
7097 7340
7098 /* Put ximg into the image. */ 7341 /* Put ximg into the image. */
7099 image_put_x_image (f, img, ximg, 0); 7342 image_put_x_image (f, img, ximg, 0);
7100 xfree (buf);
7101 7343
7344#endif /* ! USE_CAIRO */
7345
7346 xfree (buf);
7102 return 1; 7347 return 1;
7103} 7348}
7104 7349
@@ -7348,7 +7593,6 @@ gif_load (struct frame *f, struct image *img)
7348{ 7593{
7349 Lisp_Object file; 7594 Lisp_Object file;
7350 int rc, width, height, x, y, i, j; 7595 int rc, width, height, x, y, i, j;
7351 XImagePtr ximg;
7352 ColorMapObject *gif_color_map; 7596 ColorMapObject *gif_color_map;
7353 unsigned long pixel_colors[256]; 7597 unsigned long pixel_colors[256];
7354 GifFileType *gif; 7598 GifFileType *gif;
@@ -7360,6 +7604,12 @@ gif_load (struct frame *f, struct image *img)
7360 EMACS_INT idx; 7604 EMACS_INT idx;
7361 int gif_err; 7605 int gif_err;
7362 7606
7607#ifdef USE_CAIRO
7608 unsigned char *data = 0;
7609#else
7610 XImagePtr ximg;
7611#endif
7612
7363 if (NILP (specified_data)) 7613 if (NILP (specified_data))
7364 { 7614 {
7365 file = x_find_image_file (specified_file); 7615 file = x_find_image_file (specified_file);
@@ -7488,6 +7738,25 @@ gif_load (struct frame *f, struct image *img)
7488 } 7738 }
7489 } 7739 }
7490 7740
7741#ifdef USE_CAIRO
7742 /* xzalloc so data is zero => transparent */
7743 data = (unsigned char *) xzalloc (width * height * 4);
7744 if (STRINGP (specified_bg))
7745 {
7746 XColor color;
7747 if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
7748 {
7749 uint32_t *dataptr = (uint32_t *)data;
7750 int r = color.red/256;
7751 int g = color.green/256;
7752 int b = color.blue/256;
7753
7754 for (y = 0; y < height; ++y)
7755 for (x = 0; x < width; ++x)
7756 *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
7757 }
7758 }
7759#else
7491 /* Create the X image and pixmap. */ 7760 /* Create the X image and pixmap. */
7492 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 7761 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
7493 { 7762 {
@@ -7514,6 +7783,7 @@ gif_load (struct frame *f, struct image *img)
7514 for (x = img->corners[RIGHT_CORNER]; x < width; ++x) 7783 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
7515 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); 7784 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7516 } 7785 }
7786#endif
7517 7787
7518 /* Read the GIF image into the X image. */ 7788 /* Read the GIF image into the X image. */
7519 7789
@@ -7568,12 +7838,14 @@ gif_load (struct frame *f, struct image *img)
7568 if (disposal == 0) 7838 if (disposal == 0)
7569 disposal = 1; 7839 disposal = 1;
7570 7840
7571 /* Allocate subimage colors. */
7572 memset (pixel_colors, 0, sizeof pixel_colors);
7573 gif_color_map = subimage->ImageDesc.ColorMap; 7841 gif_color_map = subimage->ImageDesc.ColorMap;
7574 if (!gif_color_map) 7842 if (!gif_color_map)
7575 gif_color_map = gif->SColorMap; 7843 gif_color_map = gif->SColorMap;
7576 7844
7845#ifndef USE_CAIRO
7846 /* Allocate subimage colors. */
7847 memset (pixel_colors, 0, sizeof pixel_colors);
7848
7577 if (gif_color_map) 7849 if (gif_color_map)
7578 for (i = 0; i < gif_color_map->ColorCount; ++i) 7850 for (i = 0; i < gif_color_map->ColorCount; ++i)
7579 { 7851 {
@@ -7588,6 +7860,7 @@ gif_load (struct frame *f, struct image *img)
7588 pixel_colors[i] = lookup_rgb_color (f, r, g, b); 7860 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7589 } 7861 }
7590 } 7862 }
7863#endif
7591 7864
7592 /* Apply the pixel values. */ 7865 /* Apply the pixel values. */
7593 if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace) 7866 if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace)
@@ -7605,20 +7878,47 @@ gif_load (struct frame *f, struct image *img)
7605 { 7878 {
7606 int c = raster[y * subimg_width + x]; 7879 int c = raster[y * subimg_width + x];
7607 if (transparency_color_index != c || disposal != 1) 7880 if (transparency_color_index != c || disposal != 1)
7608 XPutPixel (ximg, x + subimg_left, row + subimg_top, 7881 {
7609 pixel_colors[c]); 7882#ifdef USE_CAIRO
7883 uint32_t *dataptr =
7884 ((uint32_t*)data + ((row + subimg_top) * subimg_width
7885 + x + subimg_left));
7886 int r = gif_color_map->Colors[c].Red;
7887 int g = gif_color_map->Colors[c].Green;
7888 int b = gif_color_map->Colors[c].Blue;
7889
7890 if (transparency_color_index != c)
7891 *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
7892#else
7893 XPutPixel (ximg, x + subimg_left, row + subimg_top,
7894 pixel_colors[c]);
7895#endif
7896 }
7610 } 7897 }
7611 } 7898 }
7612 } 7899 }
7613 else 7900 else
7614 { 7901 {
7615 for (y = 0; y < subimg_height; ++y) 7902 for (y = 0; y < subimg_height; ++y)
7616 for (x = 0; x < subimg_width; ++x) 7903 for (x = 0; x < subimg_width; ++x)
7617 { 7904 {
7618 int c = raster[y * subimg_width + x]; 7905 int c = raster[y * subimg_width + x];
7619 if (transparency_color_index != c || disposal != 1) 7906 if (transparency_color_index != c || disposal != 1)
7620 XPutPixel (ximg, x + subimg_left, y + subimg_top, 7907 {
7621 pixel_colors[c]); 7908#ifdef USE_CAIRO
7909 uint32_t *dataptr =
7910 ((uint32_t*)data + ((y + subimg_top) * subimg_width
7911 + x + subimg_left));
7912 int r = gif_color_map->Colors[c].Red;
7913 int g = gif_color_map->Colors[c].Green;
7914 int b = gif_color_map->Colors[c].Blue;
7915 if (transparency_color_index != c)
7916 *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
7917#else
7918 XPutPixel (ximg, x + subimg_left, y + subimg_top,
7919 pixel_colors[c]);
7920#endif
7921 }
7622 } 7922 }
7623 } 7923 }
7624 } 7924 }
@@ -7675,6 +7975,9 @@ gif_load (struct frame *f, struct image *img)
7675#endif 7975#endif
7676 } 7976 }
7677 7977
7978#ifdef USE_CAIRO
7979 create_cairo_image_surface (img, data, width, height);
7980#else
7678 /* Maybe fill in the background field while we have ximg handy. */ 7981 /* Maybe fill in the background field while we have ximg handy. */
7679 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 7982 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7680 /* Casting avoids a GCC warning. */ 7983 /* Casting avoids a GCC warning. */
@@ -7682,6 +7985,7 @@ gif_load (struct frame *f, struct image *img)
7682 7985
7683 /* Put ximg into the image. */ 7986 /* Put ximg into the image. */
7684 image_put_x_image (f, img, ximg, 0); 7987 image_put_x_image (f, img, ximg, 0);
7988#endif
7685 7989
7686 return 1; 7990 return 1;
7687} 7991}
@@ -8901,6 +9205,37 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8901 eassert (gdk_pixbuf_get_has_alpha (pixbuf)); 9205 eassert (gdk_pixbuf_get_has_alpha (pixbuf));
8902 eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); 9206 eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8903 9207
9208#ifdef USE_CAIRO
9209 {
9210 unsigned char *data = (unsigned char *) xmalloc (width*height*4);
9211 int y;
9212 uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
9213
9214 for (y = 0; y < height; ++y)
9215 {
9216 const guchar *iconptr = pixels + y * rowstride;
9217 uint32_t *dataptr = (uint32_t *) (data + y * rowstride);
9218 int x;
9219
9220 for (x = 0; x < width; ++x)
9221 {
9222 if (iconptr[3] == 0)
9223 *dataptr = bgcolor;
9224 else
9225 *dataptr = (iconptr[0] << 16)
9226 | (iconptr[1] << 8)
9227 | iconptr[2]
9228 | (iconptr[3] << 24);
9229
9230 iconptr += 4;
9231 ++dataptr;
9232 }
9233 }
9234
9235 create_cairo_image_surface (img, data, width, height);
9236 g_object_unref (pixbuf);
9237 }
9238#else
8904 /* Try to create a x pixmap to hold the svg pixmap. */ 9239 /* Try to create a x pixmap to hold the svg pixmap. */
8905 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) 9240 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
8906 { 9241 {
@@ -8972,6 +9307,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8972 9307
8973 /* Put ximg into the image. */ 9308 /* Put ximg into the image. */
8974 image_put_x_image (f, img, ximg, 0); 9309 image_put_x_image (f, img, ximg, 0);
9310#endif /* ! USE_CAIRO */
8975 9311
8976 return 1; 9312 return 1;
8977 9313
@@ -9239,15 +9575,16 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
9239 /* For each pixel of the image, look its color up in the 9575 /* For each pixel of the image, look its color up in the
9240 color table. After having done so, the color table will 9576 color table. After having done so, the color table will
9241 contain an entry for each color used by the image. */ 9577 contain an entry for each color used by the image. */
9578#ifdef COLOR_TABLE_SUPPORT
9242 for (y = 0; y < img->height; ++y) 9579 for (y = 0; y < img->height; ++y)
9243 for (x = 0; x < img->width; ++x) 9580 for (x = 0; x < img->width; ++x)
9244 { 9581 {
9245 unsigned long pixel = XGetPixel (ximg, x, y); 9582 unsigned long pixel = XGetPixel (ximg, x, y);
9583
9246 lookup_pixel_color (f, pixel); 9584 lookup_pixel_color (f, pixel);
9247 } 9585 }
9248 9586
9249 /* Record colors in the image. Free color table and XImage. */ 9587 /* Record colors in the image. Free color table and XImage. */
9250#ifdef COLOR_TABLE_SUPPORT
9251 img->colors = colors_in_color_table (&img->ncolors); 9588 img->colors = colors_in_color_table (&img->ncolors);
9252 free_color_table (); 9589 free_color_table ();
9253#endif 9590#endif
@@ -9360,7 +9697,7 @@ lookup_image_type (Lisp_Object type)
9360 return define_image_type (&gif_type); 9697 return define_image_type (&gif_type);
9361#endif 9698#endif
9362 9699
9363#if defined (HAVE_PNG) || defined (HAVE_NS) 9700#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
9364 if (EQ (type, Qpng)) 9701 if (EQ (type, Qpng))
9365 return define_image_type (&png_type); 9702 return define_image_type (&png_type);
9366#endif 9703#endif
diff --git a/src/xfns.c b/src/xfns.c
index 03ef8136ae2..5ac58e9c7e0 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3116,6 +3116,9 @@ This function is an internal primitive--use `make-frame' instead. */)
3116 specbind (Qx_resource_name, name); 3116 specbind (Qx_resource_name, name);
3117 } 3117 }
3118 3118
3119#ifdef USE_CAIRO
3120 register_font_driver (&ftcrfont_driver, f);
3121#else
3119#ifdef HAVE_FREETYPE 3122#ifdef HAVE_FREETYPE
3120#ifdef HAVE_XFT 3123#ifdef HAVE_XFT
3121 register_font_driver (&xftfont_driver, f); 3124 register_font_driver (&xftfont_driver, f);
@@ -3124,6 +3127,7 @@ This function is an internal primitive--use `make-frame' instead. */)
3124#endif /* not HAVE_XFT */ 3127#endif /* not HAVE_XFT */
3125#endif /* HAVE_FREETYPE */ 3128#endif /* HAVE_FREETYPE */
3126 register_font_driver (&xfont_driver, f); 3129 register_font_driver (&xfont_driver, f);
3130#endif /* not USE_CAIRO */
3127 3131
3128 x_default_parameter (f, parms, Qfont_backend, Qnil, 3132 x_default_parameter (f, parms, Qfont_backend, Qnil,
3129 "fontBackend", "FontBackend", RES_TYPE_STRING); 3133 "fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -5118,6 +5122,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5118 specbind (Qx_resource_name, name); 5122 specbind (Qx_resource_name, name);
5119 } 5123 }
5120 5124
5125#ifdef USE_CAIRO
5126 register_font_driver (&ftcrfont_driver, f);
5127#else
5121 register_font_driver (&xfont_driver, f); 5128 register_font_driver (&xfont_driver, f);
5122#ifdef HAVE_FREETYPE 5129#ifdef HAVE_FREETYPE
5123#ifdef HAVE_XFT 5130#ifdef HAVE_XFT
@@ -5126,6 +5133,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5126 register_font_driver (&ftxfont_driver, f); 5133 register_font_driver (&ftxfont_driver, f);
5127#endif /* not HAVE_XFT */ 5134#endif /* not HAVE_XFT */
5128#endif /* HAVE_FREETYPE */ 5135#endif /* HAVE_FREETYPE */
5136#endif /* not USE_CAIRO */
5129 5137
5130 x_default_parameter (f, parms, Qfont_backend, Qnil, 5138 x_default_parameter (f, parms, Qfont_backend, Qnil,
5131 "fontBackend", "FontBackend", RES_TYPE_STRING); 5139 "fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -6209,6 +6217,158 @@ present and mapped to the usual X keysyms. */)
6209 6217
6210 6218
6211/*********************************************************************** 6219/***********************************************************************
6220 Printing
6221 ***********************************************************************/
6222
6223#ifdef USE_CAIRO
6224DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
6225 doc: /* XXX Experimental. Return image data of FRAMES in TYPE format.
6226FRAMES should be nil (the selected frame), a frame, or a list of
6227frames (each of which corresponds to one page). Optional arg TYPE
6228should be either `pdf' (default), `png', `ps', or `svg'. Supported
6229types are determined by the compile-time configuration of cairo. */)
6230 (Lisp_Object frames, Lisp_Object type)
6231{
6232 Lisp_Object result, rest, tmp;
6233 cairo_surface_type_t surface_type;
6234
6235 if (NILP (frames))
6236 frames = selected_frame;
6237 if (!CONSP (frames))
6238 frames = list1 (frames);
6239
6240 tmp = Qnil;
6241 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6242 {
6243 struct frame *f = XFRAME (XCAR (rest));
6244
6245 if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
6246 error ("Invalid frame");
6247
6248 Lisp_Object frame;
6249
6250 XSETFRAME (frame, f);
6251 tmp = Fcons (frame, tmp);
6252 }
6253 frames = Fnreverse (tmp);
6254
6255#ifdef CAIRO_HAS_PDF_SURFACE
6256 if (NILP (type) || EQ (type, intern ("pdf"))) /* XXX: Qpdf */
6257 surface_type = CAIRO_SURFACE_TYPE_PDF;
6258 else
6259#endif
6260#ifdef CAIRO_HAS_PNG_FUNCTIONS
6261 if (EQ (type, intern ("png")))
6262 {
6263 if (!NILP (XCDR (frames)))
6264 error ("PNG export cannot handle multiple frames.");
6265 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
6266 }
6267 else
6268#endif
6269#ifdef CAIRO_HAS_PS_SURFACE
6270 if (EQ (type, intern ("ps")))
6271 surface_type = CAIRO_SURFACE_TYPE_PS;
6272 else
6273#endif
6274#ifdef CAIRO_HAS_SVG_SURFACE
6275 if (EQ (type, intern ("svg")))
6276 {
6277 /* For now, we stick to SVG 1.1. */
6278 if (!NILP (XCDR (frames)))
6279 error ("SVG export cannot handle multiple frames.");
6280 surface_type = CAIRO_SURFACE_TYPE_SVG;
6281 }
6282 else
6283#endif
6284 error ("Unsupported export type");
6285
6286 result = x_cr_export_frames (frames, surface_type);
6287
6288 return result;
6289}
6290
6291#ifdef USE_GTK
6292DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
6293 doc: /* Pop up a page setup dialog.
6294The current page setup can be obtained using `x-get-page-setup'. */)
6295 (void)
6296{
6297 block_input ();
6298 xg_page_setup_dialog ();
6299 unblock_input ();
6300
6301 return Qnil;
6302}
6303
6304DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
6305 doc: /* Return the value of the current page setup.
6306The return value is an alist containing the following keys:
6307
6308 orientation: page orientation (symbol `portrait', `landscape',
6309 `reverse-portrait', or `reverse-landscape').
6310 width, height: page width/height in points not including margins.
6311 left-margin, right-margin, top-margin, bottom-margin: print margins,
6312 which is the parts of the page that the printer cannot print
6313 on, in points.
6314
6315The paper width can be obtained as the sum of width, left-margin, and
6316right-margin values. Likewise, the paper height is the sum of height,
6317top-margin, and bottom-margin values. */)
6318 (void)
6319{
6320 Lisp_Object result;
6321
6322 block_input ();
6323 result = xg_get_page_setup ();
6324 unblock_input ();
6325
6326 return result;
6327}
6328
6329DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
6330 doc: /* Pop up a print dialog to print the current contents of FRAMES.
6331FRAMES should be nil (the selected frame), a frame, or a list of
6332frames (each of which corresponds to one page). Each frame should be
6333visible. */)
6334 (Lisp_Object frames)
6335{
6336 Lisp_Object rest, tmp;
6337
6338 if (NILP (frames))
6339 frames = selected_frame;
6340 if (!CONSP (frames))
6341 frames = list1 (frames);
6342
6343 tmp = Qnil;
6344 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6345 {
6346 struct frame *f = XFRAME (XCAR (rest));
6347 if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
6348 error ("Invalid frame");
6349 Lisp_Object frame;
6350
6351 XSETFRAME (frame, f);
6352 if (!EQ (Fframe_visible_p (frame), Qt))
6353 error ("Frames to be printed must be visible.");
6354 tmp = Fcons (frame, tmp);
6355 }
6356 frames = Fnreverse (tmp);
6357
6358 /* Make sure the current matrices are up-to-date. */
6359 Fredisplay (Qt);
6360
6361 block_input ();
6362 xg_print_frames_dialog (frames);
6363 unblock_input ();
6364
6365 return Qnil;
6366}
6367#endif /* USE_GTK */
6368#endif /* USE_CAIRO */
6369
6370
6371/***********************************************************************
6212 Initialization 6372 Initialization
6213 ***********************************************************************/ 6373 ***********************************************************************/
6214 6374
@@ -6265,6 +6425,16 @@ syms_of_xfns (void)
6265 DEFSYM (Qfont_param, "font-parameter"); 6425 DEFSYM (Qfont_param, "font-parameter");
6266 DEFSYM (Qmono, "mono"); 6426 DEFSYM (Qmono, "mono");
6267 6427
6428#ifdef USE_CAIRO
6429 DEFSYM (Qorientation, "orientation");
6430 DEFSYM (Qtop_margin, "top-margin");
6431 DEFSYM (Qbottom_margin, "bottom-margin");
6432 DEFSYM (Qportrait, "portrait");
6433 DEFSYM (Qlandscape, "landscape");
6434 DEFSYM (Qreverse_portrait, "reverse-portrait");
6435 DEFSYM (Qreverse_landscape, "reverse-landscape");
6436#endif
6437
6268 Fput (Qundefined_color, Qerror_conditions, 6438 Fput (Qundefined_color, Qerror_conditions,
6269 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); 6439 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
6270 Fput (Qundefined_color, Qerror_message, 6440 Fput (Qundefined_color, Qerror_message,
@@ -6405,6 +6575,20 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
6405 } 6575 }
6406#endif /* USE_GTK */ 6576#endif /* USE_GTK */
6407 6577
6578#ifdef USE_CAIRO
6579 Fprovide (intern_c_string ("cairo"), Qnil);
6580
6581 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
6582 doc: /* Version info for cairo. */);
6583 {
6584 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
6585 int len = sprintf (cairo_version, "%d.%d.%d",
6586 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
6587 CAIRO_VERSION_MICRO);
6588 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
6589 }
6590#endif
6591
6408 /* X window properties. */ 6592 /* X window properties. */
6409 defsubr (&Sx_change_window_property); 6593 defsubr (&Sx_change_window_property);
6410 defsubr (&Sx_delete_window_property); 6594 defsubr (&Sx_delete_window_property);
@@ -6455,4 +6639,13 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
6455#if defined (USE_GTK) && defined (HAVE_FREETYPE) 6639#if defined (USE_GTK) && defined (HAVE_FREETYPE)
6456 defsubr (&Sx_select_font); 6640 defsubr (&Sx_select_font);
6457#endif 6641#endif
6642
6643#ifdef USE_CAIRO
6644 defsubr (&Sx_export_frames);
6645#ifdef USE_GTK
6646 defsubr (&Sx_page_setup_dialog);
6647 defsubr (&Sx_get_page_setup);
6648 defsubr (&Sx_print_frames_dialog);
6649#endif
6650#endif
6458} 6651}
diff --git a/src/xterm.c b/src/xterm.c
index 06ce7070bca..3734fbfee92 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -22,6 +22,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 22
23#include <config.h> 23#include <config.h>
24#include <stdio.h> 24#include <stdio.h>
25#ifdef USE_CAIRO
26#include <math.h>
27#endif
25 28
26#include "lisp.h" 29#include "lisp.h"
27#include "blockinput.h" 30#include "blockinput.h"
@@ -220,6 +223,7 @@ static int x_io_error_quitter (Display *);
220static struct terminal *x_create_terminal (struct x_display_info *); 223static struct terminal *x_create_terminal (struct x_display_info *);
221static void x_update_end (struct frame *); 224static void x_update_end (struct frame *);
222static void XTframe_up_to_date (struct frame *); 225static void XTframe_up_to_date (struct frame *);
226static void x_clear_area1 (Display *, Window, int, int, int, int, int);
223static void x_clear_frame (struct frame *); 227static void x_clear_frame (struct frame *);
224static _Noreturn void x_ins_del_lines (struct frame *, int, int); 228static _Noreturn void x_ins_del_lines (struct frame *, int, int);
225static void frame_highlight (struct frame *); 229static void frame_highlight (struct frame *);
@@ -325,6 +329,587 @@ record_event (char *locus, int type)
325 329
326#endif 330#endif
327 331
332static void x_free_cr_resources (struct frame *);
333static void x_set_clip_rectangles (struct frame *, GC, XRectangle *, int);
334static void x_reset_clip_rectangles (struct frame *, GC);
335static void x_fill_rectangle (struct frame *, GC, int, int, int, int);
336static void x_draw_rectangle (struct frame *, GC, int, int, int, int);
337static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int,
338 int, int, int);
339static void x_clear_window (struct frame *);
340
341#ifdef USE_CAIRO
342static struct x_gc_ext_data *x_gc_get_ext_data (struct frame *, GC, int);
343static void x_extension_initialize (struct x_display_info *);
344static cairo_status_t x_cr_accumulate_data (void *,
345 const unsigned char *,
346 unsigned int);
347
348#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
349#define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
350
351static struct x_gc_ext_data *
352x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
353{
354 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
355 XEDataObject object;
356 XExtData **head, *ext_data;
357
358 object.gc = gc;
359 head = XEHeadOfExtensionList (object);
360 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
361 if (ext_data == NULL)
362 {
363 if (!create_if_not_found_p)
364 return NULL;
365 else
366 {
367 ext_data = xzalloc (sizeof (*ext_data));
368 ext_data->number = dpyinfo->ext_codes->extension;
369 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
370 XAddToExtensionList (head, ext_data);
371 }
372 }
373 return (struct x_gc_ext_data *) ext_data->private_data;
374}
375
376static void
377x_extension_initialize (struct x_display_info *dpyinfo)
378{
379 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
380
381 dpyinfo->ext_codes = ext_codes;
382}
383
384static void
385x_cr_destroy_surface (struct frame *f)
386{
387 if (FRAME_CR_SURFACE (f))
388 {
389 cairo_t *cr = FRAME_CR_CONTEXT (f);
390 cairo_surface_destroy (FRAME_CR_SURFACE (f));
391 FRAME_CR_SURFACE (f) = 0;
392 if (cr) cairo_destroy (cr);
393 FRAME_CR_CONTEXT (f) = NULL;
394 }
395}
396
397cairo_t *
398x_begin_cr_clip (struct frame *f, GC gc)
399{
400 cairo_t *cr = FRAME_CR_CONTEXT (f);
401
402 if (!cr)
403 {
404
405 if (! FRAME_CR_SURFACE (f))
406 {
407 cairo_surface_t *surface;
408 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
409 FRAME_X_WINDOW (f),
410 FRAME_DISPLAY_INFO (f)->visual,
411 FRAME_PIXEL_WIDTH (f),
412 FRAME_PIXEL_HEIGHT (f));
413 cr = cairo_create (surface);
414 cairo_surface_destroy (surface);
415 }
416 else
417 cr = cairo_create (FRAME_CR_SURFACE (f));
418 FRAME_CR_CONTEXT (f) = cr;
419 }
420 cairo_save (cr);
421
422 if (gc)
423 {
424 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
425
426 if (gc_ext && gc_ext->n_clip_rects)
427 {
428 int i;
429
430 for (i = 0; i < gc_ext->n_clip_rects; i++)
431 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
432 gc_ext->clip_rects[i].y,
433 gc_ext->clip_rects[i].width,
434 gc_ext->clip_rects[i].height);
435 cairo_clip (cr);
436 }
437 }
438
439 return cr;
440}
441
442void
443x_end_cr_clip (struct frame *f)
444{
445 cairo_restore (FRAME_CR_CONTEXT (f));
446}
447
448void
449x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
450{
451 XGCValues xgcv;
452 XColor color;
453
454 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
455 color.pixel = xgcv.foreground;
456 x_query_color (f, &color);
457 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
458 color.green / 65535.0, color.blue / 65535.0);
459}
460
461void
462x_set_cr_source_with_gc_background (struct frame *f, GC gc)
463{
464 XGCValues xgcv;
465 XColor color;
466
467 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
468 color.pixel = xgcv.background;
469 x_query_color (f, &color);
470 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
471 color.green / 65535.0, color.blue / 65535.0);
472}
473
474/* Fringe bitmaps. */
475
476static int max_fringe_bmp = 0;
477static cairo_pattern_t **fringe_bmp = 0;
478
479static void
480x_cr_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
481{
482 int i, stride;
483 cairo_surface_t *surface;
484 unsigned char *data;
485 cairo_pattern_t *pattern;
486
487 if (which >= max_fringe_bmp)
488 {
489 i = max_fringe_bmp;
490 max_fringe_bmp = which + 20;
491 fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *));
492 while (i < max_fringe_bmp)
493 fringe_bmp[i++] = 0;
494 }
495
496 block_input ();
497
498 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
499 stride = cairo_image_surface_get_stride (surface);
500 data = cairo_image_surface_get_data (surface);
501
502 for (i = 0; i < h; i++)
503 {
504 *((unsigned short *) data) = bits[i];
505 data += stride;
506 }
507
508 cairo_surface_mark_dirty (surface);
509 pattern = cairo_pattern_create_for_surface (surface);
510 cairo_surface_destroy (surface);
511
512 unblock_input ();
513
514 fringe_bmp[which] = pattern;
515}
516
517static void
518x_cr_destroy_fringe_bitmap (int which)
519{
520 if (which >= max_fringe_bmp)
521 return;
522
523 if (fringe_bmp[which])
524 {
525 block_input ();
526 cairo_pattern_destroy (fringe_bmp[which]);
527 unblock_input ();
528 }
529 fringe_bmp[which] = 0;
530}
531
532static void
533x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
534 int src_x, int src_y, int width, int height,
535 int dest_x, int dest_y, bool overlay_p)
536{
537 cairo_t *cr;
538 cairo_matrix_t matrix;
539 cairo_surface_t *surface;
540 cairo_format_t format;
541
542 cr = x_begin_cr_clip (f, gc);
543 if (overlay_p)
544 cairo_rectangle (cr, dest_x, dest_y, width, height);
545 else
546 {
547 x_set_cr_source_with_gc_background (f, gc);
548 cairo_rectangle (cr, dest_x, dest_y, width, height);
549 cairo_fill_preserve (cr);
550 }
551 cairo_clip (cr);
552 cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y);
553 cairo_pattern_set_matrix (image, &matrix);
554 cairo_pattern_get_surface (image, &surface);
555 format = cairo_image_surface_get_format (surface);
556 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
557 {
558 cairo_set_source (cr, image);
559 cairo_fill (cr);
560 }
561 else
562 {
563 x_set_cr_source_with_gc_foreground (f, gc);
564 cairo_mask (cr, image);
565 }
566 x_end_cr_clip (f);
567}
568
569void
570x_cr_draw_frame (cairo_t *cr, struct frame *f)
571{
572 int width, height;
573
574 width = FRAME_PIXEL_WIDTH (f);
575 height = FRAME_PIXEL_HEIGHT (f);
576
577 x_free_cr_resources (f);
578 FRAME_CR_CONTEXT (f) = cr;
579 x_clear_area (f, 0, 0, width, height);
580 expose_frame (f, 0, 0, width, height);
581 FRAME_CR_CONTEXT (f) = NULL;
582}
583
584static cairo_status_t
585x_cr_accumulate_data (void *closure, const unsigned char *data,
586 unsigned int length)
587{
588 Lisp_Object *acc = (Lisp_Object *) closure;
589
590 *acc = Fcons (make_unibyte_string (data, length), *acc);
591
592 return CAIRO_STATUS_SUCCESS;
593}
594
595static void
596x_cr_destroy (Lisp_Object arg)
597{
598 cairo_t *cr = (cairo_t *) XSAVE_POINTER (arg, 0);
599
600 block_input ();
601 cairo_destroy (cr);
602 unblock_input ();
603}
604
605Lisp_Object
606x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
607{
608 struct frame *f;
609 cairo_surface_t *surface;
610 cairo_t *cr;
611 int width, height;
612 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
613 Lisp_Object acc = Qnil, args[2];
614 int count = SPECPDL_INDEX ();
615
616 Fredisplay (Qt);
617
618 f = XFRAME (XCAR (frames));
619 frames = XCDR (frames);
620 width = FRAME_PIXEL_WIDTH (f);
621 height = FRAME_PIXEL_HEIGHT (f);
622
623 block_input ();
624#ifdef CAIRO_HAS_PDF_SURFACE
625 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
626 {
627 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
628 width, height);
629 surface_set_size_func = cairo_pdf_surface_set_size;
630 }
631 else
632#endif
633#ifdef CAIRO_HAS_PNG_FUNCTIONS
634 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
635 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
636 else
637#endif
638#ifdef CAIRO_HAS_PS_SURFACE
639 if (surface_type == CAIRO_SURFACE_TYPE_PS)
640 {
641 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
642 width, height);
643 surface_set_size_func = cairo_ps_surface_set_size;
644 }
645 else
646#endif
647#ifdef CAIRO_HAS_SVG_SURFACE
648 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
649 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
650 width, height);
651 else
652#endif
653 abort ();
654
655 cr = cairo_create (surface);
656 cairo_surface_destroy (surface);
657 record_unwind_protect (x_cr_destroy, make_save_ptr (cr));
658 unblock_input ();
659
660 while (1)
661 {
662 QUIT;
663
664 block_input ();
665 x_free_cr_resources (f);
666 FRAME_CR_CONTEXT (f) = cr;
667 x_clear_area (f, 0, 0, width, height);
668 expose_frame (f, 0, 0, width, height);
669 FRAME_CR_CONTEXT (f) = NULL;
670 unblock_input ();
671
672 if (NILP (frames))
673 break;
674
675 block_input ();
676 cairo_surface_show_page (surface);
677 f = XFRAME (XCAR (frames));
678 frames = XCDR (frames);
679 width = FRAME_PIXEL_WIDTH (f);
680 height = FRAME_PIXEL_HEIGHT (f);
681 if (surface_set_size_func)
682 (*surface_set_size_func) (surface, width, height);
683 unblock_input ();
684 }
685
686#ifdef CAIRO_HAS_PNG_FUNCTIONS
687 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
688 {
689 block_input ();
690 cairo_surface_flush (surface);
691 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
692 unblock_input ();
693 }
694#endif
695 unbind_to (count, Qnil);
696
697 args[0] = intern ("concat");
698 args[1] = Fnreverse (acc);
699 return Fapply (2, args);
700}
701
702#endif /* USE_CAIRO */
703
704static void
705x_free_cr_resources (struct frame *f)
706{
707#ifdef USE_CAIRO
708 if (f == NULL)
709 {
710 Lisp_Object rest, frame;
711 FOR_EACH_FRAME (rest, frame)
712 if (FRAME_X_P (XFRAME (frame)))
713 x_free_cr_resources (XFRAME (frame));
714 }
715 else
716 {
717 cairo_t *cr = FRAME_CR_CONTEXT (f);
718
719 if (cr)
720 {
721 cairo_surface_t *surface = cairo_get_target (cr);
722
723 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
724 {
725 cairo_destroy (cr);
726 FRAME_CR_CONTEXT (f) = NULL;
727 }
728 }
729 }
730#endif
731}
732
733static void
734x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
735{
736 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
737#ifdef USE_CAIRO
738 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
739
740 {
741 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
742
743 gc_ext->n_clip_rects = n;
744 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
745 }
746#endif
747}
748
749static void
750x_reset_clip_rectangles (struct frame *f, GC gc)
751{
752 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
753#ifdef USE_CAIRO
754 {
755 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
756
757 if (gc_ext)
758 gc_ext->n_clip_rects = 0;
759 }
760#endif
761}
762
763static void
764x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
765{
766#ifdef USE_CAIRO
767 cairo_t *cr;
768
769 cr = x_begin_cr_clip (f, gc);
770 x_set_cr_source_with_gc_foreground (f, gc);
771 cairo_rectangle (cr, x, y, width, height);
772 cairo_fill (cr);
773 x_end_cr_clip (f);
774#else
775 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
776 gc, x, y, width, height);
777#endif
778}
779
780static void
781x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
782{
783#ifdef USE_CAIRO
784 cairo_t *cr;
785
786 cr = x_begin_cr_clip (f, gc);
787 x_set_cr_source_with_gc_foreground (f, gc);
788 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
789 cairo_set_line_width (cr, 1);
790 cairo_stroke (cr);
791 x_end_cr_clip (f);
792#else
793 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
794 gc, x, y, width, height);
795#endif
796}
797
798static void
799x_clear_window (struct frame *f)
800{
801#ifdef USE_CAIRO
802 cairo_t *cr;
803
804 cr = x_begin_cr_clip (f, NULL);
805 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
806 cairo_paint (cr);
807 x_end_cr_clip (f);
808#else
809 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
810#endif
811}
812
813#ifdef USE_CAIRO
814static void
815x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
816 int width, int height, int top_p)
817{
818 cairo_t *cr;
819
820 cr = x_begin_cr_clip (f, gc);
821 x_set_cr_source_with_gc_foreground (f, gc);
822 cairo_move_to (cr, top_p ? x : x + height, y);
823 cairo_line_to (cr, x, y + height);
824 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
825 cairo_line_to (cr, x + width, y);
826 cairo_fill (cr);
827 x_end_cr_clip (f);
828}
829
830enum corners
831 {
832 CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */
833 CORNER_BOTTOM_LEFT, /* pi/2 -> pi */
834 CORNER_TOP_LEFT, /* pi -> 3pi/2 */
835 CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */
836 CORNER_LAST
837 };
838
839static void
840x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
841 int width, int height,
842 double radius, double margin, int corners)
843{
844 cairo_t *cr;
845 int i;
846
847 cr = x_begin_cr_clip (f, gc);
848 x_set_cr_source_with_gc_background (f, gc);
849 for (i = 0; i < CORNER_LAST; i++)
850 if (corners & (1 << i))
851 {
852 double xm, ym, xc, yc;
853
854 if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
855 xm = x - margin, xc = xm + radius;
856 else
857 xm = x + width + margin, xc = xm - radius;
858 if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
859 ym = y - margin, yc = ym + radius;
860 else
861 ym = y + height + margin, yc = ym - radius;
862
863 cairo_move_to (cr, xm, ym);
864 cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
865 }
866 cairo_clip (cr);
867 cairo_rectangle (cr, x, y, width, height);
868 cairo_fill (cr);
869 x_end_cr_clip (f);
870}
871
872static void
873x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
874 int width, int height, int wave_length)
875{
876 cairo_t *cr;
877 double dx = wave_length, dy = height - 1;
878 int xoffset, n;
879
880 cr = x_begin_cr_clip (f, gc);
881 x_set_cr_source_with_gc_foreground (f, gc);
882 cairo_rectangle (cr, x, y, width, height);
883 cairo_clip (cr);
884
885 if (x >= 0)
886 {
887 xoffset = x % (wave_length * 2);
888 if (xoffset == 0)
889 xoffset = wave_length * 2;
890 }
891 else
892 xoffset = x % (wave_length * 2) + wave_length * 2;
893 n = (width + xoffset) / wave_length + 1;
894 if (xoffset > wave_length)
895 {
896 xoffset -= wave_length;
897 --n;
898 y += height - 1;
899 dy = -dy;
900 }
901
902 cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
903 while (--n >= 0)
904 {
905 cairo_rel_line_to (cr, dx, dy);
906 dy = -dy;
907 }
908 cairo_set_line_width (cr, 1);
909 cairo_stroke (cr);
910 x_end_cr_clip (f);
911}
912#endif
328 913
329 914
330/* Return the struct x_display_info corresponding to DPY. */ 915/* Return the struct x_display_info corresponding to DPY. */
@@ -452,9 +1037,42 @@ x_set_frame_alpha (struct frame *f)
452static void 1037static void
453x_update_begin (struct frame *f) 1038x_update_begin (struct frame *f)
454{ 1039{
455 /* Nothing to do. */ 1040#ifdef USE_CAIRO
456} 1041 if (! NILP (tip_frame) && XFRAME (tip_frame) == f
1042 && ! FRAME_VISIBLE_P (f))
1043 return;
1044
1045 if (! FRAME_CR_SURFACE (f))
1046 {
1047 int width, height;
1048#ifdef USE_GTK
1049 if (FRAME_GTK_WIDGET (f))
1050 {
1051 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1052 width = gdk_window_get_width (w);
1053 height = gdk_window_get_height (w);
1054 }
1055 else
1056#endif
1057 {
1058 width = FRAME_PIXEL_WIDTH (f);
1059 height = FRAME_PIXEL_HEIGHT (f);
1060 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1061 height += FRAME_TOOL_BAR_HEIGHT (f);
1062 if (! FRAME_EXTERNAL_MENU_BAR (f))
1063 height += FRAME_MENU_BAR_HEIGHT (f);
1064 }
457 1065
1066 if (width > 0 && height > 0)
1067 {
1068 block_input();
1069 FRAME_CR_SURFACE (f) = cairo_image_surface_create
1070 (CAIRO_FORMAT_ARGB32, width, height);
1071 unblock_input();
1072 }
1073 }
1074#endif /* USE_CAIRO */
1075}
458 1076
459/* Start update of window W. */ 1077/* Start update of window W. */
460 1078
@@ -496,8 +1114,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, 1114 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
497 face->foreground); 1115 face->foreground);
498 1116
1117#ifdef USE_CAIRO
1118 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
1119#else
499 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1120 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
500 f->output_data.x->normal_gc, x, y0, x, y1); 1121 f->output_data.x->normal_gc, x, y0, x, y1);
1122#endif
501} 1123}
502 1124
503/* Draw a window divider from (x0,y0) to (x1,y1) */ 1125/* Draw a window divider from (x0,y0) to (x1,y1) */
@@ -517,39 +1139,38 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
517 ? face_last->foreground 1139 ? face_last->foreground
518 : FRAME_FOREGROUND_PIXEL (f)); 1140 : FRAME_FOREGROUND_PIXEL (f));
519 Display *display = FRAME_X_DISPLAY (f); 1141 Display *display = FRAME_X_DISPLAY (f);
520 Window window = FRAME_X_WINDOW (f);
521 1142
522 if (y1 - y0 > x1 - x0 && x1 - x0 > 2) 1143 if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
523 /* Vertical. */ 1144 /* Vertical. */
524 { 1145 {
525 XSetForeground (display, f->output_data.x->normal_gc, color_first); 1146 XSetForeground (display, f->output_data.x->normal_gc, color_first);
526 XFillRectangle (display, window, f->output_data.x->normal_gc, 1147 x_fill_rectangle (f, f->output_data.x->normal_gc,
527 x0, y0, 1, y1 - y0); 1148 x0, y0, 1, y1 - y0);
528 XSetForeground (display, f->output_data.x->normal_gc, color); 1149 XSetForeground (display, f->output_data.x->normal_gc, color);
529 XFillRectangle (display, window, f->output_data.x->normal_gc, 1150 x_fill_rectangle (f, f->output_data.x->normal_gc,
530 x0 + 1, y0, x1 - x0 - 2, y1 - y0); 1151 x0 + 1, y0, x1 - x0 - 2, y1 - y0);
531 XSetForeground (display, f->output_data.x->normal_gc, color_last); 1152 XSetForeground (display, f->output_data.x->normal_gc, color_last);
532 XFillRectangle (display, window, f->output_data.x->normal_gc, 1153 x_fill_rectangle (f, f->output_data.x->normal_gc,
533 x1 - 1, y0, 1, y1 - y0); 1154 x1 - 1, y0, 1, y1 - y0);
534 } 1155 }
535 else if (x1 - x0 > y1 - y0 && y1 - y0 > 3) 1156 else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
536 /* Horizontal. */ 1157 /* Horizontal. */
537 { 1158 {
538 XSetForeground (display, f->output_data.x->normal_gc, color_first); 1159 XSetForeground (display, f->output_data.x->normal_gc, color_first);
539 XFillRectangle (display, window, f->output_data.x->normal_gc, 1160 x_fill_rectangle (f, f->output_data.x->normal_gc,
540 x0, y0, x1 - x0, 1); 1161 x0, y0, x1 - x0, 1);
541 XSetForeground (display, f->output_data.x->normal_gc, color); 1162 XSetForeground (display, f->output_data.x->normal_gc, color);
542 XFillRectangle (display, window, f->output_data.x->normal_gc, 1163 x_fill_rectangle (f, f->output_data.x->normal_gc,
543 x0, y0 + 1, x1 - x0, y1 - y0 - 2); 1164 x0, y0 + 1, x1 - x0, y1 - y0 - 2);
544 XSetForeground (display, f->output_data.x->normal_gc, color_last); 1165 XSetForeground (display, f->output_data.x->normal_gc, color_last);
545 XFillRectangle (display, window, f->output_data.x->normal_gc, 1166 x_fill_rectangle (f, f->output_data.x->normal_gc,
546 x0, y1 - 1, x1 - x0, 1); 1167 x0, y1 - 1, x1 - x0, 1);
547 } 1168 }
548 else 1169 else
549 { 1170 {
550 XSetForeground (display, f->output_data.x->normal_gc, color); 1171 XSetForeground (display, f->output_data.x->normal_gc, color);
551 XFillRectangle (display, window, f->output_data.x->normal_gc, 1172 x_fill_rectangle (f, f->output_data.x->normal_gc,
552 x0, y0, x1 - x0, y1 - y0); 1173 x0, y0, x1 - x0, y1 - y0);
553 } 1174 }
554} 1175}
555 1176
@@ -612,6 +1233,43 @@ x_update_end (struct frame *f)
612 /* Mouse highlight may be displayed again. */ 1233 /* Mouse highlight may be displayed again. */
613 MOUSE_HL_INFO (f)->mouse_face_defer = false; 1234 MOUSE_HL_INFO (f)->mouse_face_defer = false;
614 1235
1236#ifdef USE_CAIRO
1237 if (FRAME_CR_SURFACE (f))
1238 {
1239 cairo_t *cr = 0;
1240 block_input();
1241#if defined (USE_GTK) && defined (HAVE_GTK3)
1242 if (FRAME_GTK_WIDGET (f))
1243 {
1244 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1245 cr = gdk_cairo_create (w);
1246 }
1247 else
1248#endif
1249 {
1250 cairo_surface_t *surface;
1251 int width = FRAME_PIXEL_WIDTH (f);
1252 int height = FRAME_PIXEL_HEIGHT (f);
1253 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1254 height += FRAME_TOOL_BAR_HEIGHT (f);
1255 if (! FRAME_EXTERNAL_MENU_BAR (f))
1256 height += FRAME_MENU_BAR_HEIGHT (f);
1257 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
1258 FRAME_X_WINDOW (f),
1259 FRAME_DISPLAY_INFO (f)->visual,
1260 width,
1261 height);
1262 cr = cairo_create (surface);
1263 cairo_surface_destroy (surface);
1264 }
1265
1266 cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
1267 cairo_paint (cr);
1268 cairo_destroy (cr);
1269 unblock_input ();
1270 }
1271#endif /* USE_CAIRO */
1272
615#ifndef XFlush 1273#ifndef XFlush
616 block_input (); 1274 block_input ();
617 XFlush (FRAME_X_DISPLAY (f)); 1275 XFlush (FRAME_X_DISPLAY (f));
@@ -638,18 +1296,16 @@ x_clear_under_internal_border (struct frame *f)
638{ 1296{
639 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) 1297 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
640 { 1298 {
641 Display *display = FRAME_X_DISPLAY (f);
642 Window window = FRAME_X_WINDOW (f);
643 int border = FRAME_INTERNAL_BORDER_WIDTH (f); 1299 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
644 int width = FRAME_PIXEL_WIDTH (f); 1300 int width = FRAME_PIXEL_WIDTH (f);
645 int height = FRAME_PIXEL_HEIGHT (f); 1301 int height = FRAME_PIXEL_HEIGHT (f);
646 int margin = FRAME_TOP_MARGIN_HEIGHT (f); 1302 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
647 1303
648 block_input (); 1304 block_input ();
649 x_clear_area (display, window, 0, 0, border, height); 1305 x_clear_area (f, 0, 0, border, height);
650 x_clear_area (display, window, 0, margin, width, border); 1306 x_clear_area (f, 0, margin, width, border);
651 x_clear_area (display, window, width - border, 0, border, height); 1307 x_clear_area (f, width - border, 0, border, height);
652 x_clear_area (display, window, 0, height - border, width, border); 1308 x_clear_area (f, 0, height - border, width, border);
653 unblock_input (); 1309 unblock_input ();
654 } 1310 }
655} 1311}
@@ -691,11 +1347,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)); 1347 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
692 1348
693 block_input (); 1349 block_input ();
694 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1350 x_clear_area (f, 0, y, width, height);
695 0, y, width, height); 1351 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 (); 1352 unblock_input ();
700 } 1353 }
701 } 1354 }
@@ -725,13 +1378,29 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
725 else 1378 else
726 XSetForeground (display, face->gc, face->background); 1379 XSetForeground (display, face->gc, face->background);
727 1380
728 XFillRectangle (display, window, face->gc, 1381 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
729 p->bx, p->by, p->nx, p->ny);
730 1382
731 if (!face->stipple) 1383 if (!face->stipple)
732 XSetForeground (display, face->gc, face->foreground); 1384 XSetForeground (display, face->gc, face->foreground);
733 } 1385 }
734 1386
1387#ifdef USE_CAIRO
1388 if (p->which && p->which < max_fringe_bmp)
1389 {
1390 XGCValues gcv;
1391
1392 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
1393 XSetForeground (display, gc, (p->cursor_p
1394 ? (p->overlay_p ? face->background
1395 : f->output_data.x->cursor_pixel)
1396 : face->foreground));
1397 XSetBackground (display, gc, face->background);
1398 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
1399 p->wd, p->h, p->x, p->y, p->overlay_p);
1400 XSetForeground (display, gc, gcv.foreground);
1401 XSetBackground (display, gc, gcv.background);
1402 }
1403#else /* not USE_CAIRO */
735 if (p->which) 1404 if (p->which)
736 { 1405 {
737 char *bits; 1406 char *bits;
@@ -776,8 +1445,9 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
776 XFreePixmap (display, clipmask); 1445 XFreePixmap (display, clipmask);
777 } 1446 }
778 } 1447 }
1448#endif /* not USE_CAIRO */
779 1449
780 XSetClipMask (display, gc, None); 1450 x_reset_clip_rectangles (f, gc);
781} 1451}
782 1452
783/*********************************************************************** 1453/***********************************************************************
@@ -985,7 +1655,7 @@ x_set_glyph_string_clipping (struct glyph_string *s)
985 int n = get_glyph_string_clip_rects (s, r, 2); 1655 int n = get_glyph_string_clip_rects (s, r, 2);
986 1656
987 if (n > 0) 1657 if (n > 0)
988 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted); 1658 x_set_clip_rectangles (s->f, s->gc, r, n);
989 s->num_clips = n; 1659 s->num_clips = n;
990} 1660}
991 1661
@@ -1005,7 +1675,7 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_stri
1005 r.height = src->height; 1675 r.height = src->height;
1006 dst->clip[0] = r; 1676 dst->clip[0] = r;
1007 dst->num_clips = 1; 1677 dst->num_clips = 1;
1008 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted); 1678 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
1009} 1679}
1010 1680
1011 1681
@@ -1057,7 +1727,7 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1057 XGCValues xgcv; 1727 XGCValues xgcv;
1058 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv); 1728 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1059 XSetForeground (s->display, s->gc, xgcv.background); 1729 XSetForeground (s->display, s->gc, xgcv.background);
1060 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); 1730 x_fill_rectangle (s->f, s->gc, x, y, w, h);
1061 XSetForeground (s->display, s->gc, xgcv.foreground); 1731 XSetForeground (s->display, s->gc, xgcv.foreground);
1062} 1732}
1063 1733
@@ -1081,7 +1751,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1081 { 1751 {
1082 /* Fill background with a stipple pattern. */ 1752 /* Fill background with a stipple pattern. */
1083 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 1753 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1084 XFillRectangle (s->display, s->window, s->gc, s->x, 1754 x_fill_rectangle (s->f, s->gc, s->x,
1085 s->y + box_line_width, 1755 s->y + box_line_width,
1086 s->background_width, 1756 s->background_width,
1087 s->height - 2 * box_line_width); 1757 s->height - 2 * box_line_width);
@@ -1124,7 +1794,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
1124 for (i = 0; i < s->nchars; ++i) 1794 for (i = 0; i < s->nchars; ++i)
1125 { 1795 {
1126 struct glyph *g = s->first_glyph + i; 1796 struct glyph *g = s->first_glyph + i;
1127 XDrawRectangle (s->display, s->window, 1797 x_draw_rectangle (s->f,
1128 s->gc, x, s->y, g->pixel_width - 1, 1798 s->gc, x, s->y, g->pixel_width - 1,
1129 s->height - 1); 1799 s->height - 1);
1130 x += g->pixel_width; 1800 x += g->pixel_width;
@@ -1176,7 +1846,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1176 if (s->font_not_found_p) 1846 if (s->font_not_found_p)
1177 { 1847 {
1178 if (s->cmp_from == 0) 1848 if (s->cmp_from == 0)
1179 XDrawRectangle (s->display, s->window, s->gc, x, s->y, 1849 x_draw_rectangle (s->f, s->gc, x, s->y,
1180 s->width - 1, s->height - 1); 1850 s->width - 1, s->height - 1);
1181 } 1851 }
1182 else if (! s->first_glyph->u.cmp.automatic) 1852 else if (! s->first_glyph->u.cmp.automatic)
@@ -1310,7 +1980,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1310 false); 1980 false);
1311 } 1981 }
1312 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE) 1982 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1313 XDrawRectangle (s->display, s->window, s->gc, 1983 x_draw_rectangle (s->f, s->gc,
1314 x, s->ybase - glyph->ascent, 1984 x, s->ybase - glyph->ascent,
1315 glyph->pixel_width - 1, 1985 glyph->pixel_width - 1,
1316 glyph->ascent + glyph->descent - 1); 1986 glyph->ascent + glyph->descent - 1);
@@ -1882,6 +2552,79 @@ x_draw_relief_rect (struct frame *f,
1882 bool left_p, bool right_p, 2552 bool left_p, bool right_p,
1883 XRectangle *clip_rect) 2553 XRectangle *clip_rect)
1884{ 2554{
2555#ifdef USE_CAIRO
2556 GC top_left_gc, bottom_right_gc;
2557 int corners = 0;
2558
2559 if (raised_p)
2560 {
2561 top_left_gc = f->output_data.x->white_relief.gc;
2562 bottom_right_gc = f->output_data.x->black_relief.gc;
2563 }
2564 else
2565 {
2566 top_left_gc = f->output_data.x->black_relief.gc;
2567 bottom_right_gc = f->output_data.x->white_relief.gc;
2568 }
2569
2570 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
2571 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
2572
2573 if (left_p)
2574 {
2575 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2576 width, bottom_y + 1 - top_y);
2577 if (top_p)
2578 corners |= 1 << CORNER_TOP_LEFT;
2579 if (bot_p)
2580 corners |= 1 << CORNER_BOTTOM_LEFT;
2581 }
2582 if (right_p)
2583 {
2584 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
2585 width, bottom_y + 1 - top_y);
2586 if (top_p)
2587 corners |= 1 << CORNER_TOP_RIGHT;
2588 if (bot_p)
2589 corners |= 1 << CORNER_BOTTOM_RIGHT;
2590 }
2591 if (top_p)
2592 {
2593 if (!right_p)
2594 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2595 right_x + 1 - left_x, width);
2596 else
2597 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
2598 right_x + 1 - left_x, width, 1);
2599 }
2600 if (bot_p)
2601 {
2602 if (!left_p)
2603 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
2604 right_x + 1 - left_x, width);
2605 else
2606 x_fill_trapezoid_for_relief (f, bottom_right_gc,
2607 left_x, bottom_y + 1 - width,
2608 right_x + 1 - left_x, width, 0);
2609 }
2610 if (left_p && width != 1)
2611 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2612 1, bottom_y + 1 - top_y);
2613 if (top_p && width != 1)
2614 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2615 right_x + 1 - left_x, 1);
2616 if (corners)
2617 {
2618 XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
2619 FRAME_BACKGROUND_PIXEL (f));
2620 x_erase_corners_for_relief (f, top_left_gc, left_x, top_y,
2621 right_x - left_x + 1, bottom_y - top_y + 1,
2622 6, 1, corners);
2623 }
2624
2625 x_reset_clip_rectangles (f, top_left_gc);
2626 x_reset_clip_rectangles (f, bottom_right_gc);
2627#else
1885 Display *dpy = FRAME_X_DISPLAY (f); 2628 Display *dpy = FRAME_X_DISPLAY (f);
1886 Window window = FRAME_X_WINDOW (f); 2629 Window window = FRAME_X_WINDOW (f);
1887 int i; 2630 int i;
@@ -1970,7 +2713,9 @@ x_draw_relief_rect (struct frame *f,
1970 right_x - i, bottom_y + 1 - (i + 1) * bot_p); 2713 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
1971 } 2714 }
1972 2715
1973 XSetClipMask (dpy, gc, None); 2716 x_reset_clip_rectangles (f, gc);
2717
2718#endif
1974} 2719}
1975 2720
1976 2721
@@ -1990,28 +2735,28 @@ x_draw_box_rect (struct glyph_string *s,
1990 2735
1991 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 2736 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
1992 XSetForeground (s->display, s->gc, s->face->box_color); 2737 XSetForeground (s->display, s->gc, s->face->box_color);
1993 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted); 2738 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
1994 2739
1995 /* Top. */ 2740 /* Top. */
1996 XFillRectangle (s->display, s->window, s->gc, 2741 x_fill_rectangle (s->f, s->gc,
1997 left_x, top_y, right_x - left_x + 1, width); 2742 left_x, top_y, right_x - left_x + 1, width);
1998 2743
1999 /* Left. */ 2744 /* Left. */
2000 if (left_p) 2745 if (left_p)
2001 XFillRectangle (s->display, s->window, s->gc, 2746 x_fill_rectangle (s->f, s->gc,
2002 left_x, top_y, width, bottom_y - top_y + 1); 2747 left_x, top_y, width, bottom_y - top_y + 1);
2003 2748
2004 /* Bottom. */ 2749 /* Bottom. */
2005 XFillRectangle (s->display, s->window, s->gc, 2750 x_fill_rectangle (s->f, s->gc,
2006 left_x, bottom_y - width + 1, right_x - left_x + 1, width); 2751 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2007 2752
2008 /* Right. */ 2753 /* Right. */
2009 if (right_p) 2754 if (right_p)
2010 XFillRectangle (s->display, s->window, s->gc, 2755 x_fill_rectangle (s->f, s->gc,
2011 right_x - width + 1, top_y, width, bottom_y - top_y + 1); 2756 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2012 2757
2013 XSetForeground (s->display, s->gc, xgcv.foreground); 2758 XSetForeground (s->display, s->gc, xgcv.foreground);
2014 XSetClipMask (s->display, s->gc, None); 2759 x_reset_clip_rectangles (s->f, s->gc);
2015} 2760}
2016 2761
2017 2762
@@ -2142,7 +2887,7 @@ x_draw_image_foreground (struct glyph_string *s)
2142 if (s->hl == DRAW_CURSOR) 2887 if (s->hl == DRAW_CURSOR)
2143 { 2888 {
2144 int relief = eabs (s->img->relief); 2889 int relief = eabs (s->img->relief);
2145 XDrawRectangle (s->display, s->window, s->gc, 2890 x_draw_rectangle (s->f, s->gc,
2146 x - relief, y - relief, 2891 x - relief, y - relief,
2147 s->slice.width + relief*2 - 1, 2892 s->slice.width + relief*2 - 1,
2148 s->slice.height + relief*2 - 1); 2893 s->slice.height + relief*2 - 1);
@@ -2151,7 +2896,7 @@ x_draw_image_foreground (struct glyph_string *s)
2151 } 2896 }
2152 else 2897 else
2153 /* Draw a rectangle if image could not be loaded. */ 2898 /* Draw a rectangle if image could not be loaded. */
2154 XDrawRectangle (s->display, s->window, s->gc, x, y, 2899 x_draw_rectangle (s->f, s->gc, x, y,
2155 s->slice.width - 1, s->slice.height - 1); 2900 s->slice.width - 1, s->slice.height - 1);
2156} 2901}
2157 2902
@@ -2290,7 +3035,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2290 if (s->hl == DRAW_CURSOR) 3035 if (s->hl == DRAW_CURSOR)
2291 { 3036 {
2292 int r = eabs (s->img->relief); 3037 int r = eabs (s->img->relief);
2293 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r, 3038 x_draw_rectangle (s->f, s->gc, x - r, y - r,
2294 s->slice.width + r*2 - 1, 3039 s->slice.width + r*2 - 1,
2295 s->slice.height + r*2 - 1); 3040 s->slice.height + r*2 - 1);
2296 } 3041 }
@@ -2298,7 +3043,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2298 } 3043 }
2299 else 3044 else
2300 /* Draw a rectangle if image could not be loaded. */ 3045 /* Draw a rectangle if image could not be loaded. */
2301 XDrawRectangle (s->display, pixmap, s->gc, x, y, 3046 x_draw_rectangle (s->f, s->gc, x, y,
2302 s->slice.width - 1, s->slice.height - 1); 3047 s->slice.width - 1, s->slice.height - 1);
2303} 3048}
2304 3049
@@ -2313,7 +3058,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2313 { 3058 {
2314 /* Fill background with a stipple pattern. */ 3059 /* Fill background with a stipple pattern. */
2315 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 3060 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2316 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); 3061 x_fill_rectangle (s->f, s->gc, x, y, w, h);
2317 XSetFillStyle (s->display, s->gc, FillSolid); 3062 XSetFillStyle (s->display, s->gc, FillSolid);
2318 } 3063 }
2319 else 3064 else
@@ -2422,7 +3167,25 @@ x_draw_image_glyph_string (struct glyph_string *s)
2422 } 3167 }
2423 3168
2424 /* Draw the foreground. */ 3169 /* Draw the foreground. */
2425 if (pixmap != None) 3170#ifdef USE_CAIRO
3171 if (s->img->cr_data)
3172 {
3173 cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
3174
3175 int x = s->x + s->img->hmargin;
3176 int y = s->y + s->img->vmargin;
3177 int width = s->background_width;
3178
3179 cairo_set_source_surface (cr, s->img->cr_data,
3180 x - s->slice.x,
3181 y - s->slice.y);
3182 cairo_rectangle (cr, x, y, width, height);
3183 cairo_fill (cr);
3184 x_end_cr_clip (s->f);
3185 }
3186 else
3187#endif
3188 if (pixmap != None)
2426 { 3189 {
2427 x_draw_image_foreground_1 (s, pixmap); 3190 x_draw_image_foreground_1 (s, pixmap);
2428 x_set_glyph_string_clipping (s); 3191 x_set_glyph_string_clipping (s);
@@ -2505,13 +3268,13 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
2505 gc = s->face->gc; 3268 gc = s->face->gc;
2506 3269
2507 get_glyph_string_clip_rect (s, &r); 3270 get_glyph_string_clip_rect (s, &r);
2508 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted); 3271 x_set_clip_rectangles (s->f, gc, &r, 1);
2509 3272
2510 if (s->face->stipple) 3273 if (s->face->stipple)
2511 { 3274 {
2512 /* Fill background with a stipple pattern. */ 3275 /* Fill background with a stipple pattern. */
2513 XSetFillStyle (s->display, gc, FillOpaqueStippled); 3276 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2514 XFillRectangle (s->display, s->window, gc, x, y, w, h); 3277 x_fill_rectangle (s->f, gc, x, y, w, h);
2515 XSetFillStyle (s->display, gc, FillSolid); 3278 XSetFillStyle (s->display, gc, FillSolid);
2516 } 3279 }
2517 else 3280 else
@@ -2519,11 +3282,11 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
2519 XGCValues xgcv; 3282 XGCValues xgcv;
2520 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv); 3283 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2521 XSetForeground (s->display, gc, xgcv.background); 3284 XSetForeground (s->display, gc, xgcv.background);
2522 XFillRectangle (s->display, s->window, gc, x, y, w, h); 3285 x_fill_rectangle (s->f, gc, x, y, w, h);
2523 XSetForeground (s->display, gc, xgcv.foreground); 3286 XSetForeground (s->display, gc, xgcv.foreground);
2524 } 3287 }
2525 3288
2526 XSetClipMask (s->display, gc, None); 3289 x_reset_clip_rectangles (s->f, gc);
2527 } 3290 }
2528 } 3291 }
2529 else if (!s->background_filled_p) 3292 else if (!s->background_filled_p)
@@ -2560,6 +3323,10 @@ static void
2560x_draw_underwave (struct glyph_string *s) 3323x_draw_underwave (struct glyph_string *s)
2561{ 3324{
2562 int wave_height = 3, wave_length = 2; 3325 int wave_height = 3, wave_length = 2;
3326#ifdef USE_CAIRO
3327 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
3328 s->width, wave_height, wave_length);
3329#else /* not USE_CAIRO */
2563 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax; 3330 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
2564 bool odd; 3331 bool odd;
2565 XRectangle wave_clip, string_clip, final_clip; 3332 XRectangle wave_clip, string_clip, final_clip;
@@ -2609,6 +3376,7 @@ x_draw_underwave (struct glyph_string *s)
2609 3376
2610 /* Restore previous clipping rectangle(s) */ 3377 /* Restore previous clipping rectangle(s) */
2611 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted); 3378 XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, Unsorted);
3379#endif /* not USE_CAIRO */
2612} 3380}
2613 3381
2614 3382
@@ -2778,14 +3546,14 @@ x_draw_glyph_string (struct glyph_string *s)
2778 s->underline_position = position; 3546 s->underline_position = position;
2779 y = s->ybase + position; 3547 y = s->ybase + position;
2780 if (s->face->underline_defaulted_p) 3548 if (s->face->underline_defaulted_p)
2781 XFillRectangle (s->display, s->window, s->gc, 3549 x_fill_rectangle (s->f, s->gc,
2782 s->x, y, s->width, thickness); 3550 s->x, y, s->width, thickness);
2783 else 3551 else
2784 { 3552 {
2785 XGCValues xgcv; 3553 XGCValues xgcv;
2786 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3554 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2787 XSetForeground (s->display, s->gc, s->face->underline_color); 3555 XSetForeground (s->display, s->gc, s->face->underline_color);
2788 XFillRectangle (s->display, s->window, s->gc, 3556 x_fill_rectangle (s->f, s->gc,
2789 s->x, y, s->width, thickness); 3557 s->x, y, s->width, thickness);
2790 XSetForeground (s->display, s->gc, xgcv.foreground); 3558 XSetForeground (s->display, s->gc, xgcv.foreground);
2791 } 3559 }
@@ -2797,14 +3565,14 @@ x_draw_glyph_string (struct glyph_string *s)
2797 unsigned long dy = 0, h = 1; 3565 unsigned long dy = 0, h = 1;
2798 3566
2799 if (s->face->overline_color_defaulted_p) 3567 if (s->face->overline_color_defaulted_p)
2800 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3568 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2801 s->width, h); 3569 s->width, h);
2802 else 3570 else
2803 { 3571 {
2804 XGCValues xgcv; 3572 XGCValues xgcv;
2805 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3573 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2806 XSetForeground (s->display, s->gc, s->face->overline_color); 3574 XSetForeground (s->display, s->gc, s->face->overline_color);
2807 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3575 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2808 s->width, h); 3576 s->width, h);
2809 XSetForeground (s->display, s->gc, xgcv.foreground); 3577 XSetForeground (s->display, s->gc, xgcv.foreground);
2810 } 3578 }
@@ -2817,14 +3585,14 @@ x_draw_glyph_string (struct glyph_string *s)
2817 unsigned long dy = (s->height - h) / 2; 3585 unsigned long dy = (s->height - h) / 2;
2818 3586
2819 if (s->face->strike_through_color_defaulted_p) 3587 if (s->face->strike_through_color_defaulted_p)
2820 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3588 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2821 s->width, h); 3589 s->width, h);
2822 else 3590 else
2823 { 3591 {
2824 XGCValues xgcv; 3592 XGCValues xgcv;
2825 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3593 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2826 XSetForeground (s->display, s->gc, s->face->strike_through_color); 3594 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2827 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3595 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2828 s->width, h); 3596 s->width, h);
2829 XSetForeground (s->display, s->gc, xgcv.foreground); 3597 XSetForeground (s->display, s->gc, xgcv.foreground);
2830 } 3598 }
@@ -2853,7 +3621,7 @@ x_draw_glyph_string (struct glyph_string *s)
2853 x_draw_glyph_string_foreground (prev); 3621 x_draw_glyph_string_foreground (prev);
2854 else 3622 else
2855 x_draw_composite_glyph_string_foreground (prev); 3623 x_draw_composite_glyph_string_foreground (prev);
2856 XSetClipMask (prev->display, prev->gc, None); 3624 x_reset_clip_rectangles (prev->f, prev->gc);
2857 prev->hl = save; 3625 prev->hl = save;
2858 prev->num_clips = 0; 3626 prev->num_clips = 0;
2859 } 3627 }
@@ -2878,7 +3646,7 @@ x_draw_glyph_string (struct glyph_string *s)
2878 x_draw_glyph_string_foreground (next); 3646 x_draw_glyph_string_foreground (next);
2879 else 3647 else
2880 x_draw_composite_glyph_string_foreground (next); 3648 x_draw_composite_glyph_string_foreground (next);
2881 XSetClipMask (next->display, next->gc, None); 3649 x_reset_clip_rectangles (next->f, next->gc);
2882 next->hl = save; 3650 next->hl = save;
2883 next->num_clips = 0; 3651 next->num_clips = 0;
2884 next->clip_head = s->next; 3652 next->clip_head = s->next;
@@ -2887,7 +3655,7 @@ x_draw_glyph_string (struct glyph_string *s)
2887 } 3655 }
2888 3656
2889 /* Reset clipping. */ 3657 /* Reset clipping. */
2890 XSetClipMask (s->display, s->gc, None); 3658 x_reset_clip_rectangles (s->f, s->gc);
2891 s->num_clips = 0; 3659 s->num_clips = 0;
2892} 3660}
2893 3661
@@ -2918,11 +3686,32 @@ x_delete_glyphs (struct frame *f, register int n)
2918/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable. 3686/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2919 If they are <= 0, this is probably an error. */ 3687 If they are <= 0, this is probably an error. */
2920 3688
3689static void
3690x_clear_area1 (Display *dpy, Window window,
3691 int x, int y, int width, int height, int exposures)
3692{
3693 eassert (width > 0 && height > 0);
3694 XClearArea (dpy, window, x, y, width, height, exposures);
3695}
3696
3697
2921void 3698void
2922x_clear_area (Display *dpy, Window window, int x, int y, int width, int height) 3699x_clear_area (struct frame *f, int x, int y, int width, int height)
2923{ 3700{
3701#ifdef USE_CAIRO
3702 cairo_t *cr;
3703
2924 eassert (width > 0 && height > 0); 3704 eassert (width > 0 && height > 0);
2925 XClearArea (dpy, window, x, y, width, height, False); 3705
3706 cr = x_begin_cr_clip (f, NULL);
3707 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
3708 cairo_rectangle (cr, x, y, width, height);
3709 cairo_fill (cr);
3710 x_end_cr_clip (f);
3711#else
3712 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3713 x, y, width, height, False);
3714#endif
2926} 3715}
2927 3716
2928 3717
@@ -2937,7 +3726,7 @@ x_clear_frame (struct frame *f)
2937 3726
2938 block_input (); 3727 block_input ();
2939 3728
2940 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 3729 x_clear_window (f);
2941 3730
2942 /* We have to clear the scroll bars. If we have changed colors or 3731 /* We have to clear the scroll bars. If we have changed colors or
2943 something like that, then they should be notified. */ 3732 something like that, then they should be notified. */
@@ -3243,12 +4032,16 @@ x_scroll_run (struct window *w, struct run *run)
3243 /* Cursor off. Will be switched on again in x_update_window_end. */ 4032 /* Cursor off. Will be switched on again in x_update_window_end. */
3244 x_clear_cursor (w); 4033 x_clear_cursor (w);
3245 4034
4035#ifdef USE_CAIRO
4036 SET_FRAME_GARBAGED (f);
4037#else
3246 XCopyArea (FRAME_X_DISPLAY (f), 4038 XCopyArea (FRAME_X_DISPLAY (f),
3247 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), 4039 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3248 f->output_data.x->normal_gc, 4040 f->output_data.x->normal_gc,
3249 x, from_y, 4041 x, from_y,
3250 width, height, 4042 width, height,
3251 x, to_y); 4043 x, to_y);
4044#endif
3252 4045
3253 unblock_input (); 4046 unblock_input ();
3254} 4047}
@@ -4157,7 +4950,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4157 dpyinfo->last_mouse_glyph_frame = f1; 4950 dpyinfo->last_mouse_glyph_frame = f1;
4158 4951
4159 *bar_window = Qnil; 4952 *bar_window = Qnil;
4160 *part = scroll_bar_above_handle; 4953 *part = 0;
4161 *fp = f1; 4954 *fp = f1;
4162 XSETINT (*x, win_x); 4955 XSETINT (*x, win_x);
4163 XSETINT (*y, win_y); 4956 XSETINT (*y, win_y);
@@ -4251,7 +5044,7 @@ x_window_to_menu_bar (Window window)
4251#ifdef USE_TOOLKIT_SCROLL_BARS 5044#ifdef USE_TOOLKIT_SCROLL_BARS
4252 5045
4253static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part, 5046static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
4254 int, int, bool); 5047 int, int, bool);
4255 5048
4256/* Lisp window being scrolled. Set when starting to interact with 5049/* Lisp window being scrolled. Set when starting to interact with
4257 a toolkit scroll bar, reset to nil when ending the interaction. */ 5050 a toolkit scroll bar, reset to nil when ending the interaction. */
@@ -5508,8 +6301,7 @@ x_scroll_bar_create (struct window *w, int top, int left,
5508 for the case that a window has been split horizontally. In 6301 for the case that a window has been split horizontally. In
5509 this case, no clear_frame is generated to reduce flickering. */ 6302 this case, no clear_frame is generated to reduce flickering. */
5510 if (width > 0 && window_box_height (w) > 0) 6303 if (width > 0 && window_box_height (w) > 0)
5511 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6304 x_clear_area (f, left, top, width, window_box_height (w));
5512 left, top, width, window_box_height (w));
5513 6305
5514 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6306 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5515 /* Position and size of scroll bar. */ 6307 /* Position and size of scroll bar. */
@@ -5641,7 +6433,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5641 /* Draw the empty space above the handle. Note that we can't clear 6433 /* Draw the empty space above the handle. Note that we can't clear
5642 zero-height areas; that means "clear to end of window." */ 6434 zero-height areas; that means "clear to end of window." */
5643 if ((inside_width > 0) && (start > 0)) 6435 if ((inside_width > 0) && (start > 0))
5644 x_clear_area (FRAME_X_DISPLAY (f), w, 6436 x_clear_area1 (FRAME_X_DISPLAY (f), w,
5645 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6437 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5646 VERTICAL_SCROLL_BAR_TOP_BORDER, 6438 VERTICAL_SCROLL_BAR_TOP_BORDER,
5647 inside_width, start); 6439 inside_width, start);
@@ -5652,7 +6444,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5652 f->output_data.x->scroll_bar_foreground_pixel); 6444 f->output_data.x->scroll_bar_foreground_pixel);
5653 6445
5654 /* Draw the handle itself. */ 6446 /* Draw the handle itself. */
5655 XFillRectangle (FRAME_X_DISPLAY (f), w, gc, 6447 x_fill_rectangle (f, gc,
5656 /* x, y, width, height */ 6448 /* x, y, width, height */
5657 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6449 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5658 VERTICAL_SCROLL_BAR_TOP_BORDER + start, 6450 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
@@ -5666,7 +6458,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5666 /* Draw the empty space below the handle. Note that we can't 6458 /* Draw the empty space below the handle. Note that we can't
5667 clear zero-height areas; that means "clear to end of window." */ 6459 clear zero-height areas; that means "clear to end of window." */
5668 if ((inside_width > 0) && (end < inside_height)) 6460 if ((inside_width > 0) && (end < inside_height))
5669 x_clear_area (FRAME_X_DISPLAY (f), w, 6461 x_clear_area1 (FRAME_X_DISPLAY (f), w,
5670 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6462 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5671 VERTICAL_SCROLL_BAR_TOP_BORDER + end, 6463 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
5672 inside_width, inside_height - end); 6464 inside_width, inside_height - end);
@@ -5733,8 +6525,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5733 if (width > 0 && height > 0) 6525 if (width > 0 && height > 0)
5734 { 6526 {
5735 block_input (); 6527 block_input ();
5736 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6528 x_clear_area (f, left, top, width, height);
5737 left, top, width, height);
5738 unblock_input (); 6529 unblock_input ();
5739 } 6530 }
5740 6531
@@ -5766,8 +6557,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5766 /* Since toolkit scroll bars are smaller than the space reserved 6557 /* Since toolkit scroll bars are smaller than the space reserved
5767 for them on the frame, we have to clear "under" them. */ 6558 for them on the frame, we have to clear "under" them. */
5768 if (width > 0 && height > 0) 6559 if (width > 0 && height > 0)
5769 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6560 x_clear_area (f, left, top, width, height);
5770 left, top, width, height);
5771#ifdef USE_GTK 6561#ifdef USE_GTK
5772 xg_update_scrollbar_pos (f, bar->x_window, top, 6562 xg_update_scrollbar_pos (f, bar->x_window, top,
5773 left, width, max (height, 1)); 6563 left, width, max (height, 1));
@@ -5853,8 +6643,7 @@ XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int posit
5853 6643
5854 /* Clear also part between window_width and 6644 /* Clear also part between window_width and
5855 WINDOW_PIXEL_WIDTH. */ 6645 WINDOW_PIXEL_WIDTH. */
5856 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6646 x_clear_area (f, left, top, pixel_width, height);
5857 left, top, pixel_width, height);
5858 unblock_input (); 6647 unblock_input ();
5859 } 6648 }
5860 6649
@@ -5885,7 +6674,7 @@ XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int posit
5885 /* Since toolkit scroll bars are smaller than the space reserved 6674 /* Since toolkit scroll bars are smaller than the space reserved
5886 for them on the frame, we have to clear "under" them. */ 6675 for them on the frame, we have to clear "under" them. */
5887 if (width > 0 && height > 0) 6676 if (width > 0 && height > 0)
5888 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6677 x_clear_area (f,
5889 WINDOW_LEFT_EDGE_X (w), top, 6678 WINDOW_LEFT_EDGE_X (w), top,
5890 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); 6679 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
5891#ifdef USE_GTK 6680#ifdef USE_GTK
@@ -6131,7 +6920,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
6131 f->output_data.x->scroll_bar_foreground_pixel); 6920 f->output_data.x->scroll_bar_foreground_pixel);
6132 6921
6133 /* Draw a one-pixel border just inside the edges of the scroll bar. */ 6922 /* Draw a one-pixel border just inside the edges of the scroll bar. */
6134 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc, 6923 x_draw_rectangle (f, gc,
6135 /* x, y, width, height */ 6924 /* x, y, width, height */
6136 0, 0, bar->width - 1, bar->height - 1); 6925 0, 0, bar->width - 1, bar->height - 1);
6137 6926
@@ -6915,11 +7704,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6915 } 7704 }
6916 else 7705 else
6917 { 7706 {
6918#ifdef USE_GTK 7707#if defined (USE_GTK) && ! defined (HAVE_GTK3) && ! defined (USE_CAIRO)
6919 /* This seems to be needed for GTK 2.6 and later, see 7708 /* This seems to be needed for GTK 2.6 and later, see
6920 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ 7709 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
6921 x_clear_area (event->xexpose.display, 7710 x_clear_area (f,
6922 event->xexpose.window,
6923 event->xexpose.x, event->xexpose.y, 7711 event->xexpose.x, event->xexpose.y,
6924 event->xexpose.width, event->xexpose.height); 7712 event->xexpose.width, event->xexpose.height);
6925#endif 7713#endif
@@ -7529,6 +8317,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7529 8317
7530 case ConfigureNotify: 8318 case ConfigureNotify:
7531 f = x_top_window_to_frame (dpyinfo, event->xconfigure.window); 8319 f = x_top_window_to_frame (dpyinfo, event->xconfigure.window);
8320#ifdef USE_CAIRO
8321 if (f) x_cr_destroy_surface (f);
8322#endif
7532#ifdef USE_GTK 8323#ifdef USE_GTK
7533 if (!f 8324 if (!f
7534 && (f = any) 8325 && (f = any)
@@ -7536,6 +8327,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7536 { 8327 {
7537 xg_frame_resized (f, event->xconfigure.width, 8328 xg_frame_resized (f, event->xconfigure.width,
7538 event->xconfigure.height); 8329 event->xconfigure.height);
8330#ifdef USE_CAIRO
8331 x_cr_destroy_surface (f);
8332#endif
7539 f = 0; 8333 f = 0;
7540 } 8334 }
7541#endif 8335#endif
@@ -7957,7 +8751,7 @@ x_clip_to_row (struct window *w, struct glyph_row *row,
7957 clip_rect.width = window_width; 8751 clip_rect.width = window_width;
7958 clip_rect.height = row->visible_height; 8752 clip_rect.height = row->visible_height;
7959 8753
7960 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted); 8754 x_set_clip_rectangles (f, gc, &clip_rect, 1);
7961} 8755}
7962 8756
7963 8757
@@ -8006,8 +8800,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
8006 } 8800 }
8007 /* Set clipping, draw the rectangle, and reset clipping again. */ 8801 /* Set clipping, draw the rectangle, and reset clipping again. */
8008 x_clip_to_row (w, row, TEXT_AREA, gc); 8802 x_clip_to_row (w, row, TEXT_AREA, gc);
8009 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1); 8803 x_draw_rectangle (f, gc, x, y, wd, h - 1);
8010 XSetClipMask (dpy, gc, None); 8804 x_reset_clip_rectangles (f, gc);
8011} 8805}
8012 8806
8013 8807
@@ -8085,7 +8879,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8085 if ((cursor_glyph->resolved_level & 1) != 0) 8879 if ((cursor_glyph->resolved_level & 1) != 0)
8086 x += cursor_glyph->pixel_width - width; 8880 x += cursor_glyph->pixel_width - width;
8087 8881
8088 XFillRectangle (dpy, window, gc, x, 8882 x_fill_rectangle (f, gc, x,
8089 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), 8883 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8090 width, row->height); 8884 width, row->height);
8091 } 8885 }
@@ -8105,13 +8899,13 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8105 if ((cursor_glyph->resolved_level & 1) != 0 8899 if ((cursor_glyph->resolved_level & 1) != 0
8106 && cursor_glyph->pixel_width > w->phys_cursor_width - 1) 8900 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
8107 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; 8901 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
8108 XFillRectangle (dpy, window, gc, x, 8902 x_fill_rectangle (f, gc, x,
8109 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + 8903 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
8110 row->height - width), 8904 row->height - width),
8111 w->phys_cursor_width - 1, width); 8905 w->phys_cursor_width - 1, width);
8112 } 8906 }
8113 8907
8114 XSetClipMask (dpy, gc, None); 8908 x_reset_clip_rectangles (f, gc);
8115 } 8909 }
8116} 8910}
8117 8911
@@ -8133,7 +8927,7 @@ x_define_frame_cursor (struct frame *f, Cursor cursor)
8133static void 8927static void
8134x_clear_frame_area (struct frame *f, int x, int y, int width, int height) 8928x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
8135{ 8929{
8136 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), x, y, width, height); 8930 x_clear_area (f, x, y, width, height);
8137#ifdef USE_GTK 8931#ifdef USE_GTK
8138 /* Must queue a redraw, because scroll bars might have been cleared. */ 8932 /* Must queue a redraw, because scroll bars might have been cleared. */
8139 if (FRAME_GTK_WIDGET (f)) 8933 if (FRAME_GTK_WIDGET (f))
@@ -10247,6 +11041,7 @@ x_free_frame_resources (struct frame *f)
10247 free_frame_xic (f); 11041 free_frame_xic (f);
10248#endif 11042#endif
10249 11043
11044 x_free_cr_resources (f);
10250#ifdef USE_X_TOOLKIT 11045#ifdef USE_X_TOOLKIT
10251 if (f->output_data.x->widget) 11046 if (f->output_data.x->widget)
10252 { 11047 {
@@ -11333,6 +12128,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
11333 x_session_initialize (dpyinfo); 12128 x_session_initialize (dpyinfo);
11334#endif 12129#endif
11335 12130
12131#ifdef USE_CAIRO
12132 x_extension_initialize (dpyinfo);
12133#endif
12134
11336 unblock_input (); 12135 unblock_input ();
11337 12136
11338 return dpyinfo; 12137 return dpyinfo;
@@ -11444,8 +12243,13 @@ static struct redisplay_interface x_redisplay_interface =
11444 x_get_glyph_overhangs, 12243 x_get_glyph_overhangs,
11445 x_fix_overlapping_area, 12244 x_fix_overlapping_area,
11446 x_draw_fringe_bitmap, 12245 x_draw_fringe_bitmap,
12246#ifdef USE_CAIRO
12247 x_cr_define_fringe_bitmap,
12248 x_cr_destroy_fringe_bitmap,
12249#else
11447 0, /* define_fringe_bitmap */ 12250 0, /* define_fringe_bitmap */
11448 0, /* destroy_fringe_bitmap */ 12251 0, /* destroy_fringe_bitmap */
12252#endif
11449 x_compute_glyph_string_overhangs, 12253 x_compute_glyph_string_overhangs,
11450 x_draw_glyph_string, 12254 x_draw_glyph_string,
11451 x_define_frame_cursor, 12255 x_define_frame_cursor,
@@ -11623,6 +12427,10 @@ x_initialize (void)
11623#endif 12427#endif
11624#endif 12428#endif
11625 12429
12430#ifdef USE_CAIRO
12431 x_cr_init_fringe (&x_redisplay_interface);
12432#endif
12433
11626 /* Note that there is no real way portable across R3/R4 to get the 12434 /* Note that there is no real way portable across R3/R4 to get the
11627 original error handler. */ 12435 original error handler. */
11628 XSetErrorHandler (x_error_handler); 12436 XSetErrorHandler (x_error_handler);
diff --git a/src/xterm.h b/src/xterm.h
index 0366261b2f4..3081c1653e3 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -70,6 +70,19 @@ typedef GtkWidget *xt_or_gtk_widget;
70#define USE_GTK_TOOLTIP 70#define USE_GTK_TOOLTIP
71#endif 71#endif
72 72
73#ifdef USE_CAIRO
74#include <cairo-xlib.h>
75#ifdef CAIRO_HAS_PDF_SURFACE
76#include <cairo-pdf.h>
77#endif
78#ifdef CAIRO_HAS_PS_SURFACE
79#include <cairo-ps.h>
80#endif
81#ifdef CAIRO_HAS_SVG_SURFACE
82#include <cairo-svg.h>
83#endif
84#endif
85
73#ifdef HAVE_X_I18N 86#ifdef HAVE_X_I18N
74#include <X11/Xlocale.h> 87#include <X11/Xlocale.h>
75#endif 88#endif
@@ -115,6 +128,9 @@ struct xim_inst_t
115 128
116struct x_bitmap_record 129struct x_bitmap_record
117{ 130{
131#ifdef USE_CAIRO
132 void *img;
133#endif
118 Pixmap pixmap; 134 Pixmap pixmap;
119 bool have_mask; 135 bool have_mask;
120 Pixmap mask; 136 Pixmap mask;
@@ -124,6 +140,19 @@ struct x_bitmap_record
124 int height, width, depth; 140 int height, width, depth;
125}; 141};
126 142
143#ifdef USE_CAIRO
144struct x_gc_ext_data
145{
146#define MAX_CLIP_RECTS 2
147 /* Number of clipping rectangles. */
148 int n_clip_rects;
149
150 /* Clipping rectangles. */
151 XRectangle clip_rects[MAX_CLIP_RECTS];
152};
153#endif
154
155
127/* For each X display, we have a structure that records 156/* For each X display, we have a structure that records
128 information about it. */ 157 information about it. */
129 158
@@ -411,6 +440,10 @@ struct x_display_info
411 440
412 /* SM */ 441 /* SM */
413 Atom Xatom_SM_CLIENT_ID; 442 Atom Xatom_SM_CLIENT_ID;
443
444#ifdef USE_CAIRO
445 XExtCodes *ext_codes;
446#endif
414}; 447};
415 448
416#ifdef HAVE_X_I18N 449#ifdef HAVE_X_I18N
@@ -636,7 +669,6 @@ struct x_output
636 /* The offset we need to add to compensate for type A WMs. */ 669 /* The offset we need to add to compensate for type A WMs. */
637 int move_offset_top; 670 int move_offset_top;
638 int move_offset_left; 671 int move_offset_left;
639};
640 672
641/* Extreme 'short' and 'long' values suitable for libX11. */ 673/* Extreme 'short' and 'long' values suitable for libX11. */
642#define X_SHRT_MAX 0x7fff 674#define X_SHRT_MAX 0x7fff
@@ -645,6 +677,14 @@ struct x_output
645#define X_LONG_MIN (-1 - X_LONG_MAX) 677#define X_LONG_MIN (-1 - X_LONG_MAX)
646#define X_ULONG_MAX 0xffffffffUL 678#define X_ULONG_MAX 0xffffffffUL
647 679
680#ifdef USE_CAIRO
681 /* Cairo drawing context. */
682 cairo_t *cr_context;
683 /* Cairo surface for double buffering */
684 cairo_surface_t *cr_surface;
685#endif
686};
687
648#define No_Cursor (None) 688#define No_Cursor (None)
649 689
650enum 690enum
@@ -991,7 +1031,8 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
991 double, int); 1031 double, int);
992#endif 1032#endif
993extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); 1033extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *);
994extern void x_clear_area (Display *, Window, int, int, int, int); 1034extern void x_query_color (struct frame *f, XColor *);
1035extern void x_clear_area (struct frame *f, int, int, int, int);
995#if !defined USE_X_TOOLKIT && !defined USE_GTK 1036#if !defined USE_X_TOOLKIT && !defined USE_GTK
996extern void x_mouse_leave (struct x_display_info *); 1037extern void x_mouse_leave (struct x_display_info *);
997#endif 1038#endif
@@ -1000,6 +1041,14 @@ extern void x_mouse_leave (struct x_display_info *);
1000extern int x_dispatch_event (XEvent *, Display *); 1041extern int x_dispatch_event (XEvent *, Display *);
1001#endif 1042#endif
1002extern int x_x_to_emacs_modifiers (struct x_display_info *, int); 1043extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
1044#ifdef USE_CAIRO
1045extern cairo_t *x_begin_cr_clip (struct frame *, GC);
1046extern void x_end_cr_clip (struct frame *);
1047extern void x_set_cr_source_with_gc_foreground (struct frame *, GC);
1048extern void x_set_cr_source_with_gc_background (struct frame *, GC);
1049extern void x_cr_draw_frame (cairo_t *, struct frame *);
1050extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
1051#endif
1003 1052
1004INLINE int 1053INLINE int
1005x_display_pixel_height (struct x_display_info *dpyinfo) 1054x_display_pixel_height (struct x_display_info *dpyinfo)