Merge branch 'cairo'.

Main work done by YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>.
Small fixes and image work by Jan D. <jan.h.d@swipnet.se>.
This commit is contained in:
Jan D 2015-05-23 12:34:45 +02:00
commit c03c730481
21 changed files with 2321 additions and 141 deletions

View file

@ -1,9 +1,23 @@
2015-04-11 Jan Djärv <jan.h.d@swipnet.se>
* configure.ac: Allow jpeg with cairo.
Allow tiff and gif with cairo.
2015-04-07 Paul Eggert <eggert@cs.ucla.edu>
Merge from gnulib
* lib/stddef.in.h: Update from gnulib, incorporating:
2015-04-02 stddef: port to pre-C11 GCC on x86
2015-04-05 Jan Djärv <jan.h.d@swipnet.se>
* configure.ac: Allow rsvg with cairo. Move back HAVE_RSVG.
2015-04-03 Jan Djärv <jan.h.d@swipnet.se>
* configure.ac (HAVE_RSVG): Move after cairo.
(USE_CAIRO): Disable rsvg, don't disable Xpm.
2015-04-03 Paul Eggert <eggert@cs.ucla.edu>
Port 'configure' to clang 3.5
@ -108,6 +122,13 @@
* configure.ac: Set locallisppath to empty for NS self contained,
unless --enable-loadllisppath was given (Bug#19850).
2015-02-11 Jan Djärv <jan.h.d@swipnet.se>
* configure.ac (with-cairo): New option.
(USE_CAIRO): Default to yes for Gtk+ 3. Add code to test for cairo,
set CAIRO_CFLAGS, CAIRO_LIBS. Add ftcrfonto to FONT_OBJ if cairo.
Output "Does Emacs use cairo?".
2015-02-09 Paul Eggert <eggert@cs.ucla.edu>
* configure.ac (HAVE_LIBXML2): Add missing comma.

View file

@ -330,6 +330,7 @@ OPTION_DEFAULT_ON([tiff],[don't compile with TIFF image support])
OPTION_DEFAULT_ON([gif],[don't compile with GIF image support])
OPTION_DEFAULT_ON([png],[don't compile with PNG image support])
OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support])
OPTION_DEFAULT_OFF([cairo],[compile with Cairo drawing])
OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support])
OPTION_DEFAULT_ON([imagemagick],[don't compile with ImageMagick image support])
@ -2407,6 +2408,7 @@ if test "${opsys}" != "mingw32"; then
AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.])
GTK_OBJ=emacsgtkfixed.o
gtk_term_header=gtkutil.h
USE_CAIRO=yes
USE_GTK_TOOLKIT="GTK3"
if test "x$ac_enable_gtk_deprecation_warnings" = x; then
AC_DEFINE([GDK_DISABLE_DEPRECATION_WARNINGS], [1],
@ -3075,6 +3077,25 @@ AC_SUBST(LIBOTF_LIBS)
AC_SUBST(M17N_FLT_CFLAGS)
AC_SUBST(M17N_FLT_LIBS)
USE_CAIRO=no
if test "${HAVE_X11}" = "yes"; then
if test "${with_cairo}" != "no"; then
CAIRO_REQUIRED=1.12.0
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
if test $USE_CAIRO = yes; then
AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
else
AC_MSG_ERROR([cairo requested but not found.])
fi
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $CAIRO_LIBS"
AC_SUBST(CAIRO_CFLAGS)
AC_SUBST(CAIRO_LIBS)
fi
fi
### Use -lXpm if available, unless '--with-xpm=no'.
### mingw32 doesn't use -lXpm, since it loads the library dynamically.
### In the Cygwin-w32 build, we need to use /usr/include/noX/X11/xpm.h
@ -4009,8 +4030,8 @@ OLDCFLAGS="$CFLAGS"
OLDLIBS="$LIBS"
CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS"
LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS"
CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS"
LIBS="$LIBS $GFILENOTIFY_LIBS"
CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $GFILENOTIFY_LIBS $CAIRO_LIBS"
AC_MSG_CHECKING([whether GLib is linked in])
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[#include <glib.h>
@ -4776,7 +4797,9 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then
XMENU_OBJ=xmenu.o
XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o"
FONT_OBJ=xfont.o
if test "$HAVE_XFT" = "yes"; then
if test "$USE_CAIRO" = "yes"; then
FONT_OBJ="ftfont.o ftcrfont.o"
elif test "$HAVE_XFT" = "yes"; then
FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o"
elif test "$HAVE_FREETYPE" = "yes"; then
FONT_OBJ="$FONT_OBJ ftfont.o ftxfont.o"
@ -5142,6 +5165,7 @@ echo " Does Emacs use -ltiff? ${HAVE_TIFF}"
echo " Does Emacs use a gif library? ${HAVE_GIF} $LIBGIF"
echo " Does Emacs use a png library? ${HAVE_PNG} $LIBPNG"
echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
echo " Does Emacs use cairo? ${USE_CAIRO}"
echo " Does Emacs use imagemagick? ${HAVE_IMAGEMAGICK}"
echo " Does Emacs support sound? ${HAVE_SOUND}"

View file

@ -1748,6 +1748,12 @@
(package-menu--print-info, package-menu--status-predicate):
Account for the "incompat" status.
2015-02-11 Martin Rudalics <rudalics@gmx.at>
2015-02-11 Jan Djärv <jan.h.d@swipnet.se>
* version.el (emacs-version): Add cairo version.
2015-02-11 Martin Rudalics <rudalics@gmx.at>
* frame.el (toggle-frame-maximized, toggle-frame-fullscreen):

View file

@ -56,8 +56,8 @@ to the system configuration; look at `system-configuration' instead."
(interactive "P")
(let ((version-string
(format (if (not (called-interactively-p 'interactive))
"GNU Emacs %s (%s%s%s)\n of %s on %s"
"GNU Emacs %s (%s%s%s) of %s on %s")
"GNU Emacs %s (%s%s%s%s)\n of %s on %s"
"GNU Emacs %s (%s%s%s%s) of %s on %s")
emacs-version
system-configuration
(cond ((featurep 'motif)
@ -68,6 +68,9 @@ to the system configuration; look at `system-configuration' instead."
((featurep 'ns)
(format ", NS %s" ns-version-string))
(t ""))
(if (featurep 'cairo)
(format ", cairo version %s" cairo-version-string)
"")
(if (and (boundp 'x-toolkit-scroll-bars)
(memq x-toolkit-scroll-bars '(xaw xaw3d)))
(format ", %s scroll bars"

View file

@ -1,3 +1,6 @@
2015-04-03 Jan Djärv <jan.h.d@swipnet.se>
* Makefile.in (CAIRO_CFLAGS): Add.
2015-03-18 Stefan Monnier <monnier@iro.umontreal.ca>
* xlwmenu.c (pop_up_menu): Remove debugging code.

View file

@ -33,6 +33,7 @@ C_SWITCH_MACHINE=@C_SWITCH_MACHINE@
PROFILING_CFLAGS = @PROFILING_CFLAGS@
WARN_CFLAGS = `echo @WARN_CFLAGS@ | sed 's/ -Wwrite-strings//'`
WERROR_CFLAGS = @WERROR_CFLAGS@
CAIRO_CFLAGS= @CAIRO_CFLAGS@
CC=@CC@
CFLAGS=@CFLAGS@
@ -88,6 +89,7 @@ endif
ALL_CFLAGS= $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
$(C_SWITCH_MACHINE) $(DEPFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(PROFILING_CFLAGS) $(CFLAGS) \
$(CAIRO_CFLAGS) \
-Demacs -I../src \
-I$(srcdir) -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib

View file

@ -1,9 +1,51 @@
2015-04-26 Jan Djärv <jan.h.d@swipnet.se>
* image.c (xcolor_to_argb32): New function.
(get_spec_bg_or_alpha_as_argb): Call xcolor_to_argb32.
(pbm_load, png_load_body, jpeg_load_body, gif_load): Only use
XImagePtr if ! USE_CAIRO.
(pbm_load): Add cairo support.
2015-04-12 Jan Djärv <jan.h.d@swipnet.se>
* xterm.c (x_draw_image_glyph_string): Added missing USE_CAIRO.
(x_free_cr_resources): Renamed from x_prepare_for_xlibdraw.
(x_cr_draw_frame, x_cr_export_frames, x_shift_glyphs_for_insert)
(x_free_frame_resources): Rename x_prepare_for_xlibdraw to
x_free_cr_resources.
* image.c (get_spec_bg_or_alpha_as_argb)
(create_cairo_image_surface): New functions when USE_CAIRO.
(xpm_load): Call the above functions. Handle XPM without mask
when USE_CAIRO.
(png_load_body): Handle USE_CAIRO case.
(png_load): Remove USE_CAIRO specific fuction, modify png_load_body
instead.
(jpeg_load_body): Call create_cairo_image_surface.
(gif_load, svg_load_image): Handle specified background, call
create_cairo_image_surface.
2015-04-11 Jan Djärv <jan.h.d@swipnet.se>
* image.c (jpeg_load_body): Create cairo image surface if USE_CAIRO.
(tiff_load): Create cairo image surface if USE_CAIRO.
(gif_load): Ditto.
2015-04-06 Koichi Arakawa <arakawa@pp.iij4u.or.jp> (tiny change)
* w32proc.c (w32_executable_type): Look for the DLL name in the
correct section. This avoids segfaults with some executables.
(Bug#20264)
2015-04-05 Jan Djärv <jan.h.d@swipnet.se>
* image.c: #undef COLOR_TABLE_SUPPORT when USE_CAIRO.
(x_clear_image): Free cr_data and cr_data2 if set.
(xpm_load): Assign data to cr_data2.
(svg_load_image): Convert from GdkPixbuf to CAIRO_FORMAT_ARGB32.
* dispextern.h (struct image): add cr_data2 if cairo.
2015-04-04 Jan Djärv <jan.h.d@swipnet.se>
* xselect.c (x_reply_selection_request)
@ -15,8 +57,17 @@
2015-04-03 Jan Djärv <jan.h.d@swipnet.se>
* image.c (prepare_image_for_display): Don't load if USE_CAIRO.
(x_clear_image): If USE_CAIRO, also free possible img->ximg->obdata and
don't return early.
(ALLOC_XPM_COLORS): Don't define when USE_CAIRO.
(xpm_load): Convert simple Xpms (32 bit ZPixmap) to CAIRO_FORMAT_ARGB32
and create a surface.
* xterm.c (handle_one_xevent): Always redraw tool tips on
MapNotify. Update tool tip frame sizes on ConfigureNotify.
(x_update_begin): Don't create any surface for non-visible
tip frames, the geometry may be wrong.
2015-03-31 Eli Zaretskii <eliz@gnu.org>
@ -559,6 +610,191 @@
DEFINE_LISP_SYMBOL_BEGIN / DEFINE_LISP_SYMBOL_END. All uses changed.
(DEFINE_NONNIL_Q_SYMBOL_MACROS): New macro, defaulting to true.
2015-02-19 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* ftcrfont.c (ftcrfont_draw): Don't flush when drawing to screen.
2015-02-17 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* xterm.c [USE_CAIRO]: Include math.h.
(enum corners) [USE_CAIRO]: New enum.
(x_erase_corners_for_relief) [USE_CAIRO]: New function.
(x_draw_relief_rect) [USE_CAIRO]: Use it. If box width is larger
than 1, draw the outermost line using the black relief.
2015-02-16 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* gtkutil.c (xg_page_setup_dialog, xg_get_page_setup, draw_page)
(xg_print_frames_dialog): Modernize k&r declarations.
* xfns.c (Fx_export_frames, Fx_page_setup_dialog, Fx_get_page_setup)
(Fx_print_frames_dialog): Modernize k&r declarations.
* xterm.c (x_draw_window_divider): Use x_fill_rectangle instead of
XFillRectangle.
(x_draw_horizontal_wave) [USE_CAIRO]: New function.
(x_draw_underwave) [USE_CAIRO]: Use it.
(x_gc_get_ext_data, x_extension_initialize, x_begin_cr_clip)
(x_end_cr_clip, x_set_cr_source_with_gc_foreground)
(x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap)
(x_cr_destroy_fringe_bitmap, x_cr_draw_frame, x_cr_accumulate_data)
(x_cr_destroy, x_cr_export_frames, x_prepare_for_xlibdraw)
(x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle)
(x_draw_rectangle, x_clear_window, x_fill_trapezoid_for_relief)
(x_clear_area): Modernize k&r declarations.
(x_cr_draw_image, x_fill_rectangle, x_draw_rectangle)
(x_fill_trapezoid_for_relief): Use int instead of unsigned int for
width and height args.
(x_draw_stretch_glyph_string): Call x_reset_clip_rectangles instead
of XSetClipMask.
(x_draw_relief_rect) [USE_CAIRO]: Reset clipping.
(x_fill_trapezoid_for_relief): Remove unnecessary cairo_close_path.
2015-02-14 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* fringe.c (init_fringe_bitmap) [USE_CAIRO]: Adjust bitmap data for
cairo image surface.
* xterm.c (x_cr_define_fringe_bitmap): Call cairo_surface_mark_dirty.
2015-02-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
Jan Djärv <jan.h.d@swipnet.se>
* xterm.h: Add include of cairo header files.
(x_bitmap_record): Add img if cairo.
(x_gc_ext_data): New struct for cairo.
(x_display_info): Add ext_codes for cairo.
(x_output): Add cr_context and cr_surface for cairo.
(x_clear_area): Change arguments from Display*/Window to frame pointer.
(x_query_color, x_begin_cr_clip, x_end_cr_clip)
(x_set_cr_source_with_gc_foreground, x_set_cr_source_with_gc_background)
(x_cr_draw_frame, x_cr_export_frames): Declare.
* xterm.c (x_clear_area1, x_prepare_for_xlibdraw)
(x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle)
(x_draw_rectangle, x_fill_trapezoid_for_relief, x_clear_window)
(x_gc_get_ext_data, x_extension_initialize, x_cr_accumulate_data):
Declare.
(FRAME_CR_CONTEXT, FRAME_CR_SURFACE): New macros.
(max_fringe_bmp, fringe_bmp): New variables.
(x_gc_get_ext_data, x_extension_initialize)
(x_cr_destroy_surface, x_begin_cr_clip, x_end_cr_clip)
(x_set_cr_source_with_gc_foreground)
(x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap)
(x_cr_destroy_fringe_bitmap, x_cr_draw_image, x_cr_draw_frame)
(x_cr_accumulate_data, x_cr_destroy, x_cr_export_frames)
(x_prepare_for_xlibdraw, x_set_clip_rectangles)
(x_reset_clip_rectangles, x_fill_rectangle, x_draw_rectangle)
(x_clear_window, x_fill_trapezoid_for_relief): New functions.
(x_update_begin): Create cairo surface if needed.
(x_draw_vertical_window_border): Call x_fill_rectangle for cairo.
(x_update_end): Paint cairo drawing surface to xlib surface.
(x_clear_under_internal_border, x_after_update_window_line): Adjust
arguments to x_clear_area.
(x_draw_fringe_bitmap): Call x_fill_rectangle. Get GC values and
call x_cr_draw_image for cairo. Call x_reset_clip_rectangles instead
of XSetClipMask.
(x_set_glyph_string_clipping)
(x_set_glyph_string_clipping_exactly): Use x_set_clip_rectangles
instead of XSetClipRectangles.
(x_clear_glyph_string_rect, x_draw_glyph_string_background): Use
x_fill_rectangle instead of XFillRectangle.
(x_draw_glyph_string_foreground)
(x_draw_composite_glyph_string_foreground)
(x_draw_glyphless_glyph_string_foreground): Use x_draw_rectangle instead
of XDrawRectangle.
(x_draw_relief_rect): Add code for USE_CAIRO.
Call x_reset_clip_rectangles instead of XSetClipMask.
(x_draw_box_rect): x_set_clip_rectangles instead of XSetClipRectangles,
x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles
instead of XSetClipMask.
(x_draw_image_foreground, x_draw_image_foreground_1):
x_draw_rectangle instead of XDrawRectangle.
(x_draw_glyph_string_bg_rect): x_fill_rectangle instead of
XFillRectangle.
(x_draw_image_glyph_string): If img has cr_data, use it as
a cairo surface.
(x_draw_stretch_glyph_string): x_set_clip_rectangles instead of
XSetClipRectangles, x_fill_rectangle instead of XFillRectangle.
(x_draw_glyph_string): x_fill_rectangle instead of XFillRectangle.,
x_reset_clip_rectangles instead of XSetClipMask.
(x_shift_glyphs_for_insert): Call x_prepare_for_xlibdraw.
(x_clear_area1): New function that calls XClearArea.
(x_clear_area): Takes frame as parameter, calls x_clear_area1 for
non-cairo.
(x_clear_frame): x_clear_window instead of XClearWindow.
(x_scroll_run): Set frame garbaged if cairo.
(XTmouse_position): Initialize *part to 0.
(x_scroll_bar_create): Adjust arguments to x_clear_area.
(x_scroll_bar_set_handle): x_clear_area1 instead of x_clear_area,
x_fill_rectangle instead of XFillRectangle.
(XTset_vertical_scroll_bar, XTset_horizontal_scroll_bar): Adjust
arguments to x_clear_area.
(x_scroll_bar_expose): x_draw_rectangle instead of XDrawRectangle.
(handle_one_xevent): Adjust arguments to x_clear_area.
Destroy cairo surface for frame if ConfigureNotify.
(x_clip_to_row): x_set_clip_rectangles instead of XSetClipRectangles.
(x_draw_hollow_cursor): x_draw_rectangle instead of XDrawRectangle,
x_reset_clip_rectangles instead of XSetClipMask.
(x_draw_bar_cursor): x_fill_rectangle instead of XFillRectangle,
x_reset_clip_rectangles instead of XSetClipMask.
(x_clear_frame_area): Adjust arguments to x_clear_area.
(x_free_frame_resources): Call x_prepare_for_xlibdraw.
(x_term_init): Call x_extension_initialize if cairo.
(x_redisplay_interface): Add x_cr_define_fringe_bitmap,
x_cr_destroy_fringe_bitmap for cairo.
(x_initialize): Call x_cr_init_fringe for cairo.
* xfns.c: New section Printing.
(x-export-frames, x-page-setup-dialog, x-get-page-setup)
(x-print-frames-dialog): New printing functions.
(Fx_create_frame, x_create_tip_frame): Register ftcrfont if
cairo.
(syms_of_xfns): Defsym Qorientation, Qtop_margin, Qbottom_margin,
Qportrait, Qlandscape, Qreverse_portrait, Qreverse_landscape).
(syms_of_xfns): Provide cairo and defvar cairo-version-string.
defsubr Sx_page_setup_dialog, Sx_get_page_setup, Sx_print_frames_dialog.
* image.c: Add defined (USE_CAIRO) for PNG.
Add !defined USE_CAIRO for W32 PNG code.
(x_clear_image): If cairo, destroy the surface in cr_data.
(png_load): Add new cairo compatible implementation.
(lookup_image_type): Add defined (USE_CAIRO) for define png_type.
* gtkutil.h (xg_page_setup_dialog, xg_get_page_setup)
(xg_print_frames_dialog): Declare.
* gtkutil.c (xg_clear_under_internal_border)
(xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Only
queue_draw if not cairo. Change args to x_clear_area.
(xg_get_font): Use Qftcr when using cairo, Qxft otherwise.
(xg_page_setup_dialog, xg_get_page_setup, draw_page)
(xg_print_frames_dialog): New functions for printing.
* ftfont.h (ftfont_open2, ftfont_info_size): Declare.
* ftfont.c (ftfont_info_size); New global variable.
(ftfont_open2): New extern function almost the same as old ftfont_open,
but takes the font_object as argument.
(ftfont_open): Build font object and call ftfont_open2.
* ftcrfont.c: New font driver for cairo, based on the ftfont driver.
* fringe.c (x_cr_init_fringe): New function name that shares code
with w32_init_fringe.
* font.h (ftcrfont_driver, syms_of_ftcrfont): Declare
* font.c (syms_of_font): Call syms_of_ftcrfont for cairo.
* dispextern.h (struct image): Add cr_data for cairo.
(x_cr_init_fringe): Declare.
* Makefile.in (CAIRO_CFLAGS, CAIRO_LIBS): New variables.
(FONT_OBJ): Add comment about ftcrfont.
(ALL_CFLAGS): Add CAIRO_CFLAGS.
(LIBES): Add CAIRO_LIBS.
2015-02-11 Martin Rudalics <rudalics@gmx.at>
* w32term.c (w32_read_socket): In SIZE_MAXIMIZED and

View file

@ -218,6 +218,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
RSVG_LIBS= @RSVG_LIBS@
RSVG_CFLAGS= @RSVG_CFLAGS@
CAIRO_LIBS= @CAIRO_LIBS@
CAIRO_CFLAGS= @CAIRO_CFLAGS@
IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@
IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
@ -273,6 +276,7 @@ W32_RES_LINK=@W32_RES_LINK@
## Empty if !HAVE_X_WINDOWS
## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT
## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
## ftfont.o ftcrfont.o if USE_CAIRO
## else xfont.o
FONT_OBJ=@FONT_OBJ@
@ -350,7 +354,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
$(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \
$(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
@ -456,7 +460,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
$(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \

View file

@ -2941,6 +2941,10 @@ struct image
/* Pixmaps of the image. */
Pixmap pixmap, mask;
#ifdef USE_CAIRO
void *cr_data;
void *cr_data2;
#endif
#ifdef HAVE_X_WINDOWS
/* X images of the image, corresponding to the above Pixmaps.
Non-NULL means it and its Pixmap counterpart may be out of sync
@ -3302,6 +3306,9 @@ bool update_window_fringes (struct window *, bool);
void w32_init_fringe (struct redisplay_interface *);
void w32_reset_fringes (void);
#endif
#ifdef USE_CAIRO
void x_cr_init_fringe (struct redisplay_interface *);
#endif
extern unsigned row_hash (struct glyph_row *);

View file

@ -5280,11 +5280,15 @@ EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
#ifdef HAVE_FREETYPE
syms_of_ftfont ();
#ifdef HAVE_X_WINDOWS
#ifdef USE_CAIRO
syms_of_ftcrfont ();
#else
syms_of_xfont ();
syms_of_ftxfont ();
#ifdef HAVE_XFT
syms_of_xftfont ();
#endif /* HAVE_XFT */
#endif /* not USE_CAIRO */
#endif /* HAVE_X_WINDOWS */
#else /* not HAVE_FREETYPE */
#ifdef HAVE_X_WINDOWS

View file

@ -844,6 +844,10 @@ extern struct font_driver nsfont_driver;
extern void syms_of_nsfont (void);
extern void syms_of_macfont (void);
#endif /* HAVE_NS */
#ifdef USE_CAIRO
extern struct font_driver ftcrfont_driver;
extern void syms_of_ftcrfont (void);
#endif
#ifndef FONT_DEBUG
#define FONT_DEBUG

View file

@ -1405,6 +1405,21 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
unsigned short *bits = fb->bits;
int j;
#ifdef USE_CAIRO
for (j = 0; j < fb->height; j++)
{
unsigned short b = *bits;
#ifdef WORDS_BIGENDIAN
*bits++ = (b << (16 - fb->width));
#else
b = (unsigned short)((swap_nibble[b & 0xf] << 12)
| (swap_nibble[(b>>4) & 0xf] << 8)
| (swap_nibble[(b>>8) & 0xf] << 4)
| (swap_nibble[(b>>12) & 0xf]));
*bits++ = (b >> (16 - fb->width));
#endif
}
#else /* not USE_CAIRO */
if (fb->width <= 8)
{
unsigned char *cbits = (unsigned char *)fb->bits;
@ -1433,6 +1448,7 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
*bits++ = b;
}
}
#endif /* not USE_CAIRO */
#endif /* HAVE_X_WINDOWS */
}
@ -1731,10 +1747,14 @@ init_fringe (void)
fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
}
#ifdef HAVE_NTGUI
#if defined (HAVE_NTGUI) || defined (USE_CAIRO)
void
#ifdef HAVE_NTGUI
w32_init_fringe (struct redisplay_interface *rif)
#else
x_cr_init_fringe (struct redisplay_interface *rif)
#endif
{
int bt;
@ -1747,7 +1767,9 @@ w32_init_fringe (struct redisplay_interface *rif)
rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
}
}
#endif
#ifdef HAVE_NTGUI
void
w32_reset_fringes (void)
{

320
src/ftcrfont.c Normal file
View file

@ -0,0 +1,320 @@
/* ftcrfont.c -- FreeType font driver on cairo.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <cairo-ft.h>
#include "lisp.h"
#include "dispextern.h"
#include "xterm.h"
#include "frame.h"
#include "blockinput.h"
#include "character.h"
#include "charset.h"
#include "fontset.h"
#include "font.h"
#include "ftfont.h"
/* FTCR font driver. */
/* The actual structure for ftcr font that can be casted to struct
font. */
struct ftcrfont_info
{
struct font font;
/* The following six members must be here in this order to be
compatible with struct ftfont_info (in ftfont.c). */
#ifdef HAVE_LIBOTF
bool maybe_otf; /* Flag to tell if this may be OTF or not. */
OTF *otf;
#endif /* HAVE_LIBOTF */
FT_Size ft_size;
int index;
FT_Matrix matrix;
cairo_font_face_t *cr_font_face;
/* To prevent cairo from cluttering the activated FT_Size maintained
in ftfont.c, we activate this special FT_Size before drawing. */
FT_Size ft_size_draw;
/* Font metrics cache. */
struct font_metrics **metrics;
short metrics_nrows;
};
#define METRICS_NCOLS_PER_ROW (128)
enum metrics_status
{
METRICS_INVALID = -1, /* metrics entry is invalid */
};
#define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
#define METRICS_SET_STATUS(metrics, status) \
((metrics)->ascent = 0, (metrics)->descent = (status))
/* Prototypes for helper function. */
static int ftcrfont_glyph_extents (struct font *, unsigned,
struct font_metrics *);
/* Prototypes for font-driver methods. */
static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object);
static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object);
static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int);
static void ftcrfont_close (struct font *);
static void ftcrfont_text_extents (struct font *, unsigned *, int,
struct font_metrics *);
static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool);
struct font_driver ftcrfont_driver;
static int
ftcrfont_glyph_extents (struct font *font,
unsigned glyph,
struct font_metrics *metrics)
{
struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
int row, col;
struct font_metrics *cache;
row = glyph / METRICS_NCOLS_PER_ROW;
col = glyph % METRICS_NCOLS_PER_ROW;
if (row >= ftcrfont_info->metrics_nrows)
{
ftcrfont_info->metrics =
xrealloc (ftcrfont_info->metrics,
sizeof (struct font_metrics *) * (row + 1));
bzero (ftcrfont_info->metrics + ftcrfont_info->metrics_nrows,
(sizeof (struct font_metrics *)
* (row + 1 - ftcrfont_info->metrics_nrows)));
ftcrfont_info->metrics_nrows = row + 1;
}
if (ftcrfont_info->metrics[row] == NULL)
{
struct font_metrics *new;
int i;
new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
METRICS_SET_STATUS (new + i, METRICS_INVALID);
ftcrfont_info->metrics[row] = new;
}
cache = ftcrfont_info->metrics[row] + col;
if (METRICS_STATUS (cache) == METRICS_INVALID)
ftfont_driver.text_extents (font, &glyph, 1, cache);
if (metrics)
*metrics = *cache;
return cache->width;
}
static Lisp_Object
ftcrfont_list (struct frame *f, Lisp_Object spec)
{
Lisp_Object list = ftfont_driver.list (f, spec), tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
return list;
}
static Lisp_Object
ftcrfont_match (struct frame *f, Lisp_Object spec)
{
Lisp_Object entity = ftfont_driver.match (f, spec);
if (VECTORP (entity))
ASET (entity, FONT_TYPE_INDEX, Qftcr);
return entity;
}
extern FT_Face ftfont_get_ft_face (Lisp_Object);
static Lisp_Object
ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
Lisp_Object font_object;
struct font *font;
struct ftcrfont_info *ftcrfont_info;
FT_Face ft_face;
FT_UInt size;
block_input ();
size = XINT (AREF (entity, FONT_SIZE_INDEX));
if (size == 0)
size = pixel_size;
font_object = font_build_object (VECSIZE (struct ftcrfont_info),
Qftcr, entity, size);
font_object = ftfont_open2 (f, entity, pixel_size, font_object);
if (NILP (font_object)) return Qnil;
font = XFONT_OBJECT (font_object);
font->driver = &ftcrfont_driver;
ftcrfont_info = (struct ftcrfont_info *) font;
ft_face = ftcrfont_info->ft_size->face;
FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
FT_Activate_Size (ftcrfont_info->ft_size_draw);
FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
ftcrfont_info->cr_font_face =
cairo_ft_font_face_create_for_ft_face (ft_face, 0);
ftcrfont_info->metrics = NULL;
ftcrfont_info->metrics_nrows = 0;
unblock_input ();
return font_object;
}
static void
ftcrfont_close (struct font *font)
{
struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
int i;
block_input ();
for (i = 0; i < ftcrfont_info->metrics_nrows; i++)
if (ftcrfont_info->metrics[i])
xfree (ftcrfont_info->metrics[i]);
if (ftcrfont_info->metrics)
xfree (ftcrfont_info->metrics);
FT_Done_Size (ftcrfont_info->ft_size_draw);
cairo_font_face_destroy (ftcrfont_info->cr_font_face);
unblock_input ();
ftfont_driver.close (font);
}
static void
ftcrfont_text_extents (struct font *font,
unsigned *code,
int nglyphs,
struct font_metrics *metrics)
{
int width, i;
block_input ();
width = ftcrfont_glyph_extents (font, code[0], metrics);
for (i = 1; i < nglyphs; i++)
{
struct font_metrics m;
int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL);
if (metrics)
{
if (width + m.lbearing < metrics->lbearing)
metrics->lbearing = width + m.lbearing;
if (width + m.rbearing > metrics->rbearing)
metrics->rbearing = width + m.rbearing;
if (m.ascent > metrics->ascent)
metrics->ascent = m.ascent;
if (m.descent > metrics->descent)
metrics->descent = m.descent;
}
width += w;
}
unblock_input ();
if (metrics)
metrics->width = width;
}
static int
ftcrfont_draw (struct glyph_string *s,
int from, int to, int x, int y, bool with_background)
{
struct frame *f = s->f;
struct face *face = s->face;
struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) s->font;
cairo_t *cr;
cairo_glyph_t *glyphs;
cairo_surface_t *surface;
cairo_surface_type_t surface_type;
int len = to - from;
int i;
block_input ();
cr = x_begin_cr_clip (f, s->gc);
if (with_background)
{
x_set_cr_source_with_gc_background (f, s->gc);
cairo_rectangle (cr, x, y - FONT_BASE (face->font),
s->width, FONT_HEIGHT (face->font));
cairo_fill (cr);
}
glyphs = alloca (sizeof (cairo_glyph_t) * len);
for (i = 0; i < len; i++)
{
unsigned code = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
| XCHAR2B_BYTE2 (s->char2b + from + i));
glyphs[i].index = code;
glyphs[i].x = x;
glyphs[i].y = y;
x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, code, NULL));
}
x_set_cr_source_with_gc_foreground (f, s->gc);
cairo_set_font_face (cr, ftcrfont_info->cr_font_face);
cairo_set_font_size (cr, s->font->pixel_size);
/* cairo_set_font_matrix */
/* cairo_set_font_options */
FT_Activate_Size (ftcrfont_info->ft_size_draw);
cairo_show_glyphs (cr, glyphs, len);
surface = cairo_get_target (cr);
/* XXX: It used to be necessary to flush when exporting. It might
be the case that this is no longer necessary. */
surface_type = cairo_surface_get_type (surface);
if (surface_type != CAIRO_SURFACE_TYPE_XLIB
&& (surface_type != CAIRO_SURFACE_TYPE_IMAGE
|| cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32))
cairo_surface_flush (surface);
x_end_cr_clip (f);
unblock_input ();
return len;
}
void
syms_of_ftcrfont (void)
{
if (ftfont_info_size != offsetof (struct ftcrfont_info, cr_font_face))
abort ();
DEFSYM (Qftcr, "ftcr");
ftcrfont_driver = ftfont_driver;
ftcrfont_driver.type = Qftcr;
ftcrfont_driver.list = ftcrfont_list;
ftcrfont_driver.match = ftcrfont_match;
ftcrfont_driver.open = ftcrfont_open;
ftcrfont_driver.close = ftcrfont_close;
ftcrfont_driver.text_extents = ftcrfont_text_extents;
ftcrfont_driver.draw = ftcrfont_draw;
register_font_driver (&ftcrfont_driver, NULL);
}

View file

@ -67,6 +67,8 @@ struct ftfont_info
FT_Matrix matrix;
};
size_t ftfont_info_size = sizeof (struct ftfont_info);
enum ftfont_cache_for
{
FTFONT_CACHE_FOR_FACE,
@ -1161,8 +1163,11 @@ ftfont_list_family (struct frame *f)
}
static Lisp_Object
ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
Lisp_Object
ftfont_open2 (struct frame *f,
Lisp_Object entity,
int pixel_size,
Lisp_Object font_object)
{
struct ftfont_info *ftfont_info;
struct font *font;
@ -1170,7 +1175,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
FT_Face ft_face;
FT_Size ft_size;
FT_UInt size;
Lisp_Object val, filename, idx, cache, font_object;
Lisp_Object val, filename, idx, cache;
bool scalable;
int spacing;
int i;
@ -1210,8 +1215,6 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
return Qnil;
}
font_object = font_build_object (VECSIZE (struct ftfont_info),
Qfreetype, entity, size);
ASET (font_object, FONT_FILE_INDEX, filename);
font = XFONT_OBJECT (font_object);
ftfont_info = (struct ftfont_info *) font;
@ -1294,6 +1297,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
return font_object;
}
static Lisp_Object
ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
Lisp_Object font_object;
FT_UInt size;
size = XINT (AREF (entity, FONT_SIZE_INDEX));
if (size == 0)
size = pixel_size;
font_object = font_build_object (VECSIZE (struct ftfont_info),
Qfreetype, entity, size);
return ftfont_open2 (f, entity, pixel_size, font_object);
}
static void
ftfont_close (struct font *font)
{

View file

@ -37,6 +37,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* HAVE_LIBOTF */
extern FcCharSet *ftfont_get_fc_charset (Lisp_Object);
extern Lisp_Object ftfont_open2 (struct frame *f,
Lisp_Object entity,
int pixel_size,
Lisp_Object font_object);
extern size_t ftfont_info_size;
#endif /* EMACS_FTFONT_H */

View file

@ -847,22 +847,23 @@ xg_clear_under_internal_border (struct frame *f)
{
if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
{
#ifndef USE_CAIRO
GtkWidget *wfixed = f->output_data.x->edit_widget;
gtk_widget_queue_draw (wfixed);
gdk_window_process_all_updates ();
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0,
#endif
x_clear_area (f, 0, 0,
FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0,
x_clear_area (f, 0, 0,
FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0,
x_clear_area (f, 0,
FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
x_clear_area (f,
FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
}
@ -2141,12 +2142,18 @@ xg_get_font (struct frame *f, const char *default_name)
PangoWeight weight = pango_font_description_get_weight (desc);
PangoStyle style = pango_font_description_get_style (desc);
#ifdef USE_CAIRO
#define FONT_TYPE_WANTED (Qftcr)
#else
#define FONT_TYPE_WANTED (Qxft)
#endif
font = CALLN (Ffont_spec,
QCname, build_string (name),
QCsize, make_float (pango_units_to_double (size)),
QCweight, XG_WEIGHT_TO_SYMBOL (weight),
QCslant, XG_STYLE_TO_SYMBOL (style),
QCtype, Qxft);
QCtype,
FONT_TYPE_WANTED);
pango_font_description_free (desc);
dupstring (&x_last_font_name, name);
@ -3806,8 +3813,10 @@ xg_update_scrollbar_pos (struct frame *f,
gtk_widget_show_all (wparent);
gtk_widget_set_size_request (wscroll, width, height);
}
#ifndef USE_CAIRO
gtk_widget_queue_draw (wfixed);
gdk_window_process_all_updates ();
#endif
if (oldx != -1 && oldw > 0 && oldh > 0)
{
/* Clear under old scroll bar position. This must be done after
@ -3815,8 +3824,7 @@ xg_update_scrollbar_pos (struct frame *f,
above. */
oldw += (scale - 1) * oldw;
oldx -= (scale - 1) * oldw;
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
oldx, oldy, oldw, oldh);
x_clear_area (f, oldx, oldy, oldw, oldh);
}
/* GTK does not redraw until the main loop is entered again, but
@ -3882,7 +3890,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
/* Clear under old scroll bar position. This must be done after
the gtk_widget_queue_draw and gdk_window_process_all_updates
above. */
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
x_clear_area (f,
oldx, oldy, oldw, oldh);
/* 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)
return retval;
}
/***********************************************************************
Printing
***********************************************************************/
#ifdef USE_CAIRO
static GtkPrintSettings *print_settings = NULL;
static GtkPageSetup *page_setup = NULL;
void
xg_page_setup_dialog (void)
{
GtkPageSetup *new_page_setup = NULL;
if (print_settings == NULL)
print_settings = gtk_print_settings_new ();
new_page_setup = gtk_print_run_page_setup_dialog (NULL, page_setup,
print_settings);
if (page_setup)
g_object_unref (page_setup);
page_setup = new_page_setup;
}
Lisp_Object
xg_get_page_setup (void)
{
Lisp_Object result, orientation_symbol;
GtkPageOrientation orientation;
if (page_setup == NULL)
page_setup = gtk_page_setup_new ();
result = list4 (Fcons (Qleft_margin,
make_float (gtk_page_setup_get_left_margin (page_setup,
GTK_UNIT_POINTS))),
Fcons (Qright_margin,
make_float (gtk_page_setup_get_right_margin (page_setup,
GTK_UNIT_POINTS))),
Fcons (Qtop_margin,
make_float (gtk_page_setup_get_top_margin (page_setup,
GTK_UNIT_POINTS))),
Fcons (Qbottom_margin,
make_float (gtk_page_setup_get_bottom_margin (page_setup,
GTK_UNIT_POINTS))));
result = Fcons (Fcons (Qheight,
make_float (gtk_page_setup_get_page_height (page_setup,
GTK_UNIT_POINTS))),
result);
result = Fcons (Fcons (Qwidth,
make_float (gtk_page_setup_get_page_width (page_setup,
GTK_UNIT_POINTS))),
result);
orientation = gtk_page_setup_get_orientation (page_setup);
if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT)
orientation_symbol = Qportrait;
else if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE)
orientation_symbol = Qlandscape;
else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
orientation_symbol = Qreverse_portrait;
else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
orientation_symbol = Qreverse_landscape;
result = Fcons (Fcons (Qorientation, orientation_symbol), result);
return result;
}
static void
draw_page (GtkPrintOperation *operation, GtkPrintContext *context,
gint page_nr, gpointer user_data)
{
Lisp_Object frames = *((Lisp_Object *) user_data);
struct frame *f = XFRAME (Fnth (make_number (page_nr), frames));
cairo_t *cr = gtk_print_context_get_cairo_context (context);
x_cr_draw_frame (cr, f);
}
void
xg_print_frames_dialog (Lisp_Object frames)
{
GtkPrintOperation *print;
GtkPrintOperationResult res;
print = gtk_print_operation_new ();
if (print_settings != NULL)
gtk_print_operation_set_print_settings (print, print_settings);
if (page_setup != NULL)
gtk_print_operation_set_default_page_setup (print, page_setup);
gtk_print_operation_set_n_pages (print, XINT (Flength (frames)));
g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), &frames);
res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
NULL, NULL);
if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
{
if (print_settings != NULL)
g_object_unref (print_settings);
print_settings =
g_object_ref (gtk_print_operation_get_print_settings (print));
}
g_object_unref (print);
}
#endif /* USE_CAIRO */
/***********************************************************************

View file

@ -180,6 +180,12 @@ extern bool xg_prepare_tooltip (struct frame *f,
extern void xg_show_tooltip (struct frame *f, int root_x, int root_y);
extern bool xg_hide_tooltip (struct frame *f);
#ifdef USE_CAIRO
extern void xg_page_setup_dialog (void);
extern Lisp_Object xg_get_page_setup (void);
extern void xg_print_frames_dialog (Lisp_Object);
#endif
/* Mark all callback data that are Lisp_object:s during GC. */
extern void xg_mark_data (void);

