X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcairo.c;h=a2d5fef9d1ddfd36914ef6f3fa22e55fdcb48424;hb=59981a5060a0e672b98655be240886d89a513d31;hp=53c454c2daeaa0bfe04e9821b58fb08d7b3749ac;hpb=f75d96d09553928fb3c5461a2e75efdd6f9e76e1;p=pspp diff --git a/src/output/cairo.c b/src/output/cairo.c index 53c454c2da..a2d5fef9d1 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -16,11 +16,13 @@ #include +#include + #include #include #include #include -#include +#include #include #include @@ -55,9 +57,9 @@ top-margin=0.5in bottom-margin=0.5in - prop-font=Times-Roman - emph-font=Times-Italic - fixed-font=Courier + prop-font=serif + emph-font=serif italic + fixed-font=monospace font-size=10000 line-gutter=1pt @@ -102,29 +104,36 @@ struct xr_font /* Cairo output driver extension record. */ struct xr_driver_ext { - char *file_name; /* Output file name. */ - enum xr_output_type file_type; /* Type of output file. */ cairo_t *cairo; + struct xr_font fonts[OUTP_FONT_CNT]; bool draw_headers; /* Draw headers at top of page? */ int page_number; /* Current page number. */ + int line_gutter; /* Space around lines. */ + int line_space; /* Space between lines. */ + int line_width; /* Width of lines. */ + }; + +struct xr_driver_options + { + struct outp_driver *driver; + + char *file_name; /* Output file name. */ + enum xr_output_type file_type; /* Type of output file. */ + + bool portrait; /* Portrait mode? */ + int paper_width; /* Width of paper before dropping margins. */ int paper_length; /* Length of paper before dropping margins. */ int left_margin; /* Left margin in XR units. */ int right_margin; /* Right margin in XR units. */ int top_margin; /* Top margin in XR units. */ int bottom_margin; /* Bottom margin in XR units. */ - - int line_gutter; /* Space around lines. */ - int line_space; /* Space between lines. */ - int line_width; /* Width of lines. */ - - struct xr_font fonts[OUTP_FONT_CNT]; }; -static bool handle_option (struct outp_driver *this, const char *key, +static bool handle_option (void *options, const char *key, const struct string *val); static void draw_headers (struct outp_driver *this); @@ -134,34 +143,18 @@ static int text_width (struct outp_driver *, const char *, enum outp_font); /* Driver initialization. */ -static bool -xr_open_driver (const char *name, int types, struct substring options) +static struct outp_driver * +xr_allocate (const char *name, int types) { - cairo_surface_t *surface; - cairo_status_t status; struct outp_driver *this; struct xr_driver_ext *x; - double width_pt, length_pt; size_t i; this = outp_allocate_driver (&cairo_class, name, types); this->width = this->length = 0; this->font_height = XR_POINT * 10; - - this->ext = x = xmalloc (sizeof *x); - x->file_name = xstrdup ("pspp.pdf"); - x->file_type = XR_PDF; - x->draw_headers = true; - x->page_number = 0; - x->portrait = true; - outp_get_paper_size ("", &x->paper_width, &x->paper_length); - x->left_margin = XR_INCH / 2; - x->right_margin = XR_INCH / 2; - x->top_margin = XR_INCH / 2; - x->bottom_margin = XR_INCH / 2; - x->line_gutter = XR_POINT; - x->line_space = XR_POINT; - x->line_width = XR_POINT / 2; + this->ext = x = xzalloc (sizeof *x); + x->cairo = NULL; x->fonts[OUTP_FIXED].string = xstrdup ("monospace"); x->fonts[OUTP_PROPORTIONAL].string = xstrdup ("serif"); x->fonts[OUTP_EMPHASIS].string = xstrdup ("serif italic"); @@ -172,12 +165,87 @@ xr_open_driver (const char *name, int types, struct substring options) font->metrics = NULL; font->layout = NULL; } + x->draw_headers = true; + x->page_number = 0; + x->line_gutter = XR_POINT; + x->line_space = XR_POINT; + x->line_width = XR_POINT / 2; + + return this; +} + +static bool +xr_set_cairo (struct outp_driver *this, cairo_t *cairo) +{ + struct xr_driver_ext *x = this->ext; + int i; + + x->cairo = cairo; + + cairo_set_line_width (x->cairo, xr_to_pt (x->line_width)); + + for (i = 0; i < OUTP_FONT_CNT; i++) + if (!load_font (this, &x->fonts[i])) + return false; + + this->fixed_width = text_width (this, "0", OUTP_FIXED); + this->prop_em_width = text_width (this, "0", OUTP_PROPORTIONAL); + + this->horiz_line_width[OUTP_L_NONE] = 0; + this->horiz_line_width[OUTP_L_SINGLE] = 2 * x->line_gutter + x->line_width; + this->horiz_line_width[OUTP_L_DOUBLE] = (2 * x->line_gutter + x->line_space + + 2 * x->line_width); + memcpy (this->vert_line_width, this->horiz_line_width, + sizeof this->vert_line_width); + + return true; +} + +struct outp_driver * +xr_create_driver (cairo_t *cairo) +{ + struct outp_driver *this; + + this = xr_allocate ("cairo", 0); + this->width = INT_MAX / 8; + this->length = INT_MAX / 8; + if (!xr_set_cairo (this, cairo)) + { + this->class->close_driver (this); + outp_free_driver (this); + return NULL; + } + return this; +} - outp_parse_options (options, handle_option, this); +static bool +xr_open_driver (const char *name, int types, struct substring option_string) +{ + struct outp_driver *this; + struct xr_driver_ext *x; + struct xr_driver_options options; + cairo_surface_t *surface; + cairo_status_t status; + double width_pt, length_pt; + + this = xr_allocate (name, types); + x = this->ext; + + options.driver = this; + options.file_name = xstrdup ("pspp.pdf"); + options.file_type = XR_PDF; + options.portrait = true; + outp_get_paper_size ("", &options.paper_width, &options.paper_length); + options.left_margin = XR_INCH / 2; + options.right_margin = XR_INCH / 2; + options.top_margin = XR_INCH / 2; + options.bottom_margin = XR_INCH / 2; - width_pt = x->paper_width / 1000.0; - length_pt = x->paper_length / 1000.0; - if (x->portrait) + outp_parse_options (this->name, option_string, handle_option, &options); + + width_pt = options.paper_width / 1000.0; + length_pt = options.paper_length / 1000.0; + if (options.portrait) { this->width = pt_to_xr (width_pt); this->length = pt_to_xr (length_pt); @@ -188,16 +256,18 @@ xr_open_driver (const char *name, int types, struct substring options) this->length = pt_to_xr (length_pt); } if (x->draw_headers) - x->top_margin += 3 * this->font_height; - this->width -= x->left_margin + x->right_margin; - this->length -= x->top_margin + x->bottom_margin; - - if (x->file_type == XR_PDF) - surface = cairo_pdf_surface_create (x->file_name, width_pt, length_pt); - else if (x->file_type == XR_PS) - surface = cairo_ps_surface_create (x->file_name, width_pt, length_pt); - else if (x->file_type == XR_SVG) - surface = cairo_svg_surface_create (x->file_name, width_pt, length_pt); + options.top_margin += 3 * this->font_height; + this->width -= options.left_margin + options.right_margin; + this->length -= options.top_margin + options.bottom_margin; + + if (options.file_type == XR_PDF) + surface = cairo_pdf_surface_create (options.file_name, + width_pt, length_pt); + else if (options.file_type == XR_PS) + surface = cairo_ps_surface_create (options.file_name, width_pt, length_pt); + else if (options.file_type == XR_SVG) + surface = cairo_svg_surface_create (options.file_name, + width_pt, length_pt); else NOT_REACHED (); @@ -205,7 +275,7 @@ xr_open_driver (const char *name, int types, struct substring options) if (status != CAIRO_STATUS_SUCCESS) { error (0, 0, _("opening output file \"%s\": %s"), - x->file_name, cairo_status_to_string (status)); + options.file_name, cairo_status_to_string (status)); cairo_surface_destroy (surface); goto error; } @@ -214,13 +284,8 @@ xr_open_driver (const char *name, int types, struct substring options) cairo_surface_destroy (surface); cairo_translate (x->cairo, - xr_to_pt (x->left_margin), - xr_to_pt (x->top_margin)); - cairo_set_line_width (x->cairo, xr_to_pt (x->line_width)); - - for (i = 0; i < OUTP_FONT_CNT; i++) - if (!load_font (this, &x->fonts[i])) - goto error; + xr_to_pt (options.left_margin), + xr_to_pt (options.top_margin)); if (this->length / this->font_height < 15) { @@ -232,22 +297,17 @@ xr_open_driver (const char *name, int types, struct substring options) goto error; } - this->fixed_width = text_width (this, "0", OUTP_FIXED); - this->prop_em_width = text_width (this, "0", OUTP_PROPORTIONAL); - - this->horiz_line_width[OUTP_L_NONE] = 0; - this->horiz_line_width[OUTP_L_SINGLE] = 2 * x->line_gutter + x->line_width; - this->horiz_line_width[OUTP_L_DOUBLE] = (2 * x->line_gutter + x->line_space - + 2 * x->line_width); - memcpy (this->vert_line_width, this->horiz_line_width, - sizeof this->vert_line_width); + if (!xr_set_cairo (this, x->cairo)) + goto error; outp_register_driver (this); + free (options.file_name); return true; error: this->class->close_driver (this); outp_free_driver (this); + free (options.file_name); return false; } @@ -265,12 +325,11 @@ xr_close_driver (struct outp_driver *this) cairo_surface_finish (cairo_get_target (x->cairo)); status = cairo_status (x->cairo); if (status != CAIRO_STATUS_SUCCESS) - error (0, 0, _("writing output file \"%s\": %s"), - x->file_name, cairo_status_to_string (status)); + error (0, 0, _("error writing output file for %s driver: %s"), + this->name, cairo_status_to_string (status)); cairo_destroy (x->cairo); } - free (x->file_name); for (i = 0; i < OUTP_FONT_CNT; i++) free_font (&x->fonts[i]); free (x); @@ -318,9 +377,10 @@ static const struct outp_option option_tab[] = }; static bool -handle_option (struct outp_driver *this, const char *key, - const struct string *val) +handle_option (void *options_, const char *key, const struct string *val) { + struct xr_driver_options *options = options_; + struct outp_driver *this = options->driver; struct xr_driver_ext *x = this->ext; int subcat; char *value = ds_cstr (val); @@ -329,20 +389,20 @@ handle_option (struct outp_driver *this, const char *key, { case -1: error (0, 0, - _("unknown configuration parameter `%s' for Cairo device " - "driver"), key); + _("unknown configuration parameter `%s' for %s device " + "driver"), key, this->class->name); break; case output_file_arg: - free (x->file_name); - x->file_name = xstrdup (value); + free (options->file_name); + options->file_name = xstrdup (value); break; case output_type_arg: if (!strcmp (value, "pdf")) - x->file_type = XR_PDF; + options->file_type = XR_PDF; else if (!strcmp (value, "ps")) - x->file_type = XR_PS; + options->file_type = XR_PS; else if (!strcmp (value, "svg")) - x->file_type = XR_SVG; + options->file_type = XR_SVG; else { error (0, 0, _("unknown Cairo output type \"%s\""), value); @@ -350,13 +410,14 @@ handle_option (struct outp_driver *this, const char *key, } break; case paper_size_arg: - outp_get_paper_size (value, &x->paper_width, &x->paper_length); + outp_get_paper_size (value, + &options->paper_width, &options->paper_length); break; case orientation_arg: if (!strcmp (value, "portrait")) - x->portrait = true; + options->portrait = true; else if (!strcmp (value, "landscape")) - x->portrait = false; + options->portrait = false; else error (0, 0, _("unknown orientation `%s' (valid orientations are " "`portrait' and `landscape')"), value); @@ -383,16 +444,16 @@ handle_option (struct outp_driver *this, const char *key, switch (subcat) { case 0: - x->left_margin = dimension; + options->left_margin = dimension; break; case 1: - x->right_margin = dimension; + options->right_margin = dimension; break; case 2: - x->top_margin = dimension; + options->top_margin = dimension; break; case 3: - x->bottom_margin = dimension; + options->bottom_margin = dimension; break; case 4: this->font_height = dimension; @@ -443,15 +504,24 @@ xr_close_page (struct outp_driver *this) } static void -xr_submit (struct outp_driver *this UNUSED, struct som_entity *s) +xr_output_chart (struct outp_driver *this, const struct chart *chart) { - switch (s->type) - { - case SOM_CHART: - break; - default: - NOT_REACHED (); - } + struct xr_driver_ext *x = this->ext; + struct chart_geometry geom; + + outp_eject_page (this); + outp_open_page (this); + + cairo_save (x->cairo); + cairo_translate (x->cairo, 0.0, xr_to_pt (this->length)); + cairo_scale (x->cairo, 1.0, -1.0); + chart_geometry_init (x->cairo, &geom, + xr_to_pt (this->width), xr_to_pt (this->length)); + chart_draw (chart, x->cairo, &geom); + chart_geometry_free (x->cairo); + cairo_restore (x->cairo); + + outp_close_page (this); } /* Draws a line from (x0,y0) to (x1,y1). */ @@ -776,28 +846,9 @@ xr_text_metrics (struct outp_driver *this, const struct outp_text *t, static void xr_text_draw (struct outp_driver *this, const struct outp_text *t) { - assert (this->page_open); text (this, t, true, NULL, NULL); } -static void -xr_chart_initialise (struct outp_driver *this UNUSED, struct chart *ch UNUSED) -{ -#ifdef NO_CHARTS - ch->lp = NULL; -#else - /* XXX libplot doesn't support Cairo yet. */ -#endif -} - -static void -xr_chart_finalise (struct outp_driver *this UNUSED, struct chart *ch UNUSED) -{ -#ifndef NO_CHARTS - /* XXX libplot doesn't support Cairo yet. */ -#endif -} - /* Attempts to load FONT, initializing its other members based on its 'string' member and the information in THIS. Returns true if successful, otherwise false. */ @@ -850,12 +901,11 @@ const struct outp_class cairo_class = xr_close_page, NULL, - xr_submit, + xr_output_chart, + + NULL, xr_line, xr_text_metrics, xr_text_draw, - - xr_chart_initialise, - xr_chart_finalise };