X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcairo.c;h=6eb39b276b7ca263a3170e692273f0ca70d81002;hb=dde5a3c946871b4aab3d6b436438dd8df11db261;hp=94dafd886b7914356b856701c09e6564269426b1;hpb=e23e9a06426e80e98fe2021a9a3326f9eea31d15;p=pspp-builds.git diff --git a/src/output/cairo.c b/src/output/cairo.c index 94dafd88..6eb39b27 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +128,7 @@ struct xr_driver /* Internal state. */ struct render_params *params; + char *command_name; char *title; char *subtitle; cairo_t *cairo; @@ -133,6 +136,8 @@ struct xr_driver int y; }; +static const struct output_driver_class cairo_driver_class; + static void xr_show_page (struct xr_driver *); static void draw_headers (struct xr_driver *); @@ -154,7 +159,7 @@ static void xr_draw_cell (void *, const struct table_cell *, static struct xr_driver * xr_driver_cast (struct output_driver *driver) { - assert (driver->class == &cairo_class); + assert (driver->class == &cairo_driver_class); return UP_CAST (driver, struct xr_driver, driver); } @@ -173,7 +178,7 @@ xr_allocate (const char *name, int device_type, struct string_map *o) xr = xzalloc (sizeof *xr); d = &xr->driver; - output_driver_init (d, &cairo_class, name, device_type); + output_driver_init (d, &cairo_driver_class, name, device_type); xr->headers = true; xr->font_height = XR_POINT * 10; xr->fonts[XR_FONT_FIXED].string @@ -232,8 +237,8 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) } static struct output_driver * -xr_create (const char *name, enum output_device_type device_type, - struct string_map *o) +xr_create (const char *file_name, enum settings_output_devices device_type, + struct string_map *o, enum xr_output_type file_type) { enum { MIN_WIDTH = 3, MIN_LENGTH = 3 }; struct output_driver *d; @@ -242,22 +247,13 @@ xr_create (const char *name, enum output_device_type device_type, cairo_status_t status; double width_pt, length_pt; int paper_width, paper_length; - char *file_name; - xr = xr_allocate (name, device_type, o); + xr = xr_allocate (file_name, device_type, o); d = &xr->driver; xr->headers = parse_boolean (opt (d, o, "headers", "true")); - xr->file_type = parse_enum (opt (d, o, "output-type", "pdf"), - "pdf", XR_PDF, - "ps", XR_PS, - "svg", XR_SVG, - (char *) NULL); - file_name = parse_string (opt (d, o, "output-file", - (xr->file_type == XR_PDF ? "pspp.pdf" - : xr->file_type == XR_PS ? "pspp.ps" - : "pspp.svg"))); + xr->file_type = file_type; parse_paper_size (opt (d, o, "paper-size", ""), &paper_width, &paper_length); xr->left_margin = parse_dimension (opt (d, o, "left-margin", ".5in")); @@ -284,7 +280,7 @@ xr_create (const char *name, enum output_device_type device_type, status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { - error (0, 0, _("opening output file \"%s\": %s"), + error (0, 0, _("error opening output file \"%s\": %s"), file_name, cairo_status_to_string (status)); cairo_surface_destroy (surface); goto error; @@ -321,7 +317,6 @@ xr_create (const char *name, enum output_device_type device_type, goto error; } - free (file_name); return &xr->driver; error: @@ -329,6 +324,27 @@ xr_create (const char *name, enum output_device_type device_type, return NULL; } +static struct output_driver * +xr_pdf_create (const char *file_name, enum settings_output_devices device_type, + struct string_map *o) +{ + return xr_create (file_name, device_type, o, XR_PDF); +} + +static struct output_driver * +xr_ps_create (const char *file_name, enum settings_output_devices device_type, + struct string_map *o) +{ + return xr_create (file_name, device_type, o, XR_PS); +} + +static struct output_driver * +xr_svg_create (const char *file_name, enum settings_output_devices device_type, + struct string_map *o) +{ + return xr_create (file_name, device_type, o, XR_SVG); +} + static void xr_destroy (struct output_driver *driver) { @@ -351,6 +367,7 @@ xr_destroy (struct output_driver *driver) cairo_destroy (xr->cairo); } + free (xr->command_name); for (i = 0; i < XR_N_FONTS; i++) free_font (&xr->fonts[i]); free (xr->params); @@ -393,67 +410,81 @@ xr_render_table_item (struct xr_driver *xr, const struct table_item *item, } static void -xr_submit (struct output_driver *driver, const struct output_item *output_item) +xr_output_table_item (struct xr_driver *xr, + const struct table_item *table_item) { - struct xr_driver *xr = xr_driver_cast (driver); - if (is_table_item (output_item)) - { - struct table_item *table_item = to_table_item (output_item); - struct render_break x_break; - struct render_page *page; - int caption_height; + struct render_break x_break; + struct render_page *page; + int caption_height; - if (xr->y > 0) - xr->y += xr->font_height; + if (xr->y > 0) + xr->y += xr->font_height; - page = xr_render_table_item (xr, table_item, &caption_height); - xr->params->size[V] = xr->length - caption_height; - for (render_break_init (&x_break, page, H); - render_break_has_next (&x_break); ) + page = xr_render_table_item (xr, table_item, &caption_height); + xr->params->size[V] = xr->length - caption_height; + for (render_break_init (&x_break, page, H); + render_break_has_next (&x_break); ) + { + struct render_page *x_slice; + struct render_break y_break; + + x_slice = render_break_next (&x_break, xr->width); + for (render_break_init (&y_break, x_slice, V); + render_break_has_next (&y_break); ) { - struct render_page *x_slice; - struct render_break y_break; + int space = xr->length - xr->y; + struct render_page *y_slice; + + /* XXX doesn't allow for caption or space between segments */ + if (render_break_next_size (&y_break) > space) + { + assert (xr->y > 0); + xr_show_page (xr); + continue; + } - x_slice = render_break_next (&x_break, xr->width); - for (render_break_init (&y_break, x_slice, V); - render_break_has_next (&y_break); ) + y_slice = render_break_next (&y_break, space); + if (caption_height) { - int space = xr->length - xr->y; - struct render_page *y_slice; - - /* XXX doesn't allow for caption or space between segments */ - if (render_break_next_size (&y_break) > space) - { - assert (xr->y > 0); - xr_show_page (xr); - continue; - } - - y_slice = render_break_next (&y_break, space); - if (caption_height) - { - struct table_cell cell; - int bb[TABLE_N_AXES][2]; - - xr_init_caption_cell (table_item_get_caption (table_item), - &cell); - bb[H][0] = 0; - bb[H][1] = xr->width; - bb[V][0] = 0; - bb[V][1] = caption_height; - xr_draw_cell (xr, &cell, bb, bb); - xr->y += caption_height; - caption_height = 0; - } - - render_page_draw (y_slice); - xr->y += render_page_get_size (y_slice, V); - render_page_unref (y_slice); + struct table_cell cell; + int bb[TABLE_N_AXES][2]; + + xr_init_caption_cell (table_item_get_caption (table_item), + &cell); + bb[H][0] = 0; + bb[H][1] = xr->width; + bb[V][0] = 0; + bb[V][1] = caption_height; + xr_draw_cell (xr, &cell, bb, bb); + xr->y += caption_height; + caption_height = 0; } - render_break_destroy (&y_break); + + render_page_draw (y_slice); + xr->y += render_page_get_size (y_slice, V); + render_page_unref (y_slice); } - render_break_destroy (&x_break); + render_break_destroy (&y_break); } + render_break_destroy (&x_break); +} + +static void +xr_output_text (struct xr_driver *xr, const char *text) +{ + struct table_item *table_item; + + table_item = table_item_create (table_from_string (TAB_LEFT, text), NULL); + xr_output_table_item (xr, table_item); + table_item_unref (table_item); +} + +static void +xr_submit (struct output_driver *driver, const struct output_item *output_item) +{ + struct xr_driver *xr = xr_driver_cast (driver); + if (is_table_item (output_item)) + xr_output_table_item (xr, to_table_item (output_item)); else if (is_chart_item (output_item)) { if (xr->y > 0) @@ -494,17 +525,17 @@ xr_submit (struct output_driver *driver, const struct output_item *output_item) break; default: - { - struct table_item *item; - - item = table_item_create (table_from_string (TAB_LEFT, text), - NULL); - xr_submit (&xr->driver, &item->output_item); - table_item_unref (item); - } + xr_output_text (xr, text); break; } - + } + else if (is_message_item (output_item)) + { + const struct message_item *message_item = to_message_item (output_item); + const struct msg *msg = message_item_get_msg (message_item); + char *s = msg_to_string (msg, xr->command_name); + xr_output_text (xr, s); + free (s); } } @@ -895,14 +926,17 @@ free_font (struct xr_font *font) if (font->desc != NULL) pango_font_description_free (font->desc); pango_font_metrics_unref (font->metrics); - g_object_unref (font->layout); + if (font->layout != NULL) + g_object_unref (font->layout); } -/* Cairo driver class. */ -const struct output_driver_class cairo_class = +struct output_driver_factory pdf_driver_factory = { "pdf", xr_pdf_create }; +struct output_driver_factory ps_driver_factory = { "ps", xr_ps_create }; +struct output_driver_factory svg_driver_factory = { "svg", xr_svg_create }; + +static const struct output_driver_class cairo_driver_class = { "cairo", - xr_create, xr_destroy, xr_submit, xr_flush, @@ -944,6 +978,19 @@ xr_create_driver (cairo_t *cairo) return xr; } +static struct xr_rendering * +xr_rendering_create_text (struct xr_driver *xr, const char *text, cairo_t *cr) +{ + struct table_item *table_item; + struct xr_rendering *r; + + table_item = table_item_create (table_from_string (0, text), NULL); + r = xr_rendering_create (xr, &table_item->output_item, cr); + table_item_unref (table_item); + + return r; +} + struct xr_rendering * xr_rendering_create (struct xr_driver *xr, const struct output_item *item, cairo_t *cr) @@ -951,15 +998,15 @@ xr_rendering_create (struct xr_driver *xr, const struct output_item *item, struct xr_rendering *r = NULL; if (is_text_item (item)) + r = xr_rendering_create_text (xr, text_item_get_text (to_text_item (item)), + cr); + else if (is_message_item (item)) { - const struct text_item *text_item = to_text_item (item); - const char *text = text_item_get_text (text_item); - struct table_item *table_item; - - table_item = table_item_create (table_from_string (TAB_LEFT, text), - NULL); - r = xr_rendering_create (xr, &table_item->output_item, cr); - table_item_unref (table_item); + const struct message_item *message_item = to_message_item (item); + const struct msg *msg = message_item_get_msg (message_item); + char *s = msg_to_string (msg, NULL); + r = xr_rendering_create_text (xr, s, cr); + free (s); } else if (is_table_item (item)) { @@ -1072,7 +1119,7 @@ xr_draw_png_chart (const struct chart_item *item, status = cairo_surface_write_to_png (surface, file_name); if (status != CAIRO_STATUS_SUCCESS) - error (0, 0, _("writing output file \"%s\": %s"), + error (0, 0, _("error writing output file \"%s\": %s"), file_name, cairo_status_to_string (status)); cairo_destroy (cr);