View file

@ -88,6 +88,10 @@ typedef struct w32_bitmap_record Bitmap_Record;
#endif /* HAVE_NTGUI */
#ifdef USE_CAIRO
#undef COLOR_TABLE_SUPPORT
#endif
#ifdef HAVE_NS
#undef COLOR_TABLE_SUPPORT
@ -514,7 +518,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
#endif /* HAVE_X_WINDOWS */
/***********************************************************************
Image types
***********************************************************************/
@ -1019,6 +1022,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
/* We're about to display IMG, so set its timestamp to `now'. */
img->timestamp = current_timespec ();
#ifndef USE_CAIRO
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
@ -1032,6 +1036,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
unblock_input ();
}
#endif
#endif
}
@ -1078,6 +1083,54 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
return ascent;
}
#ifdef USE_CAIRO
static uint32_t
xcolor_to_argb32 (XColor xc)
{
return (0xff << 24) | ((xc.red / 256) << 16)
| ((xc.green / 256) << 8) | (xc.blue / 256);
}
static uint32_t
get_spec_bg_or_alpha_as_argb (struct image *img,
struct frame *f)
{
uint32_t bgcolor = 0;
XColor xbgcolor;
Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
FRAME_X_COLORMAP (f),
SSDATA (bg),
&xbgcolor))
bgcolor = xcolor_to_argb32 (xbgcolor);
return bgcolor;
}
static void
create_cairo_image_surface (struct image *img,
unsigned char *data,
int width,
int height)
{
cairo_surface_t *surface;
cairo_format_t format = CAIRO_FORMAT_ARGB32;
int stride = cairo_format_stride_for_width (format, width);
surface = cairo_image_surface_create_for_data (data,
format,
width,
height,
stride);
img->width = width;
img->height = height;
img->cr_data = surface;
img->cr_data2 = data;
img->pixmap = 0;
}
#endif
/* Image background colors. */
@ -1299,6 +1352,11 @@ static void
x_clear_image (struct frame *f, struct image *img)
{
block_input ();
#ifdef USE_CAIRO
if (img->cr_data)
cairo_surface_destroy ((cairo_surface_t *)img->cr_data);
if (img->cr_data2) xfree (img->cr_data2);
#endif
x_clear_image_1 (f, img,
CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
unblock_input ();
@ -3154,9 +3212,11 @@ static struct image_type xpm_type =
color allocation failures more gracefully than the ones on the XPM
lib. */
#ifndef USE_CAIRO
#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
#define ALLOC_XPM_COLORS
#endif
#endif /* USE_CAIRO */
#endif /* HAVE_X_WINDOWS */
#ifdef ALLOC_XPM_COLORS
@ -3617,6 +3677,44 @@ xpm_load (struct frame *f, struct image *img)
#endif /* HAVE_NTGUI */
}
#ifdef USE_CAIRO
// Load very specific Xpm:s.
if (rc == XpmSuccess
&& img->ximg->format == ZPixmap
&& img->ximg->bits_per_pixel == 32
&& (! img->mask_img || img->mask_img->bits_per_pixel == 1))
{
int width = img->ximg->width;
int height = img->ximg->height;
unsigned char *data = (unsigned char *) xmalloc (width*height*4);
int i;
uint32_t *od = (uint32_t *)data;
uint32_t *id = (uint32_t *)img->ximg->data;
unsigned char *mid = img->mask_img ? img->mask_img->data : 0;
uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
for (i = 0; i < height; ++i)
{
int k;
for (k = 0; k < width; ++k)
{
int idx = i * img->ximg->bytes_per_line/4 + k;
int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0;
int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1;
if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha
else od[idx] = bgcolor;
}
}
create_cairo_image_surface (img, data, width, height);
}
else
{
rc = XpmFileInvalid;
x_clear_image (f, img);
}
#else
#ifdef HAVE_X_WINDOWS
if (rc == XpmSuccess)
{
@ -3642,6 +3740,7 @@ xpm_load (struct frame *f, struct image *img)
}
}
#endif
#endif /* ! USE_CAIRO */
if (rc == XpmSuccess)
{
@ -5148,12 +5247,17 @@ pbm_load (struct frame *f, struct image *img)
bool raw_p;
int x, y;
int width, height, max_color_idx = 0;
XImagePtr ximg;
Lisp_Object file, specified_file;
enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
unsigned char *contents = NULL;
unsigned char *end, *p;
ptrdiff_t size;
#ifdef USE_CAIRO
unsigned char *data = 0;
uint32_t *dataptr;
#else
XImagePtr ximg;
#endif
specified_file = image_spec_value (img->spec, QCfile, NULL);
@ -5235,6 +5339,11 @@ pbm_load (struct frame *f, struct image *img)
width = pbm_scan_number (&p, end);
height = pbm_scan_number (&p, end);
#ifdef USE_CAIRO
data = (unsigned char *) xmalloc (width * height * 4);
dataptr = (uint32_t *) data;
#endif
if (type != PBM_MONO)
{
max_color_idx = pbm_scan_number (&p, end);
@ -5251,8 +5360,10 @@ pbm_load (struct frame *f, struct image *img)
goto error;
}
#ifndef USE_CAIRO
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
goto error;
#endif
/* Initialize the color hash table. */
init_color_table ();
@ -5263,12 +5374,34 @@ pbm_load (struct frame *f, struct image *img)
struct image_keyword fmt[PBM_LAST];
unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
#ifdef USE_CAIRO
XColor xfg, xbg;
int fga32, bga32;
#endif
/* Parse the image specification. */
memcpy (fmt, pbm_format, sizeof fmt);
parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
/* Get foreground and background colors, maybe allocate colors. */
#ifdef USE_CAIRO
if (! fmt[PBM_FOREGROUND].count
|| ! STRINGP (fmt[PBM_FOREGROUND].value)
|| ! x_defined_color (f, SSDATA (fmt[PBM_FOREGROUND].value), &xfg, 0))
{
xfg.pixel = fg;
x_query_color (f, &xfg);
}
fga32 = xcolor_to_argb32 (xfg);
if (! fmt[PBM_BACKGROUND].count
|| ! STRINGP (fmt[PBM_BACKGROUND].value)
|| ! x_defined_color (f, SSDATA (fmt[PBM_BACKGROUND].value), &xbg, 0))
{
xbg.pixel = bg;
x_query_color (f, &xbg);
}
bga32 = xcolor_to_argb32 (xbg);
#else
if (fmt[PBM_FOREGROUND].count
&& STRINGP (fmt[PBM_FOREGROUND].value))
fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
@ -5279,6 +5412,7 @@ pbm_load (struct frame *f, struct image *img)
img->background = bg;
img->background_valid = 1;
}
#endif
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
@ -5289,7 +5423,11 @@ pbm_load (struct frame *f, struct image *img)
{
if (p >= end)
{
#ifdef USE_CAIRO
xfree (data);
#else
x_destroy_x_image (ximg);
#endif
x_clear_image (f, img);
image_error ("Invalid image size in image `%s'",
img->spec, Qnil);
@ -5303,7 +5441,11 @@ pbm_load (struct frame *f, struct image *img)
else
g = pbm_scan_number (&p, end);
#ifdef USE_CAIRO
*dataptr++ = g ? fga32 : bga32;
#else
XPutPixel (ximg, x, y, g ? fg : bg);
#endif
}
}
else
@ -5316,7 +5458,11 @@ pbm_load (struct frame *f, struct image *img)
if (raw_p && p + expected_size > end)
{
#ifdef USE_CAIRO
xfree (data);
#else
x_destroy_x_image (ximg);
#endif
x_clear_image (f, img);
image_error ("Invalid image size in image `%s'",
img->spec, Qnil);
@ -5357,18 +5503,29 @@ pbm_load (struct frame *f, struct image *img)
if (r < 0 || g < 0 || b < 0)
{
#ifdef USE_CAIRO
xfree (data);
#else
x_destroy_x_image (ximg);
#endif
image_error ("Invalid pixel value in image `%s'",
img->spec, Qnil);
goto error;
}
#ifdef USE_CAIRO
r = (double) r * 255 / max_color_idx;
g = (double) g * 255 / max_color_idx;
b = (double) b * 255 / max_color_idx;
*dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
#else
/* RGB values are now in the range 0..max_color_idx.
Scale this to the range 0..0xffff supported by X. */
r = (double) r * 65535 / max_color_idx;
g = (double) g * 65535 / max_color_idx;
b = (double) b * 65535 / max_color_idx;
XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
#endif
}
}
@ -5384,12 +5541,16 @@ pbm_load (struct frame *f, struct image *img)
/* Maybe fill in the background field while we have ximg handy. */
#ifdef USE_CAIRO
create_cairo_image_surface (img, data, width, height);
#else
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
#endif
/* X and W32 versions did it here, MAC version above. ++kfs
img->width = width;
@ -5404,7 +5565,7 @@ pbm_load (struct frame *f, struct image *img)
PNG
***********************************************************************/
#if defined (HAVE_PNG) || defined (HAVE_NS)
#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
/* Function prototypes. */
@ -5478,7 +5639,7 @@ png_image_p (Lisp_Object object)
return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
}
#endif /* HAVE_PNG || HAVE_NS */
#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
#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)
Lisp_Object specified_data;
int x, y;
ptrdiff_t i;
XImagePtr ximg, mask_img = NULL;
png_struct *png_ptr;
png_info *info_ptr = NULL, *end_info = NULL;
FILE *fp = NULL;
@ -5727,6 +5887,13 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
bool transparent_p;
struct png_memory_storage tbr; /* Data to be read */
#ifdef USE_CAIRO
unsigned char *data = 0;
uint32_t *dataptr;
#else
XImagePtr ximg, mask_img = NULL;
#endif
/* Find out what file to load. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
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)
goto error;
}
#ifndef USE_CAIRO
/* Create the X image and pixmap now, so that the work below can be
omitted if the image is too large for X. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
goto error;
#endif
/* If image contains simply transparency data, we prefer to
construct a clipping mask. */
@ -5937,6 +6106,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
c->fp = NULL;
}
#ifdef USE_CAIRO
data = (unsigned char *) xmalloc (width * height * 4);
dataptr = (uint32_t *) data;
#else
/* Create an image and pixmap serving as mask if the PNG image
contains an alpha channel. */
if (channels == 4
@ -5948,6 +6121,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
goto error;
}
#endif
/* Fill the X image and mask from PNG data. */
init_color_table ();
@ -5960,6 +6134,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
{
int r, g, b;
#ifdef USE_CAIRO
int a = 0xff;
r = *p++;
g = *p++;
b = *p++;
if (channels == 4) a = *p++;
*dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
#else
r = *p++ << 8;
g = *p++ << 8;
b = *p++ << 8;
@ -5986,6 +6168,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
++p;
}
#endif
}
}
@ -6015,6 +6198,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
img->width = width;
img->height = height;
#ifdef USE_CAIRO
create_cairo_image_surface (img, data, width, height);
#else
/* Maybe fill in the background field while we have ximg handy.
Casting avoids a GCC warning. */
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)
image_put_x_image (f, img, mask_img, 1);
}
#endif
return 1;
}
@ -6052,6 +6239,7 @@ png_load (struct frame *f, struct image *img)
image_spec_value (img->spec, QCdata, NULL));
}
#endif /* HAVE_NS */
@ -6463,9 +6651,12 @@ jpeg_load_body (struct frame *f, struct image *img,
FILE * IF_LINT (volatile) fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
XImagePtr ximg = NULL;
unsigned long *colors;
int width, height;
int i, ir, ig, ib;
#ifndef USE_CAIRO
XImagePtr ximg = NULL;
#endif
/* Open the JPEG file. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
@ -6525,8 +6716,9 @@ jpeg_load_body (struct frame *f, struct image *img,
jpeg_destroy_decompress (&mgr->cinfo);
/* If we already have an XImage, free that. */
#ifndef USE_CAIRO
x_destroy_x_image (ximg);
#endif
/* Free pixmap and colors. */
x_clear_image (f, img);
return 0;
@ -6560,12 +6752,14 @@ jpeg_load_body (struct frame *f, struct image *img,
sys_longjmp (mgr->setjmp_buffer, 1);
}
#ifndef USE_CAIRO
/* Create X image and pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
sys_longjmp (mgr->setjmp_buffer, 1);
}
#endif
/* Allocate colors. When color quantization is used,
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,
No more than 255 colors will be generated. */
USE_SAFE_ALLOCA;
{
int i, ir, ig, ib;
if (mgr->cinfo.out_color_components > 2)
ir = 0, ig = 1, ib = 2;
else if (mgr->cinfo.out_color_components > 1)
@ -6583,6 +6775,7 @@ jpeg_load_body (struct frame *f, struct image *img,
else
ir = 0, ig = 0, ib = 0;
#ifndef CAIRO
/* Use the color table mechanism because it handles colors that
cannot be allocated nicely. Such colors will be replaced with
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,
int b = mgr->cinfo.colormap[ib][i] << 8;
colors[i] = lookup_rgb_color (f, r, g, b);
}
#endif
#ifdef COLOR_TABLE_SUPPORT
/* Remember those colors actually allocated. */
@ -6611,12 +6805,36 @@ jpeg_load_body (struct frame *f, struct image *img,
row_stride = width * mgr->cinfo.output_components;
buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
JPOOL_IMAGE, row_stride, 1);
#ifdef USE_CAIRO
{
unsigned char *data = (unsigned char *) xmalloc (width*height*4);
uint32_t *dataptr = (uint32_t *) data;
int r, g, b;
for (y = 0; y < height; ++y)
{
jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
for (x = 0; x < width; ++x)
{
i = buffer[0][x];
r = mgr->cinfo.colormap[ir][i];
g = mgr->cinfo.colormap[ig][i];
b = mgr->cinfo.colormap[ib][i];
*dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
}
}
create_cairo_image_surface (img, data, width, height);
}
#else
for (y = 0; y < height; ++y)
{
jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
for (x = 0; x < mgr->cinfo.output_width; ++x)
XPutPixel (ximg, x, y, colors[buffer[0][x]]);
}
#endif
/* Clean up. */
jpeg_finish_decompress (&mgr->cinfo);
@ -6624,6 +6842,7 @@ jpeg_load_body (struct frame *f, struct image *img,
if (fp)
fclose (fp);
#ifndef USE_CAIRO
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
@ -6631,6 +6850,7 @@ jpeg_load_body (struct frame *f, struct image *img,
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
#endif
SAFE_FREE ();
return 1;
}
@ -7063,6 +7283,29 @@ tiff_load (struct frame *f, struct image *img)
return 0;
}
#ifdef USE_CAIRO
{
unsigned char *data = (unsigned char *) xmalloc (width*height*4);
uint32_t *dataptr = (uint32_t *) data;
int r, g, b, a;
for (y = 0; y < height; ++y)
{
uint32 *row = buf + (height - 1 - y) * width;
for (x = 0; x < width; ++x)
{
uint32 abgr = row[x];
int r = TIFFGetR (abgr);
int g = TIFFGetG (abgr);
int b = TIFFGetB (abgr);
int a = TIFFGetA (abgr);
*dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
}
}
create_cairo_image_surface (img, data, width, height);
}
#else
/* Initialize the color table. */
init_color_table ();
@ -7097,8 +7340,10 @@ tiff_load (struct frame *f, struct image *img)
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
xfree (buf);
#endif /* ! USE_CAIRO */
xfree (buf);
return 1;
}
@ -7348,7 +7593,6 @@ gif_load (struct frame *f, struct image *img)
{
Lisp_Object file;
int rc, width, height, x, y, i, j;
XImagePtr ximg;
ColorMapObject *gif_color_map;
unsigned long pixel_colors[256];
GifFileType *gif;
@ -7360,6 +7604,12 @@ gif_load (struct frame *f, struct image *img)
EMACS_INT idx;
int gif_err;
#ifdef USE_CAIRO
unsigned char *data = 0;
#else
XImagePtr ximg;
#endif
if (NILP (specified_data))
{
file = x_find_image_file (specified_file);
@ -7488,6 +7738,25 @@ gif_load (struct frame *f, struct image *img)
}
}
#ifdef USE_CAIRO
/* xzalloc so data is zero => transparent */
data = (unsigned char *) xzalloc (width * height * 4);
if (STRINGP (specified_bg))
{
XColor color;
if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
{
uint32_t *dataptr = (uint32_t *)data;
int r = color.red/256;
int g = color.green/256;
int b = color.blue/256;
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
*dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
}
}
#else
/* Create the X image and pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
@ -7514,6 +7783,7 @@ gif_load (struct frame *f, struct image *img)
for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
#endif
/* Read the GIF image into the X image. */
@ -7568,12 +7838,14 @@ gif_load (struct frame *f, struct image *img)
if (disposal == 0)
disposal = 1;
/* Allocate subimage colors. */
memset (pixel_colors, 0, sizeof pixel_colors);
gif_color_map = subimage->ImageDesc.ColorMap;
if (!gif_color_map)
gif_color_map = gif->SColorMap;
#ifndef USE_CAIRO
/* Allocate subimage colors. */
memset (pixel_colors, 0, sizeof pixel_colors);
if (gif_color_map)
for (i = 0; i < gif_color_map->ColorCount; ++i)
{
@ -7588,6 +7860,7 @@ gif_load (struct frame *f, struct image *img)
pixel_colors[i] = lookup_rgb_color (f, r, g, b);
}
}
#endif
/* Apply the pixel values. */
if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace)
@ -7605,20 +7878,47 @@ gif_load (struct frame *f, struct image *img)
{
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
XPutPixel (ximg, x + subimg_left, row + subimg_top,
pixel_colors[c]);
{
#ifdef USE_CAIRO
uint32_t *dataptr =
((uint32_t*)data + ((row + subimg_top) * subimg_width
+ x + subimg_left));
int r = gif_color_map->Colors[c].Red;
int g = gif_color_map->Colors[c].Green;
int b = gif_color_map->Colors[c].Blue;
if (transparency_color_index != c)
*dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
#else
XPutPixel (ximg, x + subimg_left, row + subimg_top,
pixel_colors[c]);
#endif
}
}
}
}
else
{
for (y = 0; y < subimg_height; ++y)
for (y = 0; y < subimg_height; ++y)
for (x = 0; x < subimg_width; ++x)
{
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
XPutPixel (ximg, x + subimg_left, y + subimg_top,
pixel_colors[c]);
{
#ifdef USE_CAIRO
uint32_t *dataptr =
((uint32_t*)data + ((y + subimg_top) * subimg_width
+ x + subimg_left));
int r = gif_color_map->Colors[c].Red;
int g = gif_color_map->Colors[c].Green;
int b = gif_color_map->Colors[c].Blue;
if (transparency_color_index != c)
*dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
#else
XPutPixel (ximg, x + subimg_left, y + subimg_top,
pixel_colors[c]);
#endif
}
}
}
}
@ -7675,6 +7975,9 @@ gif_load (struct frame *f, struct image *img)
#endif
}
#ifdef USE_CAIRO
create_cairo_image_surface (img, data, width, height);
#else
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
@ -7682,6 +7985,7 @@ gif_load (struct frame *f, struct image *img)
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
#endif
return 1;
}
@ -8901,6 +9205,37 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
eassert (gdk_pixbuf_get_has_alpha (pixbuf));
eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
#ifdef USE_CAIRO
{
unsigned char *data = (unsigned char *) xmalloc (width*height*4);
int y;
uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
for (y = 0; y < height; ++y)
{
const guchar *iconptr = pixels + y * rowstride;
uint32_t *dataptr = (uint32_t *) (data + y * rowstride);
int x;
for (x = 0; x < width; ++x)
{
if (iconptr[3] == 0)
*dataptr = bgcolor;
else
*dataptr = (iconptr[0] << 16)
| (iconptr[1] << 8)
| iconptr[2]
| (iconptr[3] << 24);
iconptr += 4;
++dataptr;
}
}
create_cairo_image_surface (img, data, width, height);
g_object_unref (pixbuf);
}
#else
/* Try to create a x pixmap to hold the svg pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
@ -8972,6 +9307,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
#endif /* ! USE_CAIRO */
return 1;
@ -9239,15 +9575,16 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
/* For each pixel of the image, look its color up in the
color table. After having done so, the color table will
contain an entry for each color used by the image. */
#ifdef COLOR_TABLE_SUPPORT
for (y = 0; y < img->height; ++y)
for (x = 0; x < img->width; ++x)
{
unsigned long pixel = XGetPixel (ximg, x, y);
lookup_pixel_color (f, pixel);
}
/* Record colors in the image. Free color table and XImage. */
#ifdef COLOR_TABLE_SUPPORT
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
#endif
@ -9360,7 +9697,7 @@ lookup_image_type (Lisp_Object type)
return define_image_type (&gif_type);
#endif
#if defined (HAVE_PNG) || defined (HAVE_NS)
#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
if (EQ (type, Qpng))
return define_image_type (&png_type);
#endif

