diff options
| author | Jeff Walsh | 2020-08-27 22:05:15 +1000 |
|---|---|---|
| committer | Jeff Walsh | 2020-11-24 12:24:40 +1100 |
| commit | e75ce0302d4c907c8ff56fb15fc7dd12b48e7370 (patch) | |
| tree | b86e587fc94a6e8f931b64bdcc0830f361c9082b /src | |
| parent | 9704e23f4c2cd56bc8091e2024c7b972a3254bb7 (diff) | |
| download | emacs-e75ce0302d4c907c8ff56fb15fc7dd12b48e7370.tar.gz emacs-e75ce0302d4c907c8ff56fb15fc7dd12b48e7370.zip | |
Add support for x-support-frames
* src/pgtkfns.c (Fx_export_frames):
(syms_of_pgtkfns): port from X11 version
* src/pgtkterm.c (pgtk_cr_accumulate_data):
(pgtk_cr_destroy):
(pgtk_cr_export_frames): port from X11
* src/pgtkterm.h: add defs
Diffstat (limited to 'src')
| -rw-r--r-- | src/pgtkfns.c | 74 | ||||
| -rw-r--r-- | src/pgtkterm.c | 115 | ||||
| -rw-r--r-- | src/pgtkterm.h | 11 |
3 files changed, 199 insertions, 1 deletions
diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 53da9b756aa..06fb4e206f4 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c | |||
| @@ -844,6 +844,78 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, | |||
| 844 | error ("Invalid scroll-bar-background."); | 844 | error ("Invalid scroll-bar-background."); |
| 845 | } | 845 | } |
| 846 | 846 | ||
| 847 | |||
| 848 | /*********************************************************************** | ||
| 849 | Printing | ||
| 850 | ***********************************************************************/ | ||
| 851 | |||
| 852 | |||
| 853 | DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0, | ||
| 854 | doc: /* Return image data of FRAMES in TYPE format. | ||
| 855 | FRAMES should be nil (the selected frame), a frame, or a list of | ||
| 856 | frames (each of which corresponds to one page). Each frame should be | ||
| 857 | visible. Optional arg TYPE should be either `pdf' (default), `png', | ||
| 858 | `postscript', or `svg'. Supported types are determined by the | ||
| 859 | compile-time configuration of cairo. | ||
| 860 | |||
| 861 | Note: Text drawn with the `x' font backend is shown with hollow boxes | ||
| 862 | unless TYPE is `png'. */) | ||
| 863 | (Lisp_Object frames, Lisp_Object type) | ||
| 864 | { | ||
| 865 | Lisp_Object rest, tmp; | ||
| 866 | cairo_surface_type_t surface_type; | ||
| 867 | |||
| 868 | if (!CONSP (frames)) | ||
| 869 | frames = list1 (frames); | ||
| 870 | |||
| 871 | tmp = Qnil; | ||
| 872 | for (rest = frames; CONSP (rest); rest = XCDR (rest)) | ||
| 873 | { | ||
| 874 | struct frame *f = decode_window_system_frame (XCAR (rest)); | ||
| 875 | Lisp_Object frame; | ||
| 876 | |||
| 877 | XSETFRAME (frame, f); | ||
| 878 | if (!FRAME_VISIBLE_P (f)) | ||
| 879 | error ("Frames to be exported must be visible."); | ||
| 880 | tmp = Fcons (frame, tmp); | ||
| 881 | } | ||
| 882 | frames = Fnreverse (tmp); | ||
| 883 | |||
| 884 | #ifdef CAIRO_HAS_PDF_SURFACE | ||
| 885 | if (NILP (type) || EQ (type, Qpdf)) | ||
| 886 | surface_type = CAIRO_SURFACE_TYPE_PDF; | ||
| 887 | else | ||
| 888 | #endif | ||
| 889 | #ifdef CAIRO_HAS_PNG_FUNCTIONS | ||
| 890 | if (EQ (type, Qpng)) | ||
| 891 | { | ||
| 892 | if (!NILP (XCDR (frames))) | ||
| 893 | error ("PNG export cannot handle multiple frames."); | ||
| 894 | surface_type = CAIRO_SURFACE_TYPE_IMAGE; | ||
| 895 | } | ||
| 896 | else | ||
| 897 | #endif | ||
| 898 | #ifdef CAIRO_HAS_PS_SURFACE | ||
| 899 | if (EQ (type, Qpostscript)) | ||
| 900 | surface_type = CAIRO_SURFACE_TYPE_PS; | ||
| 901 | else | ||
| 902 | #endif | ||
| 903 | #ifdef CAIRO_HAS_SVG_SURFACE | ||
| 904 | if (EQ (type, Qsvg)) | ||
| 905 | { | ||
| 906 | /* For now, we stick to SVG 1.1. */ | ||
| 907 | if (!NILP (XCDR (frames))) | ||
| 908 | error ("SVG export cannot handle multiple frames."); | ||
| 909 | surface_type = CAIRO_SURFACE_TYPE_SVG; | ||
| 910 | } | ||
| 911 | else | ||
| 912 | #endif | ||
| 913 | error ("Unsupported export type"); | ||
| 914 | |||
| 915 | return pgtk_cr_export_frames (frames, surface_type); | ||
| 916 | } | ||
| 917 | |||
| 918 | |||
| 847 | /* Note: see frame.c for template, also where generic functions are impl */ | 919 | /* Note: see frame.c for template, also where generic functions are impl */ |
| 848 | frame_parm_handler pgtk_frame_parm_handlers[] = { | 920 | frame_parm_handler pgtk_frame_parm_handlers[] = { |
| 849 | gui_set_autoraise, /* generic OK */ | 921 | gui_set_autoraise, /* generic OK */ |
| @@ -3673,7 +3745,7 @@ be used as the image of the icon representing the frame. */); | |||
| 3673 | defsubr (&Sx_show_tip); | 3745 | defsubr (&Sx_show_tip); |
| 3674 | defsubr (&Sx_hide_tip); | 3746 | defsubr (&Sx_hide_tip); |
| 3675 | 3747 | ||
| 3676 | // defsubr (&Spgtk_export_frames); | 3748 | defsubr (&Sx_export_frames); |
| 3677 | defsubr (&Spgtk_page_setup_dialog); | 3749 | defsubr (&Spgtk_page_setup_dialog); |
| 3678 | defsubr (&Spgtk_get_page_setup); | 3750 | defsubr (&Spgtk_get_page_setup); |
| 3679 | defsubr (&Spgtk_print_frames_dialog); | 3751 | defsubr (&Spgtk_print_frames_dialog); |
diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 544436e6e44..6d8b1ece877 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c | |||
| @@ -7045,6 +7045,17 @@ pgtk_cr_draw_frame (cairo_t * cr, struct frame *f) | |||
| 7045 | cairo_paint (cr); | 7045 | cairo_paint (cr); |
| 7046 | } | 7046 | } |
| 7047 | 7047 | ||
| 7048 | static cairo_status_t | ||
| 7049 | pgtk_cr_accumulate_data (void *closure, const unsigned char *data, | ||
| 7050 | unsigned int length) | ||
| 7051 | { | ||
| 7052 | Lisp_Object *acc = (Lisp_Object *) closure; | ||
| 7053 | |||
| 7054 | *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc); | ||
| 7055 | |||
| 7056 | return CAIRO_STATUS_SUCCESS; | ||
| 7057 | } | ||
| 7058 | |||
| 7048 | void | 7059 | void |
| 7049 | pgtk_cr_destroy_frame_context (struct frame *f) | 7060 | pgtk_cr_destroy_frame_context (struct frame *f) |
| 7050 | { | 7061 | { |
| @@ -7056,6 +7067,110 @@ pgtk_cr_destroy_frame_context (struct frame *f) | |||
| 7056 | } | 7067 | } |
| 7057 | } | 7068 | } |
| 7058 | 7069 | ||
| 7070 | static void | ||
| 7071 | pgtk_cr_destroy (void *cr) | ||
| 7072 | { | ||
| 7073 | block_input (); | ||
| 7074 | cairo_destroy (cr); | ||
| 7075 | unblock_input (); | ||
| 7076 | } | ||
| 7077 | |||
| 7078 | |||
| 7079 | |||
| 7080 | Lisp_Object | ||
| 7081 | pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type) | ||
| 7082 | { | ||
| 7083 | struct frame *f; | ||
| 7084 | cairo_surface_t *surface; | ||
| 7085 | cairo_t *cr; | ||
| 7086 | int width, height; | ||
| 7087 | void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL; | ||
| 7088 | Lisp_Object acc = Qnil; | ||
| 7089 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 7090 | |||
| 7091 | specbind (Qredisplay_dont_pause, Qt); | ||
| 7092 | redisplay_preserve_echo_area (31); | ||
| 7093 | |||
| 7094 | f = XFRAME (XCAR (frames)); | ||
| 7095 | frames = XCDR (frames); | ||
| 7096 | width = FRAME_PIXEL_WIDTH (f); | ||
| 7097 | height = FRAME_PIXEL_HEIGHT (f); | ||
| 7098 | |||
| 7099 | block_input (); | ||
| 7100 | #ifdef CAIRO_HAS_PDF_SURFACE | ||
| 7101 | if (surface_type == CAIRO_SURFACE_TYPE_PDF) | ||
| 7102 | { | ||
| 7103 | surface = cairo_pdf_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, | ||
| 7104 | width, height); | ||
| 7105 | surface_set_size_func = cairo_pdf_surface_set_size; | ||
| 7106 | } | ||
| 7107 | else | ||
| 7108 | #endif | ||
| 7109 | #ifdef CAIRO_HAS_PNG_FUNCTIONS | ||
| 7110 | if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) | ||
| 7111 | surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); | ||
| 7112 | else | ||
| 7113 | #endif | ||
| 7114 | #ifdef CAIRO_HAS_PS_SURFACE | ||
| 7115 | if (surface_type == CAIRO_SURFACE_TYPE_PS) | ||
| 7116 | { | ||
| 7117 | surface = cairo_ps_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, | ||
| 7118 | width, height); | ||
| 7119 | surface_set_size_func = cairo_ps_surface_set_size; | ||
| 7120 | } | ||
| 7121 | else | ||
| 7122 | #endif | ||
| 7123 | #ifdef CAIRO_HAS_SVG_SURFACE | ||
| 7124 | if (surface_type == CAIRO_SURFACE_TYPE_SVG) | ||
| 7125 | surface = cairo_svg_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, | ||
| 7126 | width, height); | ||
| 7127 | else | ||
| 7128 | #endif | ||
| 7129 | abort (); | ||
| 7130 | |||
| 7131 | cr = cairo_create (surface); | ||
| 7132 | cairo_surface_destroy (surface); | ||
| 7133 | record_unwind_protect_ptr (pgtk_cr_destroy, cr); | ||
| 7134 | |||
| 7135 | while (1) | ||
| 7136 | { | ||
| 7137 | cairo_t *saved_cr = FRAME_CR_CONTEXT (f); | ||
| 7138 | FRAME_CR_CONTEXT (f) = cr; | ||
| 7139 | pgtk_clear_area (f, 0, 0, width, height); | ||
| 7140 | expose_frame (f, 0, 0, width, height); | ||
| 7141 | FRAME_CR_CONTEXT (f) = saved_cr; | ||
| 7142 | |||
| 7143 | if (NILP (frames)) | ||
| 7144 | break; | ||
| 7145 | |||
| 7146 | cairo_surface_show_page (surface); | ||
| 7147 | f = XFRAME (XCAR (frames)); | ||
| 7148 | frames = XCDR (frames); | ||
| 7149 | width = FRAME_PIXEL_WIDTH (f); | ||
| 7150 | height = FRAME_PIXEL_HEIGHT (f); | ||
| 7151 | if (surface_set_size_func) | ||
| 7152 | (*surface_set_size_func) (surface, width, height); | ||
| 7153 | |||
| 7154 | unblock_input (); | ||
| 7155 | maybe_quit (); | ||
| 7156 | block_input (); | ||
| 7157 | } | ||
| 7158 | |||
| 7159 | #ifdef CAIRO_HAS_PNG_FUNCTIONS | ||
| 7160 | if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) | ||
| 7161 | { | ||
| 7162 | cairo_surface_flush (surface); | ||
| 7163 | cairo_surface_write_to_png_stream (surface, pgtk_cr_accumulate_data, &acc); | ||
| 7164 | } | ||
| 7165 | #endif | ||
| 7166 | unblock_input (); | ||
| 7167 | |||
| 7168 | unbind_to (count, Qnil); | ||
| 7169 | |||
| 7170 | return CALLN (Fapply, intern ("concat"), Fnreverse (acc)); | ||
| 7171 | } | ||
| 7172 | |||
| 7173 | |||
| 7059 | void | 7174 | void |
| 7060 | init_pgtkterm (void) | 7175 | init_pgtkterm (void) |
| 7061 | { | 7176 | { |
diff --git a/src/pgtkterm.h b/src/pgtkterm.h index f4d6ee035f1..cff16332921 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h | |||
| @@ -28,6 +28,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | 28 | ||
| 29 | #include <gtk/gtk.h> | 29 | #include <gtk/gtk.h> |
| 30 | 30 | ||
| 31 | #ifdef CAIRO_HAS_PDF_SURFACE | ||
| 32 | #include <cairo-pdf.h> | ||
| 33 | #endif | ||
| 34 | #ifdef CAIRO_HAS_PS_SURFACE | ||
| 35 | #include <cairo-ps.h> | ||
| 36 | #endif | ||
| 37 | #ifdef CAIRO_HAS_SVG_SURFACE | ||
| 38 | #include <cairo-svg.h> | ||
| 39 | #endif | ||
| 40 | |||
| 31 | // #define PGTK_DEBUG 1 | 41 | // #define PGTK_DEBUG 1 |
| 32 | 42 | ||
| 33 | #ifdef PGTK_DEBUG | 43 | #ifdef PGTK_DEBUG |
| @@ -574,6 +584,7 @@ extern void pgtk_set_cr_source_with_color (struct frame *f, | |||
| 574 | unsigned long color); | 584 | unsigned long color); |
| 575 | extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); | 585 | extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); |
| 576 | extern void pgtk_cr_destroy_frame_context (struct frame *f); | 586 | extern void pgtk_cr_destroy_frame_context (struct frame *f); |
| 587 | extern Lisp_Object pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type); | ||
| 577 | 588 | ||
| 578 | /* Defined in pgtkmenu.c */ | 589 | /* Defined in pgtkmenu.c */ |
| 579 | extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, | 590 | extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, |