aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeff Walsh2020-08-27 22:05:15 +1000
committerJeff Walsh2020-11-24 12:24:40 +1100
commite75ce0302d4c907c8ff56fb15fc7dd12b48e7370 (patch)
treeb86e587fc94a6e8f931b64bdcc0830f361c9082b /src
parent9704e23f4c2cd56bc8091e2024c7b972a3254bb7 (diff)
downloademacs-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.c74
-rw-r--r--src/pgtkterm.c115
-rw-r--r--src/pgtkterm.h11
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
853DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
854 doc: /* Return image data of FRAMES in TYPE format.
855FRAMES should be nil (the selected frame), a frame, or a list of
856frames (each of which corresponds to one page). Each frame should be
857visible. Optional arg TYPE should be either `pdf' (default), `png',
858`postscript', or `svg'. Supported types are determined by the
859compile-time configuration of cairo.
860
861Note: Text drawn with the `x' font backend is shown with hollow boxes
862unless 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 */
848frame_parm_handler pgtk_frame_parm_handlers[] = { 920frame_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
7048static cairo_status_t
7049pgtk_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
7048void 7059void
7049pgtk_cr_destroy_frame_context (struct frame *f) 7060pgtk_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
7070static void
7071pgtk_cr_destroy (void *cr)
7072{
7073 block_input ();
7074 cairo_destroy (cr);
7075 unblock_input ();
7076}
7077
7078
7079
7080Lisp_Object
7081pgtk_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
7059void 7174void
7060init_pgtkterm (void) 7175init_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);
575extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); 585extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f);
576extern void pgtk_cr_destroy_frame_context (struct frame *f); 586extern void pgtk_cr_destroy_frame_context (struct frame *f);
587extern 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 */
579extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, 590extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header,