View file

@ -3116,6 +3116,9 @@ This function is an internal primitive--use `make-frame' instead. */)
specbind (Qx_resource_name, name);
}
#ifdef USE_CAIRO
register_font_driver (&ftcrfont_driver, f);
#else
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
register_font_driver (&xftfont_driver, f);
@ -3124,6 +3127,7 @@ This function is an internal primitive--use `make-frame' instead. */)
#endif /* not HAVE_XFT */
#endif /* HAVE_FREETYPE */
register_font_driver (&xfont_driver, f);
#endif /* not USE_CAIRO */
x_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
@ -5118,6 +5122,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
specbind (Qx_resource_name, name);
}
#ifdef USE_CAIRO
register_font_driver (&ftcrfont_driver, f);
#else
register_font_driver (&xfont_driver, f);
#ifdef HAVE_FREETYPE
#ifdef HAVE_XFT
@ -5126,6 +5133,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
register_font_driver (&ftxfont_driver, f);
#endif /* not HAVE_XFT */
#endif /* HAVE_FREETYPE */
#endif /* not USE_CAIRO */
x_default_parameter (f, parms, Qfont_backend, Qnil,
"fontBackend", "FontBackend", RES_TYPE_STRING);
@ -6207,6 +6215,158 @@ present and mapped to the usual X keysyms. */)
}
/***********************************************************************
Printing
***********************************************************************/
#ifdef USE_CAIRO
DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
doc: /* XXX Experimental. Return image data of FRAMES in TYPE format.
FRAMES should be nil (the selected frame), a frame, or a list of
frames (each of which corresponds to one page). Optional arg TYPE
should be either `pdf' (default), `png', `ps', or `svg'. Supported
types are determined by the compile-time configuration of cairo. */)
(Lisp_Object frames, Lisp_Object type)
{
Lisp_Object result, rest, tmp;
cairo_surface_type_t surface_type;
if (NILP (frames))
frames = selected_frame;
if (!CONSP (frames))
frames = list1 (frames);
tmp = Qnil;
for (rest = frames; CONSP (rest); rest = XCDR (rest))
{
struct frame *f = XFRAME (XCAR (rest));
if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
error ("Invalid frame");
Lisp_Object frame;
XSETFRAME (frame, f);
tmp = Fcons (frame, tmp);
}
frames = Fnreverse (tmp);
#ifdef CAIRO_HAS_PDF_SURFACE
if (NILP (type) || EQ (type, intern ("pdf"))) /* XXX: Qpdf */
surface_type = CAIRO_SURFACE_TYPE_PDF;
else
#endif
#ifdef CAIRO_HAS_PNG_FUNCTIONS
if (EQ (type, intern ("png")))
{
if (!NILP (XCDR (frames)))
error ("PNG export cannot handle multiple frames.");
surface_type = CAIRO_SURFACE_TYPE_IMAGE;
}
else
#endif
#ifdef CAIRO_HAS_PS_SURFACE
if (EQ (type, intern ("ps")))
surface_type = CAIRO_SURFACE_TYPE_PS;
else
#endif
#ifdef CAIRO_HAS_SVG_SURFACE
if (EQ (type, intern ("svg")))
{
/* For now, we stick to SVG 1.1. */
if (!NILP (XCDR (frames)))
error ("SVG export cannot handle multiple frames.");
surface_type = CAIRO_SURFACE_TYPE_SVG;
}
else
#endif
error ("Unsupported export type");
result = x_cr_export_frames (frames, surface_type);
return result;
}
#ifdef USE_GTK
DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
doc: /* Pop up a page setup dialog.
The current page setup can be obtained using `x-get-page-setup'. */)
(void)
{
block_input ();
xg_page_setup_dialog ();
unblock_input ();
return Qnil;
}
DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
doc: /* Return the value of the current page setup.
The return value is an alist containing the following keys:
orientation: page orientation (symbol `portrait', `landscape',
`reverse-portrait', or `reverse-landscape').
width, height: page width/height in points not including margins.
left-margin, right-margin, top-margin, bottom-margin: print margins,
which is the parts of the page that the printer cannot print
on, in points.
The paper width can be obtained as the sum of width, left-margin, and
right-margin values. Likewise, the paper height is the sum of height,
top-margin, and bottom-margin values. */)
(void)
{
Lisp_Object result;
block_input ();
result = xg_get_page_setup ();
unblock_input ();
return result;
}
DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
doc: /* Pop up a print dialog to print the current contents of FRAMES.
FRAMES should be nil (the selected frame), a frame, or a list of
frames (each of which corresponds to one page). Each frame should be
visible. */)
(Lisp_Object frames)
{
Lisp_Object rest, tmp;
if (NILP (frames))
frames = selected_frame;
if (!CONSP (frames))
frames = list1 (frames);
tmp = Qnil;
for (rest = frames; CONSP (rest); rest = XCDR (rest))
{
struct frame *f = XFRAME (XCAR (rest));
if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
error ("Invalid frame");
Lisp_Object frame;
XSETFRAME (frame, f);
if (!EQ (Fframe_visible_p (frame), Qt))
error ("Frames to be printed must be visible.");
tmp = Fcons (frame, tmp);
}
frames = Fnreverse (tmp);
/* Make sure the current matrices are up-to-date. */
Fredisplay (Qt);
block_input ();
xg_print_frames_dialog (frames);
unblock_input ();
return Qnil;
}
#endif /* USE_GTK */
#endif /* USE_CAIRO */
/***********************************************************************
Initialization
@ -6265,6 +6425,16 @@ syms_of_xfns (void)
DEFSYM (Qfont_param, "font-parameter");
DEFSYM (Qmono, "mono");
#ifdef USE_CAIRO
DEFSYM (Qorientation, "orientation");
DEFSYM (Qtop_margin, "top-margin");
DEFSYM (Qbottom_margin, "bottom-margin");
DEFSYM (Qportrait, "portrait");
DEFSYM (Qlandscape, "landscape");
DEFSYM (Qreverse_portrait, "reverse-portrait");
DEFSYM (Qreverse_landscape, "reverse-landscape");
#endif
Fput (Qundefined_color, Qerror_conditions,
listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
Fput (Qundefined_color, Qerror_message,
@ -6405,6 +6575,20 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
}
#endif /* USE_GTK */
#ifdef USE_CAIRO
Fprovide (intern_c_string ("cairo"), Qnil);
DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
doc: /* Version info for cairo. */);
{
char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
int len = sprintf (cairo_version, "%d.%d.%d",
CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
CAIRO_VERSION_MICRO);
Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
}
#endif
/* X window properties. */
defsubr (&Sx_change_window_property);
defsubr (&Sx_delete_window_property);
@ -6455,4 +6639,13 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
#if defined (USE_GTK) && defined (HAVE_FREETYPE)
defsubr (&Sx_select_font);
#endif
#ifdef USE_CAIRO
defsubr (&Sx_export_frames);
#ifdef USE_GTK
defsubr (&Sx_page_setup_dialog);
defsubr (&Sx_get_page_setup);
defsubr (&Sx_print_frames_dialog);
#endif
#endif
}

