From 0eb0908d7f5bbf1b65e502095a3c1545751f17fa Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sat, 13 Apr 2019 10:05:06 +0200 Subject: Restore printing --- meson.build | 1 + src-old/print.c | 314 ------------------------------------------------- src-old/print.h | 32 ----- src/narrative_window.c | 6 +- src/print.c | 275 +++++++++++++++++++++++++++++++++++++++++++ src/print.h | 34 ++++++ 6 files changed, 313 insertions(+), 349 deletions(-) delete mode 100644 src-old/print.c delete mode 100644 src-old/print.h create mode 100644 src/print.c create mode 100644 src/print.h diff --git a/meson.build b/meson.build index 07626cc..0d6e70b 100644 --- a/meson.build +++ b/meson.build @@ -113,6 +113,7 @@ executable('colloquium', 'src/pr_clock.c', 'src/slide_window.c', 'src/testcard.c', + 'src/print.c', # 'src/stylesheet_editor.c', ], gresources, diff --git a/src-old/print.c b/src-old/print.c deleted file mode 100644 index 43c967e..0000000 --- a/src-old/print.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * print.c - * - * Copyright © 2016-2018 Thomas White - * - * This file is part of Colloquium. - * - * Colloquium 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. - * - * This program 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 this program. If not, see . - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "presentation.h" -#include "narrative_window.h" -#include "render.h" -#include "utils.h" - - -static GtkPrintSettings *print_settings = NULL; - -struct print_stuff -{ - struct presentation *p; - - /* Printing config */ - GtkWidget *combo; - int slides_only; - - /* When printing slides only */ - SCBlock *slide; - - /* When printing narrative */ - int nar_line; - struct frame *top; - int start_paras[256]; - int slide_number; -}; - - -static void print_widget_apply(GtkPrintOperation *op, GtkWidget *widget, - void *vp) -{ - const char *id; - struct print_stuff *ps = vp; - - id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ps->combo)); - if ( strcmp(id, "slides") == 0 ) { - ps->slides_only = 1; - } else { - ps->slides_only = 0; - } -} - - -static GObject *print_widget(GtkPrintOperation *op, void *vp) -{ - GtkWidget *vbox; - GtkWidget *cbox; - struct print_stuff *ps = vp; - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); - - /* What do you want to print? */ - cbox = gtk_combo_box_text_new(); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(cbox), "slides", - _("Print the slides only")); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(cbox), "narrative", - _("Print the narrative")); - gtk_box_pack_start(GTK_BOX(vbox), cbox, FALSE, FALSE, 10); - gtk_combo_box_set_active(GTK_COMBO_BOX(cbox), 1); - ps->combo = cbox; - - gtk_widget_show_all(vbox); - return G_OBJECT(vbox); - -} - - -static void print_slide_only(GtkPrintOperation *op, GtkPrintContext *ctx, - struct print_stuff *ps, int page) -{ - cairo_t *cr; - PangoContext *pc; - double w, h; - struct frame *top; - const double sw = ps->p->slide_width; - const double sh = ps->p->slide_height; - double slide_width, slide_height; - - cr = gtk_print_context_get_cairo_context(ctx); - pc = gtk_print_context_create_pango_context(ctx); - w = gtk_print_context_get_width(ctx); - h = gtk_print_context_get_height(ctx); - - cairo_rectangle(cr, 0.0, 0.0, w, h); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_fill(cr); - - if ( sw/sh > w/h ) { - /* Slide is too wide. Letterboxing top/bottom */ - slide_width = w; - slide_height = w * sh/sw; - } else { - /* Letterboxing at sides */ - slide_width = h * sw/sh; - slide_height = h; - } - - printf("%f x %f ---> %f x %f\n", w, h, slide_width, slide_height); - - top = interp_and_shape(ps->slide, ps->p->stylesheet, NULL, - ps->p->is, page+1, pc, sw, sh, ps->p->lang); - - recursive_wrap(top, pc); - - cairo_scale(cr, slide_width/sw, slide_width/sw); - - recursive_draw(top, cr, ps->p->is, - 0.0, ps->p->slide_height); - - ps->slide = next_slide(ps->p, ps->slide); -} - - -static int print_create_thumbnail(SCInterpreter *scin, SCBlock *bl, - double *w, double *h, void **bvp, void *vp) -{ - struct print_stuff *ps = vp; - struct presentation *p = ps->p; - SCBlock *b; - - *w = 270.0*(p->slide_width / p->slide_height); - *h = 270.0; - b = bl; - - *bvp = b; - - return 1; -} - - -static cairo_surface_t *print_render_thumbnail(int w, int h, void *bvp, void *vp) -{ - struct print_stuff *ps = vp; - struct presentation *p = ps->p; - SCBlock *scblocks = bvp; - cairo_surface_t *surf; - struct frame *top; - - surf = render_sc(scblocks, w, h, p->slide_width, p->slide_height, - p->stylesheet, NULL, p->is, ps->slide_number++, - &top, p->lang); - frame_free(top); - - return surf; -} - - -static void begin_narrative_print(GtkPrintOperation *op, GtkPrintContext *ctx, - struct print_stuff *ps) -{ - SCCallbackList *cbl; - PangoContext *pc; - int i, n_pages; - double h, page_height; - SCBlock *dummy_top; - - cbl = sc_callback_list_new(); - ps->slide_number = 1; - sc_callback_list_add_callback(cbl, "slide", print_create_thumbnail, - print_render_thumbnail, NULL, ps); - - pc = gtk_print_context_create_pango_context(ctx); - - dummy_top = sc_block_new_parent(ps->p->scblocks, "presentation"); - ps->top = interp_and_shape(dummy_top, ps->p->stylesheet, cbl, - ps->p->is, 0, pc, - gtk_print_context_get_width(ctx), - gtk_print_context_get_height(ctx), - ps->p->lang); - recursive_wrap(ps->top, pc); - - /* Count pages */ - page_height = gtk_print_context_get_height(ctx); - h = 0.0; - n_pages = 1; - ps->start_paras[0] = 0; - for ( i=0; itop->n_paras; i++ ) { - if ( h + paragraph_height(ps->top->paras[i]) > page_height ) { - /* Paragraph does not fit on page */ - ps->start_paras[n_pages] = i; - n_pages++; - h = 0.0; - } - h += paragraph_height(ps->top->paras[i]); - } - gtk_print_operation_set_n_pages(op, n_pages); - g_object_unref(pc); -} - - -static void print_narrative(GtkPrintOperation *op, GtkPrintContext *ctx, - struct print_stuff *ps, gint page) -{ - int i; - double h, page_height; - cairo_t *cr; - - page_height = gtk_print_context_get_height(ctx); - cr = gtk_print_context_get_cairo_context(ctx); - - h = 0.0; - for ( i=ps->start_paras[page]; itop->n_paras; i++ ) { - - /* Will this paragraph fit? */ - h += paragraph_height(ps->top->paras[i]); - if ( h > page_height ) return; - - cairo_save(cr); - render_paragraph(cr, ps->top->paras[i], ps->p->is); - cairo_restore(cr); - - cairo_translate(cr, 0.0, paragraph_height(ps->top->paras[i])); - - } - - -} - - - -static void print_begin(GtkPrintOperation *op, GtkPrintContext *ctx, void *vp) -{ - struct print_stuff *ps = vp; - - if ( ps->slides_only ) { - gtk_print_operation_set_n_pages(op, num_slides(ps->p)); - ps->slide = first_slide(ps->p); - } else { - begin_narrative_print(op, ctx, ps); - } -} - - -static void print_draw(GtkPrintOperation *op, GtkPrintContext *ctx, gint page, - void *vp) -{ - struct print_stuff *ps = vp; - if ( ps->slides_only ) { - print_slide_only(op, ctx, ps, page); - } else { - print_narrative(op, ctx, ps, page); - } -} - - -void run_printing(struct presentation *p, GtkWidget *parent) -{ - GtkPrintOperation *print; - GtkPrintOperationResult res; - struct print_stuff *ps; - - ps = malloc(sizeof(struct print_stuff)); - if ( ps == NULL ) return; - ps->p = p; - ps->nar_line = 0; - - print = gtk_print_operation_new(); - if ( print_settings != NULL ) { - gtk_print_operation_set_print_settings(print, print_settings); - } - - g_signal_connect(print, "create-custom-widget", - G_CALLBACK(print_widget), ps); - g_signal_connect(print, "custom-widget-apply", - G_CALLBACK(print_widget_apply), ps); - g_signal_connect(print, "begin_print", G_CALLBACK(print_begin), ps); - g_signal_connect(print, "draw_page", G_CALLBACK(print_draw), ps); - - res = gtk_print_operation_run(print, - GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, - GTK_WINDOW(parent), 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); -} - diff --git a/src-old/print.h b/src-old/print.h deleted file mode 100644 index 265b7c1..0000000 --- a/src-old/print.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * print.h - * - * Copyright © 2016-2018 Thomas White - * - * This file is part of Colloquium. - * - * Colloquium 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. - * - * This program 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 this program. If not, see . - * - */ - -#ifndef PRINT_H -#define PRINT_H - -#ifdef HAVE_CONFIG_H -#include -#endif - -extern void run_printing(struct presentation *p, GtkWidget *parent); - -#endif /* PRINT_H */ diff --git a/src/narrative_window.c b/src/narrative_window.c index 8987f18..70838c7 100644 --- a/src/narrative_window.c +++ b/src/narrative_window.c @@ -43,7 +43,7 @@ #include "testcard.h" #include "pr_clock.h" #include "slideshow.h" -//#include "print.h" +#include "print.h" //#include "stylesheet_editor.h" struct _narrative_window @@ -460,8 +460,8 @@ static gint export_pdf_response_sig(GtkWidget *d, gint response, static void print_sig(GSimpleAction *action, GVariant *parameter, gpointer vp) { - //NarrativeWindow *nw = vp; -// run_printing(nw->n, nw->window); + NarrativeWindow *nw = vp; + run_printing(nw->n, nw->window); } diff --git a/src/print.c b/src/print.c new file mode 100644 index 0000000..ca89cc9 --- /dev/null +++ b/src/print.c @@ -0,0 +1,275 @@ +/* + * print.c + * + * Copyright © 2016-2019 Thomas White + * + * This file is part of Colloquium. + * + * Colloquium 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. + * + * This program 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 this program. If not, see . + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#define _(x) gettext(x) + +#include "narrative.h" +#include "narrative_window.h" +#include "slide_render_cairo.h" +#include "narrative_render_cairo.h" + + +static GtkPrintSettings *print_settings = NULL; + +struct print_stuff +{ + Narrative *n; + + /* Printing config */ + GtkWidget *combo; + int slides_only; + + /* When printing slides only */ + Slide *slide; + + /* When printing narrative */ + int nar_line; + int start_paras[256]; + int slide_number; +}; + + +static void print_widget_apply(GtkPrintOperation *op, GtkWidget *widget, + void *vp) +{ + const char *id; + struct print_stuff *ps = vp; + + id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ps->combo)); + if ( strcmp(id, "slides") == 0 ) { + ps->slides_only = 1; + } else { + ps->slides_only = 0; + } +} + + +static GObject *print_widget(GtkPrintOperation *op, void *vp) +{ + GtkWidget *vbox; + GtkWidget *cbox; + struct print_stuff *ps = vp; + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 10); + + /* What do you want to print? */ + cbox = gtk_combo_box_text_new(); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(cbox), "slides", + _("Print the slides only")); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(cbox), "narrative", + _("Print the narrative")); + gtk_box_pack_start(GTK_BOX(vbox), cbox, FALSE, FALSE, 10); + gtk_combo_box_set_active(GTK_COMBO_BOX(cbox), 1); + ps->combo = cbox; + + gtk_widget_show_all(vbox); + return G_OBJECT(vbox); + +} + + +static void print_slide_only(GtkPrintOperation *op, GtkPrintContext *ctx, + struct print_stuff *ps, int page) +{ + cairo_t *cr; + PangoContext *pc; + double w, h; + double sw, sh; + double slide_width, slide_height; + struct slide_pos sel; + int slidenum; + + cr = gtk_print_context_get_cairo_context(ctx); + pc = gtk_print_context_create_pango_context(ctx); + w = gtk_print_context_get_width(ctx); + h = gtk_print_context_get_height(ctx); + + slide_get_logical_size(ps->slide, narrative_get_stylesheet(ps->n), + &sw, &sh); + + cairo_rectangle(cr, 0.0, 0.0, w, h); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_fill(cr); + + if ( sw/sh > w/h ) { + /* Slide is too wide. Letterboxing top/bottom */ + slide_width = w; + slide_height = w * sh/sw; + } else { + /* Letterboxing at sides */ + slide_width = h * sw/sh; + slide_height = h; + } + + printf("%f x %f ---> %f x %f\n", w, h, slide_width, slide_height); + + cairo_scale(cr, slide_width/sw, slide_width/sw); + + sel.para = 0; sel.pos = 0; sel.trail = 0; + slidenum = narrative_get_slide_number_for_slide(ps->n, ps->slide); + slide_render_cairo(ps->slide, cr, narrative_get_imagestore(ps->n), + narrative_get_stylesheet(ps->n), slidenum, + pango_language_get_default(), pc, + NULL, sel, sel); + + ps->slide = narrative_get_slide_by_number(ps->n, slidenum+1); +} + + +static void begin_narrative_print(GtkPrintOperation *op, GtkPrintContext *ctx, + struct print_stuff *ps) +{ + PangoContext *pc; + int i, n_pages; + double h, page_height; + struct edit_pos sel; + + ps->slide_number = 1; + + pc = gtk_print_context_create_pango_context(ctx); + + sel.para = 0; sel.pos = 0; sel.trail = 0; + narrative_wrap_range(ps->n, narrative_get_stylesheet(ps->n), + pango_language_get_default(), pc, + gtk_print_context_get_width(ctx), + narrative_get_imagestore(ps->n), + 0, narrative_get_num_items(ps->n), sel, sel); + + /* Count pages */ + page_height = gtk_print_context_get_height(ctx); + h = 0.0; + n_pages = 1; + ps->start_paras[0] = 0; + for ( i=0; in); i++ ) { + if ( h + narrative_item_get_height(ps->n, i) > page_height ) { + /* Paragraph does not fit on page */ + ps->start_paras[n_pages] = i; + n_pages++; + h = 0.0; + } + h += narrative_item_get_height(ps->n, i); + } + gtk_print_operation_set_n_pages(op, n_pages); + g_object_unref(pc); +} + + +static void print_narrative(GtkPrintOperation *op, GtkPrintContext *ctx, + struct print_stuff *ps, gint page) +{ + int i; + double h, page_height; + cairo_t *cr; + + page_height = gtk_print_context_get_height(ctx); + cr = gtk_print_context_get_cairo_context(ctx); + + h = 0.0; + for ( i=ps->start_paras[page]; in); i++ ) { + + /* Will this paragraph fit? */ + h += narrative_item_get_height(ps->n, i); + if ( h > page_height ) return; + + cairo_save(cr); + narrative_render_item_cairo(ps->n, cr, i); + cairo_restore(cr); + + cairo_translate(cr, 0.0, narrative_item_get_height(ps->n, i)); + + } +} + + +static void print_begin(GtkPrintOperation *op, GtkPrintContext *ctx, void *vp) +{ + struct print_stuff *ps = vp; + + if ( ps->slides_only ) { + gtk_print_operation_set_n_pages(op, narrative_get_num_slides(ps->n)); + ps->slide = narrative_get_slide_by_number(ps->n, 0); + } else { + begin_narrative_print(op, ctx, ps); + } +} + + +static void print_draw(GtkPrintOperation *op, GtkPrintContext *ctx, gint page, + void *vp) +{ + struct print_stuff *ps = vp; + if ( ps->slides_only ) { + print_slide_only(op, ctx, ps, page); + } else { + print_narrative(op, ctx, ps, page); + } +} + + +void run_printing(Narrative *n, GtkWidget *parent) +{ + GtkPrintOperation *print; + GtkPrintOperationResult res; + struct print_stuff *ps; + + ps = malloc(sizeof(struct print_stuff)); + if ( ps == NULL ) return; + ps->n = n; + ps->nar_line = 0; + + print = gtk_print_operation_new(); + if ( print_settings != NULL ) { + gtk_print_operation_set_print_settings(print, print_settings); + } + + g_signal_connect(print, "create-custom-widget", + G_CALLBACK(print_widget), ps); + g_signal_connect(print, "custom-widget-apply", + G_CALLBACK(print_widget_apply), ps); + g_signal_connect(print, "begin_print", G_CALLBACK(print_begin), ps); + g_signal_connect(print, "draw_page", G_CALLBACK(print_draw), ps); + + res = gtk_print_operation_run(print, + GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, + GTK_WINDOW(parent), 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); +} + diff --git a/src/print.h b/src/print.h new file mode 100644 index 0000000..b4f688b --- /dev/null +++ b/src/print.h @@ -0,0 +1,34 @@ +/* + * print.h + * + * Copyright © 2016-2019 Thomas White + * + * This file is part of Colloquium. + * + * Colloquium 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. + * + * This program 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 this program. If not, see . + * + */ + +#ifndef PRINT_H +#define PRINT_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +extern void run_printing(Narrative *n, GtkWidget *parent); + +#endif /* PRINT_H */ -- cgit v1.2.3