/* Routines to generate PostScript files. */ /* Last edited on 2002-03-15 09:35:53 by stolfi */ #ifndef psplot_H #define psplot_H #include #include typedef struct psplot_Descriptor PSPLOT; /* A PSPLOT object is a virtual graphics device that uses a graphics model similar to Postscript's. The main differences are: * The default coordinate system is in millimeters rather than points. * Line widths and dash lengths are specified in true millimeters, and are unaffected by changes in the user coordinate scales. * The graphics state includes three separate color registers, respectively for line drawing, area filling, and text printing. Each can be set to an `invisible' color to supress the corresponding features of geometric figures. * The graphics state includes a `current range' for each coordinate axis. Those ranges define the nominal `current region', which is implicitly used in some drawing commands (see "psplot_region") and may be set to clip subsequent drawing commands. The current X range also defines the margins for printing text. * The current region is implicitly divided into a a grid of cells, the `current grid', which is used by some drawing commands (see "psplot_grid_cell"). * The graphics state includes a `current text cursor', a point which defines the starting position for text_writing commands. * The graphics primitives are somewhat different from the Postscript ones, and some functionality is not available (except by writing raw Postscript commands with "raw_postscript"). */ /* PLOT CREATION */ /* New PSPLOT objects are created by "new_figure" (for Encapsulated Postscript figures) or "new_document" (for multi-page Postscript documents). For the latter, each page behaves like a separate figure. In either case, the initial coordinate system will be in millimeters, measured from the bottom left corner of the figure. The initial plotting region will be the whole figure, and the text cursor will be set to the upper left corner. The line and text colors will be set to solid Black, the area color will be set to Invisible. Line joints and caps will be rounded off. */ PSPLOT *psplot_new_figure(FILE *file, double x_size, double y_size); /* Writes into the given file the Postscript header and procedure sets approriate for an Encapsulated figure --- namely, with a "%%BoundingBox" comment, without an explicit "showpage" command, and suitable for inclusion in other documents. The extension ".eps" is recommended. The nominal figure size will be "x_size" by "y_size" in millimeters. The typical usage pattern is: | PSPLOT *p = psplot_new_figure(fopen("foo.eps", "w"), 150.0, 150.0); | psplot_segment(p, ...); | psplot_circle(p, ...); | ... | psplot_close(p, ...); */ PSPLOT *psplot_new_document( FILE *file, char *title, double x_page_size, double y_page_size ); /* Writes into the given file the Postscript header and procedure sets approriate for a multipage document, suitable for sending to the printer. The extension ".ps" is recommended. The nominal page size will be "x_page_size" by "y_page_size" in millimeters. If zero, these parameters default to the US Letter size (215.9 × 279.4 mm). Clients must call "begin_page" before issuing any other commands to the returned PSPLOT object. The typical usage pattern is: | PSPLOT *p = psplot_new_document(fopen("foo.ps", "w"), 0, 0); | psplot_begin_page(p, ...) | psplot_segment(p, ...); | ... | psplot_end_page(p); | psplot_begin_page(p, ...); | ... | psplot_end_page(p); | ... | psplot_close(p) */ /* US Letter sizes in mm: */ #define letter_x_size (8.5 * 25.4) #define letter_y_size (11.0 * 25.4) /* A4 Letter sizes in mm: */ #define a4_x_size (210.0) #define a4_y_size (297.0) void psplot_begin_page(PSPLOT *p, char *page_label); /* Starts a new page, by writing the "%%BeginPage" line, etc. A sequential page number is provided autmatically. The "page_label" is the client-assigned page label. If the "page_label" is NULL, it defaults to the "page_num". Resets the initial coordinate system to millimeters, with origin at the bottom left corner of the page. The initial plotting region will cover the whole page. */ void psplot_end_page(PSPLOT *p); /* Finishes the current page: issues the "showpage" command, writes "%%EndPage" line, etc. Implicitly ends any unpaired "begin_contenxt". */ /* TERMINATION */ void psplot_close(PSPLOT *p); /* MUST be called to write the necessary trailers, flush buffers, and close the underlying Postscript file. */ /* GENERAL OPERATIONS */ /* The following operations can be applied equally to multipage documents and to Encapsulated figures. In the former case, they must be within the scope of a "begin_page"/"end_page" pair of calls. */ /* COLORS */ #define psplot_Invisible ((psplot_Color){-1.0, -1.0, -1.0}) #define psplot_Black ((psplot_Color){{0.0, 0.0, 0.0}}) #define psplot_Red ((psplot_Color){{1.0, 0.0, 0.0}}) #define psplot_Yellow ((psplot_Color){{1.0, 1.0, 0.0}}) #define psplot_Green ((psplot_Color){{0.0, 1.0, 0.0}}) #define psplot_Cyan ((psplot_Color){{0.0, 1.0, 1.0}}) #define psplot_Blue ((psplot_Color){{0.0, 0.0, 1.0}}) #define psplot_Magenta ((psplot_Color){{1.0, 0.0, 1.0}}) #define psplot_White ((psplot_Color){{1.0, 1.0, 1.0}}) psplot_Color Gray(float v); /* A gray color with given brightness. */ void psplot_set_line_color(PSPLOT *p, psplot_Color *color); void psplot_set_area_color(PSPLOT *p, psplot_Color *color); void psplot_set_text_color(PSPLOT *p, psplot_Color *color); /* Define the color to be used for line drawing, for area filling, and for labels and captions, respectively Any of the three colors may be set to "pscolor_invisible" to supress the corresponding features. */ /* LINE DRAWINGS */ void psplot_set_line_width(PSPLOT *p, double width); void psplot_set_line_solid(PSPLOT *p); void psplot_set_line_dashed(PSPLOT *p, double *pattern, double skip); /* Sets the line width, and dash length/space pattern for line drawing. The color also applies to text labels. Width and dash lengths are in millimeters, irrespective of current scale. */ void psplot_segment(PSPLOT *p, double xa, double ya, double xb, double yb); /* Draws a segment from "(xa,ya)" to "(xb,yb)", using the current line parameters. */ void psplot_curve( PSPLOT *p, double xa, double ya, double xb, double yb, double xc, double yc, double xd, double yd ); /* Draws a Bezier arc with given control points. */ void psplot_coord_line(PSPLOT *p, psplot_Axis axis, double coord); /* Draws a reference line perpendicular to the given axis at the given coordinate value. */ void psplot_solid_dot(PSPLOT *p, double xc, double yc, double relsize); /* Draws a round dot with center "(xc,yc)" (in client coordinates) and diameter equal to "relsize" times the current line width. The dot is painted solid with the current *line* color and is not outlined. */ void psplot_arrowhead( PSPLOT *p, double xa, double ya, double xb, double yb, double width, double length, double fraction ); /* Draws triangular arrowhead suitable for a arrow with base at "(xa,ya)" and tip at "(xb,yb)", with given width and length relative to the current line width. The arrowhead is placed with the tip at "fraction" of the way from "(xa,ya)" to "(xb,yb)", and is painted solid with the current *line* color. */ /* AREA PAINTING */ /* The following procedures will paint the interior of the figure with the current "area" color, and then draw the outline with the current "line" parameters (color, pen width, and dash pattern). Use the "pscolor_invisible" color to prevent either of these action from happening. */ void psplot_filled_dot(PSPLOT *p, double xc, double yc, double relsize); /* Plots a round dot with center "(xc,yc)" (in client coordinates) and diameter equal to "relsize" times the current line width. This procedure is similar to "solid_dot" except that the circle is filled with the current *area* color, and outlined with the current line style and color. */ void psplot_rectangle(PSPLOT *p, double xlo, double xhi, double ylo, double yhi); /* Plots the rectangle "[xlo..xhi] x [ylo..yhi]". */ void psplot_circle(PSPLOT *p, double xc, double yc, double radius); /* Plots the circle with center "(xc,yc)" and given radius (in client coordinates). */ void psplot_triangle( PSPLOT *p, double xa, double ya, double xb, double yb, double xc, double yc ); /* Plots the triangle "(xa,ya), (xb,yb), (xc,yc)". */ void psplot_ellipse( PSPLOT *p, double xc, double yc, double xa, double ya, double xb, double yb ); /* Plots the ellipse which corresponds to the unit circle in the affine frame with origin "(xc,yc)" and basis vectors "(xa,ya), (xb,yb)". */ void plot_lune( PSPLOT *p, double xa, double ya, double ra, double xb, double yb, double rb ); /* Plots the lune (lens-like region) with arc midpoints (xa,ya) and (xb,yb), and arc radii ra and rb. */ void psplot_slice( PSPLOT *p, double xc, double yc, double radius, double start, double stop ); /* Plots the pie slice with given center, radius, and angle range. */ void psplot_polygon( PSPLOT *p, double x[], double y[], int n ); /* Plots the polygon (x[0],y[0]),.. (x[n-1],y[n-1]). */ void psplot_region(PSPLOT *p); /* Plots the current region, i.e. the rectangle corresponding to the current X and Y ranges. This command ignores the current clipping path, so the rectangle's outline may extend 1/2 linewidth outside the current plotting region (see below). */ /* NOMINAL PLOTTING REGION */ void psplot_set_range( PSPLOT *p, double xmin, double xmax, double ymin, double ymax ); /* Sets the nominal plotting region to be "[xmin _ xmax]×[ymin _ ymax]", without changing the current coordinate system. */ void psplot_set_range_centered( PSPLOT *p, double xsize, double ysize, double xcenter, double ycenter, int clip ); /* Equivalent to "set_range" except that the ranges are specified by their center and extent, rather than their endpoints. */ psplot_Range psplot_get_range(PSPLOT *p, psplot_Axis axis); /* Returns the current range "[r.min, r.max]" of plottable coordinates for the given axis. */ /* CLIPPING */ void psplot_set_clipping(PSPLOT *p, int clip); /* If "clip = TRUE", subsequent plotting commands will be clipped to the current plotting region. If "clip = FALSE", subsequent commands can draw anywhere on the figure/page. */ /* GRID DRAWING/PAINTING */ void psplot_set_grid_size(PSPLOT *p, int xn, int yn); /* Implicitly divides the current plotting region into an array of "xn" by "yn" cells, for use by the procedures "grid_cell" and "grid_lines" below. The cells are numbered left to right from 0 to "xn-1", and bottom to top from 0 to "yn-1". */ void psplot_grid_cell(PSPLOT *p, int xi, int yi); /* Plots the specified cell of the cell grid. The cell's outline is drawn without regard for the current clipping path (so that it may extend 1/2 linewidth outside the current plotting region). */ void psplot_grid_lines(PSPLOT *p); /* Draws all cell grid lines, within the current plotting region but ignoring the current clipping path (so that the lines may extend 1/2 linewidth outside the current plotting region). */ /* TEXT */ /* For the following commands, the "font" must be the name of a built-in Postscript font (e.g. "TimesRoman", "Courier", "Helvetica", etc.). The font will be scaled so that the baselines are "font_size" points apart. Commands that print multi-line text will place the baselines exactly "font_size" points apart, irrespective of the actual height or depth of the printed characters. */ void psplot_set_cursor(PSPLOT *p, double x, double y); /* Sets the text cursor for subsequent "print" commands. */ void psplot_newline(PSPLOT *p, double font_size); /* Sets the text cursor to the beginning of the next line. */ void psplot_print(PSPLOT *p, char *txt, char *font, double font_size, double x_align); /* Prints "txt" using the specified font and font size, starting at the current text cursor. The text "txt" will be broken into lines at newline characters ('\n'). Each line will be printed with its baseline at the Y coordinate of the current text cursor, in the space between that cursor and the current right margin (the upper endpoint of the current X range). If "x_align" is 0.0, 0.5, or 1.0, the line will be left-justified, centered, or right-justified in that space, respectively. At each newline (including the last one, if present) the text cursor will be moved down by font_size points, and horizontally to the left margin (the lower endpoint of the current X range). */ void psplot_label( PSPLOT *p, char *txt, char *font, double font_size, double x, double y, double x_align, double y_align, int base_align, double turns ); /* Prints "txt" tilted by "turns" full turns with its reference point at "(x,y)". The current text font and text cursor are not affected. If "base_align" is FALSE, the parameters "x_align" and "y_align" will be the coordinates of the reference point relative to the text's bounding box: "(0,0)" means the lower left corner, "(1,1)" the upper right corner, "(0.5,0.5)" the center, etc. If "base_align" is TRUE, the vertical position of the reference point will be interpolated between the baselines of the bottom and top lines, instead of the bounding box edges. For multi-line labels, the "x_align" parameter also defines the horizontal alignment of the lines: 0 for left-justified, 0.5 for centered, 1.0 for right-justified. In either case, the left and right margins are defined by the width of the widest line. This command is equivalent to | begin_context(p); | translate(p, x, y); | rotate(p, turns); | set_range(p, Axis_X, -x_align*wd, (1-x_align)*wd); | set_clip(0); | set_text_cursor(p, -x_align*wd, y0); | print(txt, font, font_size, x_align); | end_context(p) where "wd" is the width of the text's bounding box, and "y0" is the position of the first baseline as computed from "txt", "base_align", "y_align", and "font_size". Note that the "rotate" will fail unless the current X and Y scales are equal. */ /* COORDINATE SYSTEM */ void psplot_translate(PSPLOT *p, double xt, double yt); /* Translates the origin of the coordinate system to the point "(xt,yt)". The nominal plotting region becomes undefined. */ void psplot_scale(PSPLOT *p, double xs, double ys); /* Scales the X and Y coordinate units by the factors "xs" and "ys", respectively. The nominal plotting region becomes undefined. */ void psplot_rotate(PSPLOT *p, double turns); /* Rotates the coordinate axes to "turns" full turns (i.e. "turns*360" degrees, or "turns*2*pi" radians) counterclockwise. The nominal plotting region becomes undefined. If the current X and Y scales are different, the "turns" argument must be an integer multiple of 0.25 (a right angle turn). */ void psplot_set_scale(PSPLOT *p, psplot_Axis axis, double cmin, double cmax); /* Combines a translation and scaling on the given axis so that the current nominal plotting region remains the same on paper, but its coordinate range becomes "[cmin _ cmax]". The clipping status remains unchanged. */ double psplot_get_scale_factor(PSPLOT *p, psplot_Axis axis); /* Returns the current plotting scale along the given "axis", that, is, the actual printed displacement (in mm) that corresponds to an increment of 1 in the specified coordinate of the client's reference system. */ /* TEMPORARY PLOTTING CONTEXTS */ void psplot_begin_context(PSPLOT *p); /* Starts a new plotting context. Persistent graphics parameters are saved in a stack, and can be restored by a matched call to "end_context". The saved parameters are the current values of the current * coordinate system. * line width and dash patterns. * line, area, and fill colors. * ordinate for caption text. * nominal X and Y ranges, and whether they are clipping. * path and path endpoint (Postscript's "current point"). * font. */ void psplot_end_context(PSPLOT *p); /* Finishes the current drawing. */ /* MISCELLANEOUS */ void psplot_insert_comment(PSPLOT *p, char *txt); /* Writes "txt" to the file, as a "%" comment; it has no visible effect. */ void psplot_insert_raw_postscript(PSPLOT *p, char *txt); /* Writes a text string the underlying Postscript file, literally Not for casual use. */ void psplot_insert_postscript_string(PSPLOT *p, char *txt, char *newline); /* Writes a text string to the underlying Postscript file, in Postscript form (i.e. delimited by parentheses). Any embedded newline characters ('\n') in the string are replaced by the given "newline" string. Other non-ASCII characters and parentheses embedded in the "txt" are converted to the proper Postscript escape sequences. */ /* Some things that should be added to this package: * Other geometric primitives * Incremental path construction, including B'eziers and circular and elliptical arcs. * A "landscape" and "paper_type" arguments to "psplot_new_document", to generate the appropriate printer control comments in the header. */ /****************************************************************************/ /* */ /* Copyright © 1995 Universidade Estadual de Campinas (UNICAMP) */ /* */ /* Authors: */ /* Jorge Stolfi - CS Dept, UNICAMP */ /* */ /* This file can be freely used, distributed, and modified, provided that */ /* this copyright and authorship notice is included in every copy or */ /* derived version. */ /* */ /* DISCLAIMER: This software is offered ``as is'', without any guarantee */ /* as to fitness for any particular purpose. Neither the copyright */ /* holder nor the authors or their employers can be held responsible for */ /* any damages that may result from its use. */ /* */ /****************************************************************************/ #endif