File diff suppressed because it is too large Load diff

View file

@ -70,6 +70,19 @@ typedef GtkWidget *xt_or_gtk_widget;
#define USE_GTK_TOOLTIP
#endif
#ifdef USE_CAIRO
#include <cairo-xlib.h>
#ifdef CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
#endif
#ifdef CAIRO_HAS_PS_SURFACE
#include <cairo-ps.h>
#endif
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
#endif
#endif
#ifdef HAVE_X_I18N
#include <X11/Xlocale.h>
#endif
@ -115,6 +128,9 @@ struct xim_inst_t
struct x_bitmap_record
{
#ifdef USE_CAIRO
void *img;
#endif
Pixmap pixmap;
bool have_mask;
Pixmap mask;
@ -123,6 +139,19 @@ struct x_bitmap_record
/* Record some info about this pixmap. */
int height, width, depth;
};
#ifdef USE_CAIRO
struct x_gc_ext_data
{
#define MAX_CLIP_RECTS 2
/* Number of clipping rectangles. */
int n_clip_rects;
/* Clipping rectangles. */
XRectangle clip_rects[MAX_CLIP_RECTS];
};
#endif
/* For each X display, we have a structure that records
information about it. */
@ -411,6 +440,10 @@ struct x_display_info
/* SM */
Atom Xatom_SM_CLIENT_ID;
#ifdef USE_CAIRO
XExtCodes *ext_codes;
#endif
};
#ifdef HAVE_X_I18N
@ -636,7 +669,6 @@ struct x_output
/* The offset we need to add to compensate for type A WMs. */
int move_offset_top;
int move_offset_left;
};
/* Extreme 'short' and 'long' values suitable for libX11. */
#define X_SHRT_MAX 0x7fff
@ -645,6 +677,14 @@ struct x_output
#define X_LONG_MIN (-1 - X_LONG_MAX)
#define X_ULONG_MAX 0xffffffffUL
#ifdef USE_CAIRO
/* Cairo drawing context. */
cairo_t *cr_context;
/* Cairo surface for double buffering */
cairo_surface_t *cr_surface;
#endif
};
#define No_Cursor (None)
enum
@ -991,7 +1031,8 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
double, int);
#endif
extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *);
extern void x_clear_area (Display *, Window, int, int, int, int);
extern void x_query_color (struct frame *f, XColor *);
extern void x_clear_area (struct frame *f, int, int, int, int);
#if !defined USE_X_TOOLKIT && !defined USE_GTK
extern void x_mouse_leave (struct x_display_info *);
#endif
@ -1000,6 +1041,14 @@ extern void x_mouse_leave (struct x_display_info *);
extern int x_dispatch_event (XEvent *, Display *);
#endif
extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
#ifdef USE_CAIRO
extern cairo_t *x_begin_cr_clip (struct frame *, GC);
extern void x_end_cr_clip (struct frame *);
extern void x_set_cr_source_with_gc_foreground (struct frame *, GC);
extern void x_set_cr_source_with_gc_background (struct frame *, GC);
extern void x_cr_draw_frame (cairo_t *, struct frame *);
extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
#endif
INLINE int
x_display_pixel_height (struct x_display_info *dpyinfo)