diff options
| -rw-r--r-- | ChangeLog.1 | 21 | ||||
| -rw-r--r-- | configure.ac | 30 | ||||
| -rw-r--r-- | lisp/ChangeLog.17 | 6 | ||||
| -rw-r--r-- | lisp/version.el | 7 | ||||
| -rw-r--r-- | lwlib/ChangeLog.1 | 3 | ||||
| -rw-r--r-- | lwlib/Makefile.in | 2 | ||||
| -rw-r--r-- | src/ChangeLog.13 | 236 | ||||
| -rw-r--r-- | src/Makefile.in | 8 | ||||
| -rw-r--r-- | src/dispextern.h | 7 | ||||
| -rw-r--r-- | src/font.c | 4 | ||||
| -rw-r--r-- | src/font.h | 4 | ||||
| -rw-r--r-- | src/fringe.c | 24 | ||||
| -rw-r--r-- | src/ftcrfont.c | 320 | ||||
| -rw-r--r-- | src/ftfont.c | 26 | ||||
| -rw-r--r-- | src/ftfont.h | 5 | ||||
| -rw-r--r-- | src/gtkutil.c | 128 | ||||
| -rw-r--r-- | src/gtkutil.h | 6 | ||||
| -rw-r--r-- | src/image.c | 379 | ||||
| -rw-r--r-- | src/xfns.c | 193 | ||||
| -rw-r--r-- | src/xterm.c | 998 | ||||
| -rw-r--r-- | src/xterm.h | 53 |
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 @@ | |||
| 1 | 2015-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 | |||
| 1 | 2015-04-07 Paul Eggert <eggert@cs.ucla.edu> | 6 | 2015-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 | ||
| 12 | 2015-04-05 Jan Djärv <jan.h.d@swipnet.se> | ||
| 13 | |||
| 14 | * configure.ac: Allow rsvg with cairo. Move back HAVE_RSVG. | ||
| 15 | |||
| 16 | 2015-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 | |||
| 7 | 2015-04-03 Paul Eggert <eggert@cs.ucla.edu> | 21 | 2015-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 | ||
| 125 | 2015-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 | |||
| 111 | 2015-02-09 Paul Eggert <eggert@cs.ucla.edu> | 132 | 2015-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]) | |||
| 330 | OPTION_DEFAULT_ON([gif],[don't compile with GIF image support]) | 330 | OPTION_DEFAULT_ON([gif],[don't compile with GIF image support]) |
| 331 | OPTION_DEFAULT_ON([png],[don't compile with PNG image support]) | 331 | OPTION_DEFAULT_ON([png],[don't compile with PNG image support]) |
| 332 | OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support]) | 332 | OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support]) |
| 333 | OPTION_DEFAULT_OFF([cairo],[compile with Cairo drawing]) | ||
| 333 | OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support]) | 334 | OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support]) |
| 334 | OPTION_DEFAULT_ON([imagemagick],[don't compile with ImageMagick image support]) | 335 | OPTION_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) | |||
| 3075 | AC_SUBST(M17N_FLT_CFLAGS) | 3077 | AC_SUBST(M17N_FLT_CFLAGS) |
| 3076 | AC_SUBST(M17N_FLT_LIBS) | 3078 | AC_SUBST(M17N_FLT_LIBS) |
| 3077 | 3079 | ||
| 3080 | USE_CAIRO=no | ||
| 3081 | if 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 | ||
| 3097 | fi | ||
| 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" | |||
| 4009 | OLDLIBS="$LIBS" | 4030 | OLDLIBS="$LIBS" |
| 4010 | CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS" | 4031 | CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS" |
| 4011 | LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS" | 4032 | LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS" |
| 4012 | CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS" | 4033 | CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS $CAIRO_CFLAGS" |
| 4013 | LIBS="$LIBS $GFILENOTIFY_LIBS" | 4034 | LIBS="$LIBS $GFILENOTIFY_LIBS $CAIRO_LIBS" |
| 4014 | AC_MSG_CHECKING([whether GLib is linked in]) | 4035 | AC_MSG_CHECKING([whether GLib is linked in]) |
| 4015 | AC_LINK_IFELSE([AC_LANG_PROGRAM( | 4036 | AC_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}" | |||
| 5142 | echo " Does Emacs use a gif library? ${HAVE_GIF} $LIBGIF" | 5165 | echo " Does Emacs use a gif library? ${HAVE_GIF} $LIBGIF" |
| 5143 | echo " Does Emacs use a png library? ${HAVE_PNG} $LIBPNG" | 5166 | echo " Does Emacs use a png library? ${HAVE_PNG} $LIBPNG" |
| 5144 | echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}" | 5167 | echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}" |
| 5168 | echo " Does Emacs use cairo? ${USE_CAIRO}" | ||
| 5145 | echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}" | 5169 | echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}" |
| 5146 | 5170 | ||
| 5147 | echo " Does Emacs support sound? ${HAVE_SOUND}" | 5171 | echo " 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 | ||
| 1751 | 2015-02-11 Martin Rudalics <rudalics@gmx.at> | 1751 | 2015-02-11 Martin Rudalics <rudalics@gmx.at> |
| 1752 | 1752 | ||
| 1753 | 2015-02-11 Jan Djärv <jan.h.d@swipnet.se> | ||
| 1754 | |||
| 1755 | * version.el (emacs-version): Add cairo version. | ||
| 1756 | |||
| 1757 | 2015-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 @@ | |||
| 1 | 2015-04-03 Jan Djärv <jan.h.d@swipnet.se> | ||
| 2 | |||
| 3 | * Makefile.in (CAIRO_CFLAGS): Add. | ||
| 1 | 2015-03-18 Stefan Monnier <monnier@iro.umontreal.ca> | 4 | 2015-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@ | |||
| 33 | PROFILING_CFLAGS = @PROFILING_CFLAGS@ | 33 | PROFILING_CFLAGS = @PROFILING_CFLAGS@ |
| 34 | WARN_CFLAGS = `echo @WARN_CFLAGS@ | sed 's/ -Wwrite-strings//'` | 34 | WARN_CFLAGS = `echo @WARN_CFLAGS@ | sed 's/ -Wwrite-strings//'` |
| 35 | WERROR_CFLAGS = @WERROR_CFLAGS@ | 35 | WERROR_CFLAGS = @WERROR_CFLAGS@ |
| 36 | CAIRO_CFLAGS= @CAIRO_CFLAGS@ | ||
| 36 | 37 | ||
| 37 | CC=@CC@ | 38 | CC=@CC@ |
| 38 | CFLAGS=@CFLAGS@ | 39 | CFLAGS=@CFLAGS@ |
| @@ -88,6 +89,7 @@ endif | |||
| 88 | ALL_CFLAGS= $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ | 89 | ALL_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 @@ | |||
| 1 | 2015-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 | |||
| 9 | 2015-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 | |||
| 28 | 2015-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 | |||
| 1 | 2015-04-06 Koichi Arakawa <arakawa@pp.iij4u.or.jp> (tiny change) | 34 | 2015-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 | ||
| 40 | 2015-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 | |||
| 7 | 2015-04-04 Jan Djärv <jan.h.d@swipnet.se> | 49 | 2015-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 | ||
| 16 | 2015-04-03 Jan Djärv <jan.h.d@swipnet.se> | 58 | 2015-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 | ||
| 21 | 2015-03-31 Eli Zaretskii <eliz@gnu.org> | 72 | 2015-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 | ||
| 613 | 2015-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 | |||
| 617 | 2015-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 | |||
| 625 | 2015-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 | |||
| 653 | 2015-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 | |||
| 660 | 2015-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 | |||
| 562 | 2015-02-11 Martin Rudalics <rudalics@gmx.at> | 798 | 2015-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@ | |||
| 218 | RSVG_LIBS= @RSVG_LIBS@ | 218 | RSVG_LIBS= @RSVG_LIBS@ |
| 219 | RSVG_CFLAGS= @RSVG_CFLAGS@ | 219 | RSVG_CFLAGS= @RSVG_CFLAGS@ |
| 220 | 220 | ||
| 221 | CAIRO_LIBS= @CAIRO_LIBS@ | ||
| 222 | CAIRO_CFLAGS= @CAIRO_CFLAGS@ | ||
| 223 | |||
| 221 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ | 224 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ |
| 222 | IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ | 225 | IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ |
| 223 | 226 | ||
| @@ -273,6 +276,7 @@ W32_RES_LINK=@W32_RES_LINK@ | |||
| 273 | ## Empty if !HAVE_X_WINDOWS | 276 | ## Empty if !HAVE_X_WINDOWS |
| 274 | ## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT | 277 | ## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT |
| 275 | ## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE | 278 | ## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE |
| 279 | ## ftfont.o ftcrfont.o if USE_CAIRO | ||
| 276 | ## else xfont.o | 280 | ## else xfont.o |
| 277 | FONT_OBJ=@FONT_OBJ@ | 281 | FONT_OBJ=@FONT_OBJ@ |
| 278 | 282 | ||
| @@ -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) |
| 355 | ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) | 359 | ALL_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); | |||
| 3302 | void w32_init_fringe (struct redisplay_interface *); | 3306 | void w32_init_fringe (struct redisplay_interface *); |
| 3303 | void w32_reset_fringes (void); | 3307 | void w32_reset_fringes (void); |
| 3304 | #endif | 3308 | #endif |
| 3309 | #ifdef USE_CAIRO | ||
| 3310 | void x_cr_init_fringe (struct redisplay_interface *); | ||
| 3311 | #endif | ||
| 3305 | 3312 | ||
| 3306 | extern unsigned row_hash (struct glyph_row *); | 3313 | extern 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; | |||
| 844 | extern void syms_of_nsfont (void); | 844 | extern void syms_of_nsfont (void); |
| 845 | extern void syms_of_macfont (void); | 845 | extern void syms_of_macfont (void); |
| 846 | #endif /* HAVE_NS */ | 846 | #endif /* HAVE_NS */ |
| 847 | #ifdef USE_CAIRO | ||
| 848 | extern struct font_driver ftcrfont_driver; | ||
| 849 | extern void syms_of_ftcrfont (void); | ||
| 850 | #endif | ||
| 847 | 851 | ||
| 848 | #ifndef FONT_DEBUG | 852 | #ifndef FONT_DEBUG |
| 849 | #define FONT_DEBUG | 853 | #define FONT_DEBUG |
diff --git a/src/fringe.c b/src/fringe.c index 5e5ec60a48f..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 | ||
| 1736 | void | 1752 | void |
| 1753 | #ifdef HAVE_NTGUI | ||
| 1737 | w32_init_fringe (struct redisplay_interface *rif) | 1754 | w32_init_fringe (struct redisplay_interface *rif) |
| 1755 | #else | ||
| 1756 | x_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 | ||
| 1751 | void | 1773 | void |
| 1752 | w32_reset_fringes (void) | 1774 | w32_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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | #include <stdio.h> | ||
| 22 | #include <cairo-ft.h> | ||
| 23 | |||
| 24 | #include "lisp.h" | ||
| 25 | #include "dispextern.h" | ||
| 26 | #include "xterm.h" | ||
| 27 | #include "frame.h" | ||
| 28 | #include "blockinput.h" | ||
| 29 | #include "character.h" | ||
| 30 | #include "charset.h" | ||
| 31 | #include "fontset.h" | ||
| 32 | #include "font.h" | ||
| 33 | #include "ftfont.h" | ||
| 34 | |||
| 35 | /* FTCR font driver. */ | ||
| 36 | |||
| 37 | /* The actual structure for ftcr font that can be casted to struct | ||
| 38 | font. */ | ||
| 39 | |||
| 40 | struct ftcrfont_info | ||
| 41 | { | ||
| 42 | struct font font; | ||
| 43 | /* The following six members must be here in this order to be | ||
| 44 | compatible with struct ftfont_info (in ftfont.c). */ | ||
| 45 | #ifdef HAVE_LIBOTF | ||
| 46 | bool maybe_otf; /* Flag to tell if this may be OTF or not. */ | ||
| 47 | OTF *otf; | ||
| 48 | #endif /* HAVE_LIBOTF */ | ||
| 49 | FT_Size ft_size; | ||
| 50 | int index; | ||
| 51 | FT_Matrix matrix; | ||
| 52 | |||
| 53 | cairo_font_face_t *cr_font_face; | ||
| 54 | /* To prevent cairo from cluttering the activated FT_Size maintained | ||
| 55 | in ftfont.c, we activate this special FT_Size before drawing. */ | ||
| 56 | FT_Size ft_size_draw; | ||
| 57 | /* Font metrics cache. */ | ||
| 58 | struct font_metrics **metrics; | ||
| 59 | short metrics_nrows; | ||
| 60 | }; | ||
| 61 | |||
| 62 | #define METRICS_NCOLS_PER_ROW (128) | ||
| 63 | |||
| 64 | enum metrics_status | ||
| 65 | { | ||
| 66 | METRICS_INVALID = -1, /* metrics entry is invalid */ | ||
| 67 | }; | ||
| 68 | |||
| 69 | #define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent) | ||
| 70 | #define METRICS_SET_STATUS(metrics, status) \ | ||
| 71 | ((metrics)->ascent = 0, (metrics)->descent = (status)) | ||
| 72 | |||
| 73 | /* Prototypes for helper function. */ | ||
| 74 | static int ftcrfont_glyph_extents (struct font *, unsigned, | ||
| 75 | struct font_metrics *); | ||
| 76 | |||
| 77 | /* Prototypes for font-driver methods. */ | ||
| 78 | static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object); | ||
| 79 | static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object); | ||
| 80 | static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int); | ||
| 81 | static void ftcrfont_close (struct font *); | ||
| 82 | static void ftcrfont_text_extents (struct font *, unsigned *, int, | ||
| 83 | struct font_metrics *); | ||
| 84 | static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool); | ||
| 85 | |||
| 86 | struct font_driver ftcrfont_driver; | ||
| 87 | |||
| 88 | static int | ||
| 89 | ftcrfont_glyph_extents (struct font *font, | ||
| 90 | unsigned glyph, | ||
| 91 | struct font_metrics *metrics) | ||
| 92 | { | ||
| 93 | struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font; | ||
| 94 | int row, col; | ||
| 95 | struct font_metrics *cache; | ||
| 96 | |||
| 97 | row = glyph / METRICS_NCOLS_PER_ROW; | ||
| 98 | col = glyph % METRICS_NCOLS_PER_ROW; | ||
| 99 | if (row >= ftcrfont_info->metrics_nrows) | ||
| 100 | { | ||
| 101 | ftcrfont_info->metrics = | ||
| 102 | xrealloc (ftcrfont_info->metrics, | ||
| 103 | sizeof (struct font_metrics *) * (row + 1)); | ||
| 104 | bzero (ftcrfont_info->metrics + ftcrfont_info->metrics_nrows, | ||
| 105 | (sizeof (struct font_metrics *) | ||
| 106 | * (row + 1 - ftcrfont_info->metrics_nrows))); | ||
| 107 | ftcrfont_info->metrics_nrows = row + 1; | ||
| 108 | } | ||
| 109 | if (ftcrfont_info->metrics[row] == NULL) | ||
| 110 | { | ||
| 111 | struct font_metrics *new; | ||
| 112 | int i; | ||
| 113 | |||
| 114 | new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW); | ||
| 115 | for (i = 0; i < METRICS_NCOLS_PER_ROW; i++) | ||
| 116 | METRICS_SET_STATUS (new + i, METRICS_INVALID); | ||
| 117 | ftcrfont_info->metrics[row] = new; | ||
| 118 | } | ||
| 119 | cache = ftcrfont_info->metrics[row] + col; | ||
| 120 | |||
| 121 | if (METRICS_STATUS (cache) == METRICS_INVALID) | ||
| 122 | ftfont_driver.text_extents (font, &glyph, 1, cache); | ||
| 123 | |||
| 124 | if (metrics) | ||
| 125 | *metrics = *cache; | ||
| 126 | |||
| 127 | return cache->width; | ||
| 128 | } | ||
| 129 | |||
| 130 | static Lisp_Object | ||
| 131 | ftcrfont_list (struct frame *f, Lisp_Object spec) | ||
| 132 | { | ||
| 133 | Lisp_Object list = ftfont_driver.list (f, spec), tail; | ||
| 134 | |||
| 135 | for (tail = list; CONSP (tail); tail = XCDR (tail)) | ||
| 136 | ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr); | ||
| 137 | return list; | ||
| 138 | } | ||
| 139 | |||
| 140 | static Lisp_Object | ||
| 141 | ftcrfont_match (struct frame *f, Lisp_Object spec) | ||
| 142 | { | ||
| 143 | Lisp_Object entity = ftfont_driver.match (f, spec); | ||
| 144 | |||
| 145 | if (VECTORP (entity)) | ||
| 146 | ASET (entity, FONT_TYPE_INDEX, Qftcr); | ||
| 147 | return entity; | ||
| 148 | } | ||
| 149 | |||
| 150 | extern FT_Face ftfont_get_ft_face (Lisp_Object); | ||
| 151 | |||
| 152 | static Lisp_Object | ||
| 153 | ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | ||
| 154 | { | ||
| 155 | Lisp_Object font_object; | ||
| 156 | struct font *font; | ||
| 157 | struct ftcrfont_info *ftcrfont_info; | ||
| 158 | FT_Face ft_face; | ||
| 159 | FT_UInt size; | ||
| 160 | |||
| 161 | block_input (); | ||
| 162 | size = XINT (AREF (entity, FONT_SIZE_INDEX)); | ||
| 163 | if (size == 0) | ||
| 164 | size = pixel_size; | ||
| 165 | font_object = font_build_object (VECSIZE (struct ftcrfont_info), | ||
| 166 | Qftcr, entity, size); | ||
| 167 | font_object = ftfont_open2 (f, entity, pixel_size, font_object); | ||
| 168 | if (NILP (font_object)) return Qnil; | ||
| 169 | |||
| 170 | font = XFONT_OBJECT (font_object); | ||
| 171 | font->driver = &ftcrfont_driver; | ||
| 172 | ftcrfont_info = (struct ftcrfont_info *) font; | ||
| 173 | ft_face = ftcrfont_info->ft_size->face; | ||
| 174 | FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw); | ||
| 175 | FT_Activate_Size (ftcrfont_info->ft_size_draw); | ||
| 176 | FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size); | ||
| 177 | ftcrfont_info->cr_font_face = | ||
| 178 | cairo_ft_font_face_create_for_ft_face (ft_face, 0); | ||
| 179 | ftcrfont_info->metrics = NULL; | ||
| 180 | ftcrfont_info->metrics_nrows = 0; | ||
| 181 | unblock_input (); | ||
| 182 | |||
| 183 | return font_object; | ||
| 184 | } | ||
| 185 | |||
| 186 | static void | ||
| 187 | ftcrfont_close (struct font *font) | ||
| 188 | { | ||
| 189 | struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font; | ||
| 190 | int i; | ||
| 191 | |||
| 192 | block_input (); | ||
| 193 | for (i = 0; i < ftcrfont_info->metrics_nrows; i++) | ||
| 194 | if (ftcrfont_info->metrics[i]) | ||
| 195 | xfree (ftcrfont_info->metrics[i]); | ||
| 196 | if (ftcrfont_info->metrics) | ||
| 197 | xfree (ftcrfont_info->metrics); | ||
| 198 | FT_Done_Size (ftcrfont_info->ft_size_draw); | ||
| 199 | cairo_font_face_destroy (ftcrfont_info->cr_font_face); | ||
| 200 | unblock_input (); | ||
| 201 | |||
| 202 | ftfont_driver.close (font); | ||
| 203 | } | ||
| 204 | |||
| 205 | static void | ||
| 206 | ftcrfont_text_extents (struct font *font, | ||
| 207 | unsigned *code, | ||
| 208 | int nglyphs, | ||
| 209 | struct font_metrics *metrics) | ||
| 210 | { | ||
| 211 | int width, i; | ||
| 212 | |||
| 213 | block_input (); | ||
| 214 | width = ftcrfont_glyph_extents (font, code[0], metrics); | ||
| 215 | for (i = 1; i < nglyphs; i++) | ||
| 216 | { | ||
| 217 | struct font_metrics m; | ||
| 218 | int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL); | ||
| 219 | |||
| 220 | if (metrics) | ||
| 221 | { | ||
| 222 | if (width + m.lbearing < metrics->lbearing) | ||
| 223 | metrics->lbearing = width + m.lbearing; | ||
| 224 | if (width + m.rbearing > metrics->rbearing) | ||
| 225 | metrics->rbearing = width + m.rbearing; | ||
| 226 | if (m.ascent > metrics->ascent) | ||
| 227 | metrics->ascent = m.ascent; | ||
| 228 | if (m.descent > metrics->descent) | ||
| 229 | metrics->descent = m.descent; | ||
| 230 | } | ||
| 231 | width += w; | ||
| 232 | } | ||
| 233 | unblock_input (); | ||
| 234 | |||
| 235 | if (metrics) | ||
| 236 | metrics->width = width; | ||
| 237 | } | ||
| 238 | |||
| 239 | static int | ||
| 240 | ftcrfont_draw (struct glyph_string *s, | ||
| 241 | int from, int to, int x, int y, bool with_background) | ||
| 242 | { | ||
| 243 | struct frame *f = s->f; | ||
| 244 | struct face *face = s->face; | ||
| 245 | struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) s->font; | ||
| 246 | cairo_t *cr; | ||
| 247 | cairo_glyph_t *glyphs; | ||
| 248 | cairo_surface_t *surface; | ||
| 249 | 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 | |||
| 303 | void | ||
| 304 | syms_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 | ||
| 70 | size_t ftfont_info_size = sizeof (struct ftfont_info); | ||
| 71 | |||
| 70 | enum ftfont_cache_for | 72 | enum ftfont_cache_for |
| 71 | { | 73 | { |
| 72 | FTFONT_CACHE_FOR_FACE, | 74 | FTFONT_CACHE_FOR_FACE, |
| @@ -1161,8 +1163,11 @@ ftfont_list_family (struct frame *f) | |||
| 1161 | } | 1163 | } |
| 1162 | 1164 | ||
| 1163 | 1165 | ||
| 1164 | static Lisp_Object | 1166 | Lisp_Object |
| 1165 | ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | 1167 | ftfont_open2 (struct frame *f, |
| 1168 | Lisp_Object entity, | ||
| 1169 | int pixel_size, | ||
| 1170 | Lisp_Object font_object) | ||
| 1166 | { | 1171 | { |
| 1167 | struct ftfont_info *ftfont_info; | 1172 | struct ftfont_info *ftfont_info; |
| 1168 | struct font *font; | 1173 | struct font *font; |
| @@ -1170,7 +1175,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 1170 | FT_Face ft_face; | 1175 | FT_Face ft_face; |
| 1171 | FT_Size ft_size; | 1176 | FT_Size ft_size; |
| 1172 | FT_UInt size; | 1177 | FT_UInt size; |
| 1173 | Lisp_Object val, filename, idx, cache, font_object; | 1178 | Lisp_Object val, filename, idx, cache; |
| 1174 | bool scalable; | 1179 | bool scalable; |
| 1175 | int spacing; | 1180 | int spacing; |
| 1176 | int i; | 1181 | int i; |
| @@ -1210,8 +1215,6 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 1210 | return Qnil; | 1215 | return Qnil; |
| 1211 | } | 1216 | } |
| 1212 | 1217 | ||
| 1213 | font_object = font_build_object (VECSIZE (struct ftfont_info), | ||
| 1214 | Qfreetype, entity, size); | ||
| 1215 | ASET (font_object, FONT_FILE_INDEX, filename); | 1218 | ASET (font_object, FONT_FILE_INDEX, filename); |
| 1216 | font = XFONT_OBJECT (font_object); | 1219 | font = XFONT_OBJECT (font_object); |
| 1217 | ftfont_info = (struct ftfont_info *) font; | 1220 | ftfont_info = (struct ftfont_info *) font; |
| @@ -1294,6 +1297,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 1294 | return font_object; | 1297 | return font_object; |
| 1295 | } | 1298 | } |
| 1296 | 1299 | ||
| 1300 | static Lisp_Object | ||
| 1301 | ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | ||
| 1302 | { | ||
| 1303 | Lisp_Object font_object; | ||
| 1304 | FT_UInt size; | ||
| 1305 | size = XINT (AREF (entity, FONT_SIZE_INDEX)); | ||
| 1306 | if (size == 0) | ||
| 1307 | size = pixel_size; | ||
| 1308 | font_object = font_build_object (VECSIZE (struct ftfont_info), | ||
| 1309 | Qfreetype, entity, size); | ||
| 1310 | return ftfont_open2 (f, entity, pixel_size, font_object); | ||
| 1311 | } | ||
| 1312 | |||
| 1297 | static void | 1313 | static void |
| 1298 | ftfont_close (struct font *font) | 1314 | ftfont_close (struct font *font) |
| 1299 | { | 1315 | { |
diff --git a/src/ftfont.h b/src/ftfont.h index 210b634c094..0cfa0ae3e33 100644 --- a/src/ftfont.h +++ b/src/ftfont.h | |||
| @@ -37,6 +37,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 37 | #endif /* HAVE_LIBOTF */ | 37 | #endif /* HAVE_LIBOTF */ |
| 38 | 38 | ||
| 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); | 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); |
| 40 | extern Lisp_Object ftfont_open2 (struct frame *f, | ||
| 41 | Lisp_Object entity, | ||
| 42 | int pixel_size, | ||
| 43 | Lisp_Object font_object); | ||
| 44 | extern size_t ftfont_info_size; | ||
| 40 | 45 | ||
| 41 | #endif /* EMACS_FTFONT_H */ | 46 | #endif /* EMACS_FTFONT_H */ |
| 42 | 47 | ||
diff --git a/src/gtkutil.c b/src/gtkutil.c index 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 | ||
| 4075 | static GtkPrintSettings *print_settings = NULL; | ||
| 4076 | static GtkPageSetup *page_setup = NULL; | ||
| 4077 | |||
| 4078 | void | ||
| 4079 | xg_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 | |||
| 4092 | Lisp_Object | ||
| 4093 | xg_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 | |||
| 4134 | static void | ||
| 4135 | draw_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 | |||
| 4145 | void | ||
| 4146 | xg_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, | |||
| 180 | extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); | 180 | extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); |
| 181 | extern bool xg_hide_tooltip (struct frame *f); | 181 | extern bool xg_hide_tooltip (struct frame *f); |
| 182 | 182 | ||
| 183 | #ifdef USE_CAIRO | ||
| 184 | extern void xg_page_setup_dialog (void); | ||
| 185 | extern Lisp_Object xg_get_page_setup (void); | ||
| 186 | extern void xg_print_frames_dialog (Lisp_Object); | ||
| 187 | #endif | ||
| 188 | |||
| 183 | /* Mark all callback data that are Lisp_object:s during GC. */ | 189 | /* Mark all callback data that are Lisp_object:s during GC. */ |
| 184 | extern void xg_mark_data (void); | 190 | extern void xg_mark_data (void); |
| 185 | 191 | ||
diff --git a/src/image.c b/src/image.c index 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 | ||
| 1087 | static uint32_t | ||
| 1088 | xcolor_to_argb32 (XColor xc) | ||
| 1089 | { | ||
| 1090 | return (0xff << 24) | ((xc.red / 256) << 16) | ||
| 1091 | | ((xc.green / 256) << 8) | (xc.blue / 256); | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static uint32_t | ||
| 1095 | get_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 | |||
| 1111 | static void | ||
| 1112 | create_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 | |||
| 1299 | x_clear_image (struct frame *f, struct image *img) | 1352 | x_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 | ||
| 6224 | DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0, | ||
| 6225 | doc: /* XXX Experimental. Return image data of FRAMES in TYPE format. | ||
| 6226 | FRAMES should be nil (the selected frame), a frame, or a list of | ||
| 6227 | frames (each of which corresponds to one page). Optional arg TYPE | ||
| 6228 | should be either `pdf' (default), `png', `ps', or `svg'. Supported | ||
| 6229 | types 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 | ||
| 6292 | DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0, | ||
| 6293 | doc: /* Pop up a page setup dialog. | ||
| 6294 | The 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 | |||
| 6304 | DEFUN ("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. | ||
| 6306 | The 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 | |||
| 6315 | The paper width can be obtained as the sum of width, left-margin, and | ||
| 6316 | right-margin values. Likewise, the paper height is the sum of height, | ||
| 6317 | top-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 | |||
| 6329 | DEFUN ("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. | ||
| 6331 | FRAMES should be nil (the selected frame), a frame, or a list of | ||
| 6332 | frames (each of which corresponds to one page). Each frame should be | ||
| 6333 | visible. */) | ||
| 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 *); | |||
| 220 | static struct terminal *x_create_terminal (struct x_display_info *); | 223 | static struct terminal *x_create_terminal (struct x_display_info *); |
| 221 | static void x_update_end (struct frame *); | 224 | static void x_update_end (struct frame *); |
| 222 | static void XTframe_up_to_date (struct frame *); | 225 | static void XTframe_up_to_date (struct frame *); |
| 226 | static void x_clear_area1 (Display *, Window, int, int, int, int, int); | ||
| 223 | static void x_clear_frame (struct frame *); | 227 | static void x_clear_frame (struct frame *); |
| 224 | static _Noreturn void x_ins_del_lines (struct frame *, int, int); | 228 | static _Noreturn void x_ins_del_lines (struct frame *, int, int); |
| 225 | static void frame_highlight (struct frame *); | 229 | static void frame_highlight (struct frame *); |
| @@ -325,6 +329,587 @@ record_event (char *locus, int type) | |||
| 325 | 329 | ||
| 326 | #endif | 330 | #endif |
| 327 | 331 | ||
| 332 | static void x_free_cr_resources (struct frame *); | ||
| 333 | static void x_set_clip_rectangles (struct frame *, GC, XRectangle *, int); | ||
| 334 | static void x_reset_clip_rectangles (struct frame *, GC); | ||
| 335 | static void x_fill_rectangle (struct frame *, GC, int, int, int, int); | ||
| 336 | static void x_draw_rectangle (struct frame *, GC, int, int, int, int); | ||
| 337 | static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int, | ||
| 338 | int, int, int); | ||
| 339 | static void x_clear_window (struct frame *); | ||
| 340 | |||
| 341 | #ifdef USE_CAIRO | ||
| 342 | static struct x_gc_ext_data *x_gc_get_ext_data (struct frame *, GC, int); | ||
| 343 | static void x_extension_initialize (struct x_display_info *); | ||
| 344 | static 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 | |||
| 351 | static struct x_gc_ext_data * | ||
| 352 | x_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 | |||
| 376 | static void | ||
| 377 | x_extension_initialize (struct x_display_info *dpyinfo) | ||
| 378 | { | ||
| 379 | XExtCodes *ext_codes = XAddExtension (dpyinfo->display); | ||
| 380 | |||
| 381 | dpyinfo->ext_codes = ext_codes; | ||
| 382 | } | ||
| 383 | |||
| 384 | static void | ||
| 385 | x_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 | |||
| 397 | cairo_t * | ||
| 398 | x_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 | |||
| 442 | void | ||
| 443 | x_end_cr_clip (struct frame *f) | ||
| 444 | { | ||
| 445 | cairo_restore (FRAME_CR_CONTEXT (f)); | ||
| 446 | } | ||
| 447 | |||
| 448 | void | ||
| 449 | x_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 | |||
| 461 | void | ||
| 462 | x_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 | |||
| 476 | static int max_fringe_bmp = 0; | ||
| 477 | static cairo_pattern_t **fringe_bmp = 0; | ||
| 478 | |||
| 479 | static void | ||
| 480 | x_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 | |||
| 517 | static void | ||
| 518 | x_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 | |||
| 532 | static void | ||
| 533 | x_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 | |||
| 569 | void | ||
| 570 | x_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 | |||
| 584 | static cairo_status_t | ||
| 585 | x_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 | |||
| 595 | static void | ||
| 596 | x_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 | |||
| 605 | Lisp_Object | ||
| 606 | x_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 | |||
| 704 | static void | ||
| 705 | x_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 | |||
| 733 | static void | ||
| 734 | x_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 | |||
| 749 | static void | ||
| 750 | x_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 | |||
| 763 | static void | ||
| 764 | x_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 | |||
| 780 | static void | ||
| 781 | x_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 | |||
| 798 | static void | ||
| 799 | x_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 | ||
| 814 | static void | ||
| 815 | x_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 | |||
| 830 | enum 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 | |||
| 839 | static void | ||
| 840 | x_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 | |||
| 872 | static void | ||
| 873 | x_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) | |||
| 452 | static void | 1037 | static void |
| 453 | x_update_begin (struct frame *f) | 1038 | x_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 | |||
| 2560 | x_draw_underwave (struct glyph_string *s) | 3323 | x_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 | ||
| 3689 | static void | ||
| 3690 | x_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 | |||
| 2921 | void | 3698 | void |
| 2922 | x_clear_area (Display *dpy, Window window, int x, int y, int width, int height) | 3699 | x_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 | ||
| 4253 | static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part, | 5046 | static 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) | |||
| 8133 | static void | 8927 | static void |
| 8134 | x_clear_frame_area (struct frame *f, int x, int y, int width, int height) | 8928 | x_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 | ||
| 116 | struct x_bitmap_record | 129 | struct x_bitmap_record |
| 117 | { | 130 | { |
| 131 | #ifdef USE_CAIRO | ||
| 132 | void *img; | ||
| 133 | #endif | ||
| 118 | Pixmap pixmap; | 134 | Pixmap pixmap; |
| 119 | bool have_mask; | 135 | bool have_mask; |
| 120 | Pixmap mask; | 136 | Pixmap mask; |
| @@ -124,6 +140,19 @@ struct x_bitmap_record | |||
| 124 | int height, width, depth; | 140 | int height, width, depth; |
| 125 | }; | 141 | }; |
| 126 | 142 | ||
| 143 | #ifdef USE_CAIRO | ||
| 144 | struct x_gc_ext_data | ||
| 145 | { | ||
| 146 | #define MAX_CLIP_RECTS 2 | ||
| 147 | /* Number of clipping rectangles. */ | ||
| 148 | int n_clip_rects; | ||
| 149 | |||
| 150 | /* Clipping rectangles. */ | ||
| 151 | XRectangle clip_rects[MAX_CLIP_RECTS]; | ||
| 152 | }; | ||
| 153 | #endif | ||
| 154 | |||
| 155 | |||
| 127 | /* For each X display, we have a structure that records | 156 | /* For each X display, we have a structure that records |
| 128 | information about it. */ | 157 | information about it. */ |
| 129 | 158 | ||
| @@ -411,6 +440,10 @@ struct x_display_info | |||
| 411 | 440 | ||
| 412 | /* SM */ | 441 | /* SM */ |
| 413 | Atom Xatom_SM_CLIENT_ID; | 442 | Atom Xatom_SM_CLIENT_ID; |
| 443 | |||
| 444 | #ifdef USE_CAIRO | ||
| 445 | XExtCodes *ext_codes; | ||
| 446 | #endif | ||
| 414 | }; | 447 | }; |
| 415 | 448 | ||
| 416 | #ifdef HAVE_X_I18N | 449 | #ifdef HAVE_X_I18N |
| @@ -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 | ||
| 650 | enum | 690 | enum |
| @@ -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 |
| 993 | extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); | 1033 | extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); |
| 994 | extern void x_clear_area (Display *, Window, int, int, int, int); | 1034 | extern void x_query_color (struct frame *f, XColor *); |
| 1035 | extern 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 |
| 996 | extern void x_mouse_leave (struct x_display_info *); | 1037 | extern 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 *); | |||
| 1000 | extern int x_dispatch_event (XEvent *, Display *); | 1041 | extern int x_dispatch_event (XEvent *, Display *); |
| 1001 | #endif | 1042 | #endif |
| 1002 | extern int x_x_to_emacs_modifiers (struct x_display_info *, int); | 1043 | extern int x_x_to_emacs_modifiers (struct x_display_info *, int); |
| 1044 | #ifdef USE_CAIRO | ||
| 1045 | extern cairo_t *x_begin_cr_clip (struct frame *, GC); | ||
| 1046 | extern void x_end_cr_clip (struct frame *); | ||
| 1047 | extern void x_set_cr_source_with_gc_foreground (struct frame *, GC); | ||
| 1048 | extern void x_set_cr_source_with_gc_background (struct frame *, GC); | ||
| 1049 | extern void x_cr_draw_frame (cairo_t *, struct frame *); | ||
| 1050 | extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t); | ||
| 1051 | #endif | ||
| 1003 | 1052 | ||
| 1004 | INLINE int | 1053 | INLINE int |
| 1005 | x_display_pixel_height (struct x_display_info *dpyinfo) | 1054 | x_display_pixel_height (struct x_display_info *dpyinfo) |