From: Ben Pfaff Date: Mon, 14 Dec 2020 07:43:03 +0000 (-0800) Subject: printing works; font sizes are weird X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31a584844eb37e7f906f1f28767cb54aca4a27b5;p=pspp printing works; font sizes are weird --- diff --git a/src/output/cairo-fsm.c b/src/output/cairo-fsm.c index 5d1b63e4f1..54b65dd9c0 100644 --- a/src/output/cairo-fsm.c +++ b/src/output/cairo-fsm.c @@ -52,7 +52,7 @@ /* This file uses TABLE_HORZ and TABLE_VERT enough to warrant abbreviating. */ #define H TABLE_HORZ #define V TABLE_VERT - + struct xr_fsm_style * xr_fsm_style_ref (const struct xr_fsm_style *style_) { @@ -63,6 +63,24 @@ xr_fsm_style_ref (const struct xr_fsm_style *style_) return style; } +struct xr_fsm_style * +xr_fsm_style_unshare (struct xr_fsm_style *old) +{ + assert (old->ref_cnt > 0); + if (old->ref_cnt == 1) + return old; + + xr_fsm_style_unref (old); + + struct xr_fsm_style *new = xmemdup (old, sizeof *old); + new->ref_cnt = 1; + for (int i = 0; i < XR_N_FONTS; i++) + if (old->fonts[i]) + new->fonts[i] = pango_font_description_copy (old->fonts[i]); + + return new; +} + void xr_fsm_style_unref (struct xr_fsm_style *style) { @@ -608,7 +626,7 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell, if (font_style->typeface) desc = parse_font ( font_style->typeface, - font_style->size ? font_style->size * 1000 * xr->style->font_scale : 10000, + (font_style->size ? font_style->size * 1000 : 10000) * xr->style->font_scale, font_style->bold, font_style->italic); if (!desc) desc = xr->style->fonts[font_type]; @@ -1094,7 +1112,6 @@ xr_fsm_create (const struct output_item *item_, .ops = &xrr_render_ops, .aux = fsm, .size = { [H] = style->size[H], [V] = style->size[V] }, - /* XXX font_size */ .line_widths = xr_line_widths, .min_break = { [H] = style->min_break[H], [V] = style->min_break[V] }, .supports_margins = true, diff --git a/src/output/cairo-fsm.h b/src/output/cairo-fsm.h index f89acbe537..b61f099035 100644 --- a/src/output/cairo-fsm.h +++ b/src/output/cairo-fsm.h @@ -43,7 +43,7 @@ struct xr_fsm_style { int ref_cnt; - int size[TABLE_N_AXES]; /* Page size. */ + int size[TABLE_N_AXES]; /* Page size. */ int min_break[TABLE_N_AXES]; /* Minimum cell size to allow breaking. */ PangoFontDescription *fonts[XR_N_FONTS]; struct cell_color fg; @@ -52,6 +52,7 @@ struct xr_fsm_style double font_scale; }; struct xr_fsm_style *xr_fsm_style_ref (const struct xr_fsm_style *); +struct xr_fsm_style *xr_fsm_style_unshare (struct xr_fsm_style *); void xr_fsm_style_unref (struct xr_fsm_style *); bool xr_fsm_style_equals (const struct xr_fsm_style *, const struct xr_fsm_style *); diff --git a/src/output/cairo-pager.c b/src/output/cairo-pager.c index 8a0f948cc8..2d287499a2 100644 --- a/src/output/cairo-pager.c +++ b/src/output/cairo-pager.c @@ -55,8 +55,6 @@ xr_page_style_unshare (struct xr_page_style *old) new->ref_cnt = 1; for (int i = 0; i < 2; i++) page_heading_copy (&new->headings[i], &old->headings[i]); - if (old->font) - new->font = pango_font_description_copy (old->font); return new; } @@ -71,53 +69,37 @@ xr_page_style_unref (struct xr_page_style *ps) { for (int i = 0; i < 2; i++) page_heading_uninit (&ps->headings[i]); - if (ps->font) - pango_font_description_free (ps->font); free (ps); } } } -static bool -pfd_equals (const PangoFontDescription *a, - const PangoFontDescription *b) -{ - return a && b ? pango_font_description_equal (a, b) : !a && !b; -} - bool xr_page_style_equals (const struct xr_page_style *a, const struct xr_page_style *b) { for (int i = 0; i < TABLE_N_AXES; i++) - { - if (a->size[i] != b->size[i]) + for (int j = 0; j < 2; j++) + if (a->margins[i][j] != b->margins[i][j]) return false; - for (int j = 0; j < 2; j++) - if (a->margins[i][j] != b->margins[i][j]) - return false; - } - for (int i = 0; i < 2; i++) if (!page_heading_equals (&a->headings[i], &b->headings[i])) return false; - return (pfd_equals (a->font, b->font) - && a->font_scale == b->font_scale - && a->initial_page_number == b->initial_page_number + return (a->initial_page_number == b->initial_page_number && a->object_spacing == b->object_spacing); } struct xr_pager { struct xr_page_style *page_style; + struct xr_fsm_style *fsm_style; int page_index; int heading_heights[2]; /* Current output item. */ struct xr_fsm *fsm; - struct xr_fsm_style *fsm_style; struct output_item *item; /* Current output page. */ @@ -200,7 +182,9 @@ xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font, } static void -xr_measure_headings (const struct xr_page_style *ps, int heading_heights[2]) +xr_measure_headings (const struct xr_page_style *ps, + const struct xr_fsm_style *fs, + int heading_heights[2]) { cairo_surface_t *surface = cairo_recording_surface_create ( CAIRO_CONTENT_COLOR, NULL); @@ -208,8 +192,9 @@ xr_measure_headings (const struct xr_page_style *ps, int heading_heights[2]) for (int i = 0; i < 2; i++) { int *h = &heading_heights[i]; - *h = xr_render_page_heading (cairo, ps->font, &ps->headings[i], -1, - ps->size[H], false, 0); + *h = xr_render_page_heading (cairo, fs->fonts[XR_FONT_PROPORTIONAL], + &ps->headings[i], -1, fs->size[H], false, + 0); if (*h) *h += ps->object_spacing; } @@ -218,24 +203,28 @@ xr_measure_headings (const struct xr_page_style *ps, int heading_heights[2]) } struct xr_pager * -xr_pager_create (const struct xr_page_style *ps_) +xr_pager_create (const struct xr_page_style *ps_, + const struct xr_fsm_style *fs_) { + printf ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); struct xr_page_style *ps = xr_page_style_ref (ps_); + struct xr_fsm_style *fs = xr_fsm_style_ref (fs_); int heading_heights[2]; - xr_measure_headings (ps, heading_heights); + xr_measure_headings (ps, fs, heading_heights); int total = heading_heights[0] + heading_heights[1]; - if (total > 0 && total < ps->size[V]) + if (total > 0 && total < fs->size[V]) { + fs = xr_fsm_style_unshare (fs); ps = xr_page_style_unshare (ps); for (int i = 0; i < 2; i++) ps->margins[V][i] += heading_heights[i]; - ps->size[V] -= total; + fs->size[V] -= total; } struct xr_pager *p = xmalloc (sizeof *p); - *p = (struct xr_pager) { .page_style = ps }; + *p = (struct xr_pager) { .page_style = ps, .fsm_style = fs }; return p; } @@ -244,13 +233,18 @@ xr_pager_destroy (struct xr_pager *p) { if (p) { - xr_fsm_destroy (p->fsm); + printf (">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + xr_page_style_unref (p->page_style); xr_fsm_style_unref (p->fsm_style); + + xr_fsm_destroy (p->fsm); output_item_unref (p->item); - xr_page_style_unref (p->page_style); if (p->cr) - cairo_destroy (p->cr); + { + cairo_restore (p->cr); + cairo_destroy (p->cr); + } free (p); } } @@ -262,12 +256,11 @@ xr_pager_has_item (const struct xr_pager *p) } void -xr_pager_add_item (struct xr_pager *p, const struct xr_fsm_style *fsm_style, - const struct output_item *item) +xr_pager_add_item (struct xr_pager *p, const struct output_item *item) { + printf ("add_item\n"); assert (!p->item); p->item = output_item_ref (item); - p->fsm_style = xr_fsm_style_ref (fsm_style); xr_pager_run (p); } @@ -280,10 +273,13 @@ xr_pager_has_page (const struct xr_pager *p) void xr_pager_add_page (struct xr_pager *p, cairo_t *cr) { + printf ("add_page\n"); assert (!p->cr); + cairo_save (cr); p->cr = cr; p->y = 0; + const struct xr_fsm_style *fs = p->fsm_style; const struct xr_page_style *ps = p->page_style; const struct cell_color *bg = &ps->bg; if (bg->alpha) @@ -291,7 +287,7 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) cairo_save (cr); cairo_set_source_rgba (cr, bg->r / 255.0, bg->g / 255.0, bg->b / 255.0, bg->alpha / 255.0); - cairo_rectangle (cr, 0, 0, ps->size[H], ps->size[V]); + cairo_rectangle (cr, 0, 0, fs->size[H], fs->size[V]); cairo_fill (cr); cairo_restore (cr); } @@ -299,15 +295,16 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) xr_to_pt (ps->margins[H][0]), xr_to_pt (ps->margins[V][0])); + const PangoFontDescription *font = fs->fonts[XR_FONT_PROPORTIONAL]; int page_number = p->page_index++ + ps->initial_page_number; if (p->heading_heights[0]) - xr_render_page_heading (cr, ps->font, &ps->headings[0], page_number, - ps->size[H], true, -p->heading_heights[0]); + xr_render_page_heading (cr, font, &ps->headings[0], page_number, + fs->size[H], true, -p->heading_heights[0]); if (p->heading_heights[1]) - xr_render_page_heading (cr, ps->font, &ps->headings[1], page_number, - ps->size[H], true, - ps->size[V] + ps->object_spacing); + xr_render_page_heading (cr, font, &ps->headings[1], page_number, + fs->size[H], true, + fs->size[V] + ps->object_spacing); xr_pager_run (p); } @@ -315,10 +312,14 @@ xr_pager_add_page (struct xr_pager *p, cairo_t *cr) bool xr_pager_needs_new_page (struct xr_pager *p) { - if (p->item && p->y >= p->page_style->size[V]) + if (p->item && (!p->cr || p->y >= p->fsm_style->size[V])) { - cairo_destroy (p->cr); - p->cr = NULL; + if (p->cr) + { + cairo_restore (p->cr); + cairo_destroy (p->cr); + p->cr = NULL; + } return true; } else @@ -328,16 +329,16 @@ xr_pager_needs_new_page (struct xr_pager *p) static void xr_pager_run (struct xr_pager *p) { - if (p->item && p->cr && p->y < p->page_style->size[V]) + printf ("run:\n"); + if (p->item && p->cr && p->y < p->fsm_style->size[V]) { if (!p->fsm) { - /* XXX fsm_style needs to account for heading_heights */ + printf ("\tcreate fsm\n"); p->fsm = xr_fsm_create (p->item, p->fsm_style, p->cr); if (!p->fsm) { - xr_fsm_style_unref (p->fsm_style); - p->fsm_style = NULL; + printf ("\t(was null)\n"); output_item_unref (p->item); p->item = NULL; @@ -347,28 +348,34 @@ xr_pager_run (struct xr_pager *p) for (;;) { + printf ("\tdraw slice\n"); int spacing = p->page_style->object_spacing; int chunk = xr_fsm_draw_slice (p->fsm, p->cr, - p->page_style->size[V] - p->y); + p->fsm_style->size[V] - p->y); p->y += chunk + spacing; cairo_translate (p->cr, 0, xr_to_pt (chunk + spacing)); if (xr_fsm_is_empty (p->fsm)) { + printf ("\tfinished object\n"); xr_fsm_destroy (p->fsm); p->fsm = NULL; - xr_fsm_style_unref (p->fsm_style); - p->fsm_style = NULL; output_item_unref (p->item); p->item = NULL; return; } else if (!chunk) { + printf ("\tobject doesn't fit on page\n"); assert (p->y > 0); p->y = INT_MAX; return; } + printf ("\tneed to draw another slice\n"); } } + if (!p->item) + printf ("\tno item\n"); + if (!p->cr) + printf ("\tno page\n"); } diff --git a/src/output/cairo-pager.h b/src/output/cairo-pager.h index b0cdfdf914..ab843ee30e 100644 --- a/src/output/cairo-pager.h +++ b/src/output/cairo-pager.h @@ -33,14 +33,11 @@ struct xr_page_style { int ref_cnt; - int size[TABLE_N_AXES]; /* Page size minus margins. */ int margins[TABLE_N_AXES][2]; /* Margins. */ struct page_heading headings[2]; /* Top and bottom headings. */ - PangoFontDescription *font; struct cell_color bg; /* Background color. */ - double font_scale; int initial_page_number; int object_spacing; }; @@ -52,9 +49,10 @@ bool xr_page_style_equals (const struct xr_page_style *, struct xr_page_style *xr_page_style_default (void); static inline int -xr_page_style_paper_size (const struct xr_page_style *ps, enum table_axis a) +xr_page_style_paper_size (const struct xr_page_style *ps, + const struct xr_fsm_style *fs, enum table_axis a) { - return ps->size[a] + ps->margins[a][0] + ps->margins[a][1]; + return fs->size[a] + ps->margins[a][0] + ps->margins[a][1]; } struct xr_pager *xr_pager_create (const struct xr_page_style *, @@ -62,8 +60,7 @@ struct xr_pager *xr_pager_create (const struct xr_page_style *, void xr_pager_destroy (struct xr_pager *); bool xr_pager_has_item (const struct xr_pager *); -void xr_pager_add_item (struct xr_pager *, const struct xr_fsm_style *, - const struct output_item *); +void xr_pager_add_item (struct xr_pager *, const struct output_item *); bool xr_pager_has_page (const struct xr_pager *); void xr_pager_add_page (struct xr_pager *, cairo_t *); diff --git a/src/output/cairo.c b/src/output/cairo.c index 1673889713..a85054ebcc 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -238,16 +238,12 @@ xr_allocate (const char *name, int device_type, struct string_map *o, *xr->page_style = (struct xr_page_style) { .ref_cnt = 1, - .size = { [H] = size[H], [V] = size[V] }, .margins = { [H] = { margins[H][0], margins[H][1], }, [V] = { margins[V][0], margins[V][1], }, }, - .font = pango_font_description_copy (proportional_font), - .bg = bg, - .font_scale = font_scale, .initial_page_number = 1, .object_spacing = object_spacing, }; @@ -279,7 +275,8 @@ xr_create (struct file_handle *fh, enum settings_output_devices device_type, double paper[TABLE_N_AXES]; for (int a = 0; a < TABLE_N_AXES; a++) - paper[a] = xr_to_pt (xr_page_style_paper_size (xr->page_style, a)); + paper[a] = xr_to_pt (xr_page_style_paper_size (xr->page_style, + xr->fsm_style, a)); if (file_type == XR_PDF) xr->surface = cairo_pdf_surface_create (file_name, paper[H], paper[V]); else if (file_type == XR_PS) @@ -374,19 +371,12 @@ xr_update_page_setup (struct output_driver *driver, *page_style = (struct xr_page_style) { .ref_cnt = 1, - .size = { - [H] = (ps->paper[h] - ps->margins[h][0] - ps->margins[h][1]) * scale, - [V] = (ps->paper[v] - ps->margins[v][0] - ps->margins[v][1]) * scale, - }, .margins = { [H] = { ps->margins[h][0] * scale, ps->margins[h][1] * scale }, [V] = { ps->margins[v][0] * scale, ps->margins[v][1] * scale }, }, - .font = pango_font_description_copy (xr->page_style->font), - .bg = xr->page_style->bg, - .font_scale = xr->page_style->font_scale, .initial_page_number = ps->initial_page_number, .object_spacing = ps->object_spacing * 72 * XR_POINT, }; @@ -412,11 +402,11 @@ xr_submit (struct output_driver *driver, const struct output_item *output_item) if (!xr->pager) { - xr->pager = xr_pager_create (xr->page_style); + xr->pager = xr_pager_create (xr->page_style, xr->fsm_style); xr_pager_add_page (xr->pager, cairo_create (xr->surface)); } - xr_pager_add_item (xr->pager, xr->fsm_style, output_item); + xr_pager_add_item (xr->pager, output_item); while (xr_pager_needs_new_page (xr->pager)) { cairo_surface_show_page (xr->surface); diff --git a/src/ui/gui/psppire-output-view.c b/src/ui/gui/psppire-output-view.c index 38dbf1a060..ff19f64bab 100644 --- a/src/ui/gui/psppire-output-view.c +++ b/src/ui/gui/psppire-output-view.c @@ -985,21 +985,9 @@ static cairo_t * get_cairo_context_from_print_context (GtkPrintContext *context) { cairo_t *cr = gtk_print_context_get_cairo_context (context); - - /* - For all platforms except windows, gtk_print_context_get_dpi_[xy] returns 72. - Windows returns 600. - */ - double xres = gtk_print_context_get_dpi_x (context); - double yres = gtk_print_context_get_dpi_y (context); - - /* This means that the cairo context now has its dimensions in Points */ - cairo_scale (cr, xres / 72.0, yres / 72.0); - - return cr; + return cairo_reference (cr); } - static void create_xr_print_driver (GtkPrintContext *context, struct psppire_output_view *view) { @@ -1011,11 +999,13 @@ create_xr_print_driver (GtkPrintContext *context, struct psppire_output_view *vi [V] = gtk_page_setup_get_paper_height (ps, GTK_UNIT_POINTS) * XR_POINT, }; + /* These are all 1/2 inch. The "margins" that GTK+ gives us are useless: + they are the printer's imagable area. */ int margins[TABLE_N_AXES][2] = { - [H][0] = gtk_page_setup_get_left_margin (ps, GTK_UNIT_POINTS) * XR_POINT, - [H][1] = gtk_page_setup_get_right_margin (ps, GTK_UNIT_POINTS) * XR_POINT, - [V][0] = gtk_page_setup_get_top_margin (ps, GTK_UNIT_POINTS) * XR_POINT, - [V][1] = gtk_page_setup_get_bottom_margin (ps, GTK_UNIT_POINTS) * XR_POINT, + [H][0] = XR_POINT * 36, + [H][1] = XR_POINT * 36, + [V][0] = XR_POINT * 36, + [V][1] = XR_POINT * 36, }; double size[TABLE_N_AXES]; @@ -1031,14 +1021,11 @@ create_xr_print_driver (GtkPrintContext *context, struct psppire_output_view *vi *view->page_style = (struct xr_page_style) { .ref_cnt = 1, - .size = { [H] = size[H], [V] = size[V] }, .margins = { [H] = { margins[H][0], margins[H][1] }, [V] = { margins[V][0], margins[V][1] }, }, - .font = pango_font_description_copy (proportional_font), .bg = { .alpha = 0 }, - .font_scale = 72.0 / 128.0, .initial_page_number = 1, .object_spacing = 12 * XR_POINT, }; @@ -1048,6 +1035,7 @@ create_xr_print_driver (GtkPrintContext *context, struct psppire_output_view *vi .ref_cnt = 1, .size = { [H] = size[H], [V] = size[V] }, + .min_break = { [H] = size[H] / 2, [V] = size[V] / 2 }, .fonts = { [XR_FONT_PROPORTIONAL] = proportional_font, [XR_FONT_FIXED] = fixed_font, @@ -1058,7 +1046,7 @@ create_xr_print_driver (GtkPrintContext *context, struct psppire_output_view *vi .font_scale = 72.0 / 128.0 }; - view->pager = xr_pager_create (view->page_style); + view->pager = xr_pager_create (view->page_style, view->fsm_style); } static gboolean @@ -1074,8 +1062,7 @@ paginate (GtkPrintOperation *operation, } else if (view->print_item < view->n_items) { - xr_pager_add_item (view->pager, view->fsm_style, - view->items[view->print_item++].item); + xr_pager_add_item (view->pager, view->items[view->print_item++].item); while (xr_pager_needs_new_page (view->pager)) { xr_pager_add_page (view->pager, @@ -1086,11 +1073,11 @@ paginate (GtkPrintOperation *operation, } else { - gtk_print_operation_set_n_pages (operation, view->print_n_pages); + gtk_print_operation_set_n_pages (operation, MAX (1, view->print_n_pages)); /* Re-create the driver to do the real printing. */ xr_pager_destroy (view->pager); - view->pager = xr_pager_create (view->page_style); + view->pager = xr_pager_create (view->page_style, view->fsm_style); view->print_item = 0; view->paginated = TRUE; @@ -1106,7 +1093,7 @@ begin_print (GtkPrintOperation *operation, create_xr_print_driver (context, view); view->print_item = 0; - view->print_n_pages = 1; + view->print_n_pages = 0; view->paginated = FALSE; } @@ -1116,6 +1103,7 @@ end_print (GtkPrintOperation *operation, struct psppire_output_view *view) { xr_pager_destroy (view->pager); + view->pager = NULL; } @@ -1129,8 +1117,7 @@ draw_page (GtkPrintOperation *operation, get_cairo_context_from_print_context (context)); while (!xr_pager_needs_new_page (view->pager) && view->print_item < view->n_items) - xr_pager_add_item (view->pager, view->fsm_style, - view->items [view->print_item++].item); + xr_pager_add_item (view->pager, view->items [view->print_item++].item); } @@ -1145,6 +1132,9 @@ psppire_output_view_print (struct psppire_output_view *view, if (view->print_settings != NULL) gtk_print_operation_set_print_settings (print, view->print_settings); + gtk_print_operation_set_use_full_page (print, TRUE); + gtk_print_operation_set_unit (print, GTK_UNIT_POINTS); + g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), view); g_signal_connect (print, "end_print", G_CALLBACK (end_print), view); g_signal_connect (print, "paginate", G_CALLBACK (paginate), view);