|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T f
Length: 26888 (0x6908) Types: TextFile Names: »fig2ps.p«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./tex82/TeXgraphics/transfig/fig2ps/fig2ps.p«
program fig2ps (input, output); { Author: Igor Metz <metz@iam.unibe.ch> } { Created: Thu Jan 7 16:11:38 1988 } { Filename: /usr/u-gina/metz/work/fig2ps/fig2ps.p } { This program translates files, that were created with FIG 1.3.1, to PostScript. The PostScript code generated can be incorporated into TeX with psfig. Current version: 1.13 Revision History: Feb., 09. 88: (Igor Metz) - in procedure read_object the linewidth and lineheight were read in reversed order (for arcs). Same error below!! - Reported by Andreas Ueltschi: the procedure calc_tangent calculated wrong coordinates! Feb., 08. 88: (Igor Metz) - in procedure read_object the linewidth and lineheight were read in reverse order (for lines and splines)! Feb., 03. 88: (Igor Metz) - the procedure write_string now prefixes '(' and ')' with a backslash to prevent troubles, when strings to be printed contain '(' or ')'. Jan., 27. 88: (Igor Metz) - support for spline has been added. Jan., 27. 88: (Igor Metz) - the adaptation of linewidths for ellipses was a bit strange. The new method is to save the CTM before scaling, and to restore be CTM before stroking. - the drawing had to be shifted to the left on the page, since printers can't print on the entire page. Jan., 26. 88: (Igor Metz) - for dashed lines and arcs the arrow head was also dashed: bug is fixed. - the position of the drawing on the page has been corrected. - the linewidth for ellipses and circles had to be adapted, since we scale the coordinate system when we print them. Feb. 18 88: (Micah Beck) - increased resolution of spline rendering for 300 BPI printing. the code taken from Fig assumes 80 BPI. - fixed a bug in closed splines: there was no initial moveto command Feb. 23 88: (Micah Beck) - scale the figure by 72/pixels_per_inch to get correct size - translate lower left corner of figure to PS origin } const { the following generic object codes are taken from fig/object.h } ELLIPSE = 1; POLYLINE = 2; SPLINE = 3; TEXT = 4; ARC = 5; COMPOUND = 6; END_COMPOUND = -COMPOUND; { the following definitions are taken from fig/choices.h. They define } { the values the object component 'typ' can have. } DRAW_ELLIPSE_BY_RAD = 1; DRAW_ELLIPSE_BY_DIA = 2; DRAW_CIRCLE_BY_RAD = 3; DRAW_CIRCLE_BY_DIA = 4; DRAW_CIRCULAR_ARC = 5; DRAW_POLYLINE = 6; DRAW_BOX = 7; DRAW_POLYGON = 8; DRAW_TEXT = 9; DRAW_SPLINE = 10; DRAW_CLOSEDSPLINE = 11; DRAW_COMPOUND = 13; SOLID_LINE = 0; DASH_LINE = 1; DOTTED_LINE = 2; { not use by FIG 1.3.1 } MaxTextLength = 256; { max. length of texts in Fig-file (assumed!) } pi = 3.141592654; TOP_LEFT_Y = 820; { used for coordinate transformation FIG <-> PostScript } TOP_LEFT_X = 10; type objtype = (ellipse, polyline, spline, txt, arc, compound, end_compound); pPoint = ^tPoint; tPoint = record x,y : integer; next: pPoint end; {record} tPosition = record x,y : integer end; tEllipse = record typ, style : integer; thickness : integer; dash_length : real; direction : integer; center, radiuses, start, ending : tPosition; end; {record} tPolyline = record typ, style : integer; thickness : integer; dash_length : real; f_arrow : integer; b_arrow : integer; arrow_width, arrow_height: integer; start : pPoint; end; {record} tSpline = record typ, style : integer; thickness : integer; dash_length : real; f_arrow : integer; b_arrow : integer; arrow_width, arrow_height: integer; start : pPoint; end; {record} tText = record font, size, style : integer; height : integer; length : integer; corner : tPosition; chars : packed array [1..MaxTextLength] of char; end; {record} tArc = record typ, style : integer; thickness : integer; dash_length : real; direction : integer; f_arrow : integer; b_arrow : integer; arrow_width, arrow_height: integer; center_x, center_y : real; pos : array [1..3] of tPosition; end; {record} pObject = ^tObject; tObject = record next : pObject; case objname : objtype of ellipse : (ell : tEllipse); polyline : (poly: tPolyline); spline : (spl : tSpline); txt : (tex : tText); arc : (arq : tArc); end; var filename : packed array[1..128] of char; Objects : pObject; { list of objects found in the Fig-file } { the following 4 variables are in the Fig-file's header. They have } { always the same values, so we could define them as constants. } pixels_per_inch : integer; { always = 80 } origin : integer; { always = ? } canvas_width, canvas_height : integer; { always = 600 and = 800 } { coordinates that determine the bounding box of a drawing } llx, lly, urx, ury : real; procedure read_string (var str : array [lb .. ub : integer] of char); { read all charcters from current position to end of line. Trailing } { blanks are also read, since they could be part of the string. } var i : integer; ch : char; begin i:= lb; read(ch); { the first character is always blank! skip it } while not eoln(input) do begin read( str[i]); i:= i+1; end {while}; str[i]:= chr(0); { terminate string with null character } end { read_string }; procedure write_string (str : array [lb .. ub : integer] of char); { write all characters in str } var i : integer; begin i:= lb; while str[i] <> chr(0) do begin if (str[i]='(') or (str[i]=')') then write('\'); write(str[i]); i:= i+1; end {while}; end { write_string }; function min (a, b : real) : real; begin if a < b then min:= a else min:= b; end { min }; function max (a,b : real) : real; begin if a < b then max:= b else max:= a; end { max }; procedure read_file( var Objects : pObject); { read in the Fig-file from input, and build up a list of all object in } { the file. While reading keep track of the bounding box. } var obj_code : integer; Object : pObject; procedure read_object (obj : objtype; var Object : pObject); { read in the object 'obj' and store it's data in 'Object' } var tmp : integer; procedure read_points (var point : pPoint); { read in all points (coordinate pairs). The end is marked by the } { (9999,9999). } var last : pPoint; { points to last point in the list } aux : pPoint; { auxiliary } x_tmp, y_tmp : integer; begin last:= point; while not eoln(input) do begin read(x_tmp, y_tmp); if (x_tmp <> 9999) and (y_tmp <> 9999) then begin new(aux); { create new node } with aux^ do begin next:= nil; x:= x_tmp; y:= y_tmp; end {with}; if last=nil then begin { the list is empty, aux becomes first node } point:= aux; last:= aux; end else begin { append aux at end of list } last^.next:= aux; last:= aux; end { if }; end { if }; end {while}; end { read_points }; begin new(Object); with Object^ do begin next:= nil; objname:= obj; case obj of ellipse : with ell do begin read(typ, style,thickness,dash_length,direction); read(center.x, center.y); read(radiuses.x , radiuses.y); read(start.x, start.y); read(ending.x, ending.y); end {with}; polyline : with poly do begin read(typ, style, thickness, dash_length); read(f_arrow, b_arrow, arrow_height,arrow_width); read_points(start); end {with}; spline : with spl do begin read(typ, style, thickness, dash_length); read(f_arrow, b_arrow, arrow_height,arrow_width); read_points(start); end {with}; txt : with tex do begin read(font, size, style, height, length); read(corner.x, corner.y); read_string(chars); end {with}; arc : with arq do begin read(typ, style, thickness, dash_length, direction); read(f_arrow, b_arrow, arrow_height, arrow_width); read(center_x, center_y); read(pos[1].x, pos[1].y); read(pos[2].x, pos[2].y); read(pos[3].x, pos[3].y); end {with}; compound : read(tmp, tmp, tmp, tmp); { we ignore this info } end_compound : { do nothing } end {case}; readln; { skip end-of-line character } end {with}; if (obj=compound) or (obj=end_compound) then begin { since we ignore compounds, we can throw away this node } dispose(Object); Object:= nil; end { if }; end { read_object }; procedure insert_object (Object : pObject; var Objects : pObject); { insert the new 'Object' into the list of 'Objects'. The new object } { is inserted at the front of the list. } var aux : pObject; begin if Object <> nil then begin aux:= Objects; Objects:= Object; Object^.next:= aux; end { if }; end { insert_object }; begin Objects:= nil; { first read in the fileheader. } readln( pixels_per_inch, origin, canvas_width, canvas_height ); while not eof(input) do begin read(obj_code); case obj_code of ELLIPSE : read_object(ellipse, Object); POLYLINE : read_object(polyline, Object); SPLINE : read_object(spline, Object); TEXT : read_object(txt, Object); ARC : read_object(arc, Object); COMPOUND : read_object(compound, Object); END_COMPOUND : read_object(end_compound, Object); end {case}; insert_object(Object, Objects); end; {while} end; {read_line} procedure compute_bbox (Objects : pObject; var llx, lly, urx, ury : real); { compute the bounding box that surrounds the objects. } { If we want to compute the bounding box, we must never forget the following } { facts: } { Fig's coordinate system is : PostScript's (default) coordinate system is:} { (0,0) -------> (x,0) (0,y) ---------> (x,y)} { | | ^ ^ } { V V | | } { (0,y) -------> (x,y) (0,0) ---------> (x,0) } var p : pObject; lx, ly, ux, uy : real; tmp : real; procedure bbox (Object : pObject; var llx, lly, urx, ury : real); { compute the bounding box of a single object } var p : pPoint; delta : real; begin with Object^ do begin case objname of ellipse : with ell do begin llx:= center.x - radiuses.x; lly:= center.y - radiuses.y; urx:= center.x + radiuses.x; ury:= center.y + radiuses.y; end {with}; polyline : with poly do begin llx:= maxint; lly:= maxint; urx:= minint; ury:= minint; p:= start; while p <> nil do begin llx:= min(llx, p^.x); lly:= min(lly, p^.y); urx:= max(urx, p^.x); ury:= max(ury, p^.y); p:= p^.next; end {while}; { do not forget the arrow heads !} delta:= 0.5*arrow_width; llx:= llx - delta; lly:= lly - delta; urx:= urx + delta; ury:= ury + delta; end {with}; spline : with spl do begin { the same as for polyline } llx:= maxint; lly:= maxint; urx:= minint; ury:= minint; p:= start; while p <> nil do begin llx:= min(llx, p^.x); lly:= min(lly, p^.y); urx:= max(urx, p^.x); ury:= max(ury, p^.y); p:= p^.next; end {while}; { do not forget the arrow heads !} delta:= 0.5*arrow_width; llx:= llx - delta; lly:= lly - delta; urx:= urx + delta; ury:= ury + delta; end {with}; txt : with tex do begin llx:= corner.x; lly:= corner.y - height; urx:= corner.x + length; ury:= corner.y; end {with}; arc : with arq do begin delta:= 0.5*arrow_width; llx:= min(min(pos[1].x, pos[2].x), pos[3].x) - delta; lly:= min(min(pos[1].y, pos[2].y), pos[3].y) - delta; urx:= max(max(pos[1].x, pos[2].x), pos[3].x) + delta; ury:= max(max(pos[1].y, pos[2].y), pos[3].y) + delta; end {with}; otherwise { do nothing } end {case}; end {with}; end { bbox }; begin p:= Objects; llx:= maxint; lly:= maxint; urx:= minint; ury:= minint; while p <> nil do begin bbox(p, lx, ly, ux, uy); llx:= min(llx, lx); lly:= min(lly, ly); urx:= max(urx, ux); ury:= max(ury, uy); p:= p^.next; end {while}; { now we transform from FIG coordinates to PostScript (default) coordinates} tmp:= lly; llx:= llx + TOP_LEFT_X; lly:= TOP_LEFT_Y - ury; urx:= urx + TOP_LEFT_X; ury:= TOP_LEFT_Y - tmp; end { compute_bbox }; procedure generate_postscript (Objects : pObject; llx, lly, urx, ury : real); { Generate PostScript Code for the list of Objects. } var p : pObject; current_dashlength : real; current_thickness : integer; procedure header; { Write header. } begin writeln('%!'); writeln('%%BoundingBox: 0 0 ', ((urx-llx) * 72/pixels_per_inch):6:4, ' ', ((ury-lly) * 72/pixels_per_inch):6:4); { the following text must be the same as in ./header.ps !!!! } writeln('gsave'); writeln('/fig2psdict 20 dict def'); writeln('fig2psdict begin'); writeln('72 ', pixels_per_inch:6:0, ' div dup scale'); writeln(TOP_LEFT_X,TOP_LEFT_Y, ' translate'); writeln(-llx:6:0, -lly:6:0, ' translate'); writeln('/mtrx matrix currentmatrix def'); writeln('180 rotate'); writeln('[-1 0 0 1 0 0] concat'); writeln('/arrowhead'); writeln(' { /headlength exch def'); writeln(' /halfheadheight exch 2 div def'); writeln(' /tipy exch def'); writeln(' /tipx exch def'); writeln(' /taily exch def'); writeln(' /tailx exch def'); writeln(' /angle tipy taily sub tipx tailx sub atan def'); writeln(' /savematrix matrix currentmatrix def'); writeln(' tipx tipy translate'); writeln(' angle 90 add rotate'); writeln(' halfheadheight headlength moveto'); writeln(' 0 0 lineto'); writeln(' halfheadheight neg headlength lineto'); writeln(' savematrix setmatrix'); writeln('} def'); writeln('/printtext '); writeln(' { /txt exch def'); writeln(' /width exch def'); writeln(' /height exch def'); writeln(' /y exch def'); writeln(' /x exch def'); writeln(' gsave'); writeln(' /Courier findfont height scalefont setfont'); writeln(' /Courier findfont '); writeln(' [ width txt stringwidth pop div height mul 0 0 height 0 0] makefont'); writeln(' setfont'); writeln(' x y moveto'); writeln(' mtrx setmatrix'); writeln(' txt show'); writeln(' grestore'); writeln('} def'); writeln; end { header }; procedure generate (Object : pObject); { Generate PostScript Code for a single Object. } var p, { points to actual point } q, { points to last point } r : pPoint; { points to before last point } x0, y0 : integer; { point of contact of arc and tangent } x, y : real; { point on tangent } radius : real; { of an arc } procedure calc_tangent (var x,y : real; { point on tangent } x0, y0 : integer; { point of contact } xc, yc : real; { center of arc } x2, y2 : integer); { point on arc } { calculates a point (x,y) on the tangent which touches the arc in } { point (x0,y0). } var l : real; { length of direction vector } xn, yn : real; { components of direction vector } s : real; { scalar product } dx, dy : real; begin dx:= (x0-xc); dy:= - (y0-yc); l:= sqrt(dx*dx + dy*dy); xn:= dy / l; yn:= dx / l; s:= (x2-x0)*xn + (y2-y0)*yn; x:= s*xn + x0; y:= s*yn + y0; end { calc_tangent }; procedure chaikin_spline (x1, y1, x2, y2, x3, y3, x4, y4 : real); { The following spline drawing routine is from "An Algorithm for High-Speed Curve Generation" by George Merrill Chaikin, Computer Graphics and Image Processing, 3, Academic Press, 1974, 346-349. and "On Chaikin's Algorithm" by R. F. Riesenfeld, Computer Graphics and Image Processing, 4, Academic Press, 1975, 304-310. but I took it from fig/splsub.c } var xmid, ymid : real; begin xmid := (x2 + x3) * 0.5; ymid := (y2 + y3) * 0.5; if (abs(x1 - xmid) < 1) and (abs(y1 - ymid) < 1) then begin writeln(xmid:6:4, ' ', ymid:6:4, ' lineto'); end else begin chaikin_spline(x1, y1, ((x1 + x2) * 0.5), ((y1 + y2) * 0.5), ((3.0*x2 + x3) * 0.25), ((3.0*y2 + y3) * 0.25), xmid, ymid); end; {if} if (abs(xmid - x4) < 1) and (abs(ymid - y4) < 1) then begin writeln(x4:6:4, ' ', y4:6:4, ' lineto'); end else begin chaikin_spline(xmid, ymid, ((x2 + 3*x3) / 4), ((y2 + 3*y3) / 4), ((x3 + x4) / 2), ((y3 + y4) / 2), x4, y4); end { if }; end { chaikin_spline }; procedure draw_openspline (spl : tSpline); var cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4 : real; x1, y1, x2, y2 : real; p : pPoint; begin with spl do begin p:= start; if current_thickness <> thickness then begin writeln(thickness, ' setlinewidth'); current_thickness:= thickness; end { if }; x1 := p^.x; y1 := p^.y; p := p^.next; x2 := p^.x; y2 := p^.y; cx1 := (x1 + x2) * 0.5; cy1 := (y1 + y2) * 0.5; cx2 := (x1 + 3 * x2) * 0.25; cy2 := (y1 + 3 * y2) * 0.25; if b_arrow = 1 then begin { generate backward arrow } writeln('newpath'); writeln(x2:6:4, ' ', y2:6:4, ' ', x1:6:4, ' ', y1:6:4, ' ', arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end { if }; writeln('newpath'); if style <> SOLID_LINE then begin writeln('[3] 0 setdash'); end { if }; writeln(x1:6:4, ' ', y1:6:4, ' moveto'); writeln(cx1:6:4, ' ', cy1:6:4, ' lineto'); p:= p^.next; while p <> nil do begin x1 := x2; y1 := y2; x2 := p^.x; y2 := p^.y; cx3 := (3 * x1 + x2) * 0.25; cy3 := (3 * y1 + y2) * 0.25; cx4 := (x1 + x2) * 0.5; cy4 := (y1 + y2) * 0.5; chaikin_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); cx1 := cx4; cy1 := cy4; cx2 := (x1 + 3 * x2) * 0.25; cy2 := (y1 + 3 * y2) * 0.25; p:= p^.next; end {while}; writeln(cx1:6:4, ' ', cy1:6:4, ' moveto'); writeln(x2:6:4, ' ', y2:6:4, ' lineto'); writeln(' stroke'); if style <> SOLID_LINE then begin writeln('[] 0 setdash'); end { if }; if f_arrow = 1 then begin { forward arrow } writeln('newpath'); writeln(x1:6:4, ' ', y1:6:4, ' ', x2:6:4, ' ', y2:6:4, ' ', arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end { if }; end {with}; end { draw_openspline }; procedure draw_closedspline (spl : tSpline); var cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4 : real; x1, y1, x2, y2 : real; p : pPoint; begin with spl do begin writeln('newpath'); if style <> SOLID_LINE then begin writeln('[3] 0 setdash'); end { if }; p:= start; x1 := p^.x; y1 := p^.y; p := p^.next; x2 := p^.x; y2 := p^.y; cx1 := (x1 + x2) * 0.5; cy1 := (y1 + y2) * 0.5; cx2 := (x1 + 3 * x2) * 0.25; cy2 := (y1 + 3 * y2) * 0.25; writeln(cx1:6:4, ' ', cy1:6:4, ' moveto'); p:= p^.next; while p <> nil do begin x1 := x2; y1 := y2; x2 := p^.x; y2 := p^.y; cx3 := (3 * x1 + x2) * 0.25; cy3 := (3 * y1 + y2) * 0.25; cx4 := (x1 + x2) * 0.5; cy4 := (y1 + y2) * 0.5; chaikin_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); cx1 := cx4; cy1 := cy4; cx2 := (x1 + 3 * x2) * 0.25; cy2 := (y1 + 3 * y2) * 0.25; p:= p^.next; end {while}; x1 := x2; y1 := y2; p := start^.next; x2 := p^.x; y2 := p^.y; cx3 := (3 * x1 + x2) * 0.25; cy3 := (3 * y1 + y2) * 0.25; cx4 := (x1 + x2) * 0.5; cy4 := (y1 + y2) * 0.5; chaikin_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); writeln(' stroke'); if style <> SOLID_LINE then begin writeln('[] 0 setdash'); end { if }; end {with}; end { draw_closedspline }; begin with Object^ do begin case objname of ellipse : with ell do begin writeln('gsave'); if current_thickness <> thickness then begin writeln(thickness, ' setlinewidth'); current_thickness:= thickness; end { if }; if style <> SOLID_LINE then begin writeln('[3] 0 setdash'); end { if }; writeln('newpath'); writeln('/savematrix matrix currentmatrix def'); writeln(center.x, center.y,' translate'); writeln(radiuses.x, radiuses.y, ' scale'); writeln('0 0 1 0 360 arc'); writeln('savematrix setmatrix'); writeln('stroke'); writeln('grestore'); if style <> SOLID_LINE then begin writeln('[] 0 setdash'); end { if }; end {with}; polyline : with poly do begin if current_thickness <> thickness then begin writeln(thickness, ' setlinewidth'); current_thickness:= thickness; end { if }; p:= start; q:= nil; r:= nil; if (b_arrow = 1) then begin { generate backward arrow } if p <> nil then begin { at least 2 points available } q:= p^.next; writeln('newpath'); writeln(q^.x, q^.y, p^.x, p^.y, arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end else begin { line consists of only 1 point ! } message('warning: line with only 1 point!'); end { if }; end { if }; writeln('newpath'); if style <> SOLID_LINE then begin writeln('[3] 0 setdash'); end { if }; writeln(p^.x, p^.y,' moveto'); q:= p; p:= p^.next; while p <> nil do begin writeln(p^.x, p^.y,' lineto'); r:= q; q:= p; p:= p^.next; end {while}; writeln('stroke'); if style <> SOLID_LINE then begin writeln('[] 0 setdash'); end { if }; if f_arrow = 1 then begin { forward arrow } writeln('newpath'); writeln(r^.x, r^.y, q^.x, q^.y, arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end { if }; end {with}; spline : begin if spl.typ = DRAW_SPLINE then begin draw_openspline(spl); end else begin draw_closedspline(spl); end { if }; end {begin}; txt : with tex do begin write(corner.x, corner.y, height, length, ' ('); write_string(chars); writeln(') printtext'); end {with}; arc : with arq do begin if current_thickness <> thickness then begin writeln(thickness, ' setlinewidth'); current_thickness:= thickness; end { if }; if style <> SOLID_LINE then begin writeln('[3] 0 setdash'); end { if }; writeln('newpath'); radius:= sqrt((pos[1].x -center_x)*(pos[1].x- center_x)+ (pos[1].y -center_y)*(pos[1].y- center_y)); if direction=0 then begin {clockwise} writeln(pos[1].x, pos[1].y, ' moveto'); writeln(center_x:6:4, ' ', center_y:6:4, ' ', radius:6:4, ' ', (pos[1].y - center_y):6:4, ' ', (pos[1].x - center_x):6:4, ' atan ', (pos[3].y - center_y):6:4, ' ', (pos[3].x - center_x):6:4, ' atan arc'); end else begin {counter clockwise} writeln(pos[3].x, pos[3].y, ' moveto'); writeln(center_x:6:4, ' ', center_y:6:4, ' ', radius:6:4, ' ', (pos[3].y - center_y):6:4, ' ', (pos[3].x - center_x):6:4, ' atan ', (pos[1].y - center_y):6:4, ' ', (pos[1].x - center_x):6:4, ' atan arc'); end { if }; if style <> SOLID_LINE then begin writeln('[] 0 setdash'); end { if }; writeln('stroke'); if f_arrow=1 then begin if direction=0 then begin {clockwise} x0:= pos[3].x; y0:= pos[3].y; end else begin {counter clockwise} x0:= pos[1].x; y0:= pos[1].y; end { if }; calc_tangent(x, y, x0, y0, center_x, center_y, pos[2].x, pos[2].y); writeln('newpath'); writeln(x:6:4, ' ', y:6:4, x0, y0, arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end { if }; if b_arrow=1 then begin if direction=0 then begin {clockwise} x0:= pos[1].x; y0:= pos[1].y; end else begin {counter clockwise} x0:= pos[3].x; y0:= pos[3].y; end { if }; calc_tangent(x, y, x0, y0, center_x, center_y, pos[2].x, pos[2].y); writeln('newpath'); writeln(x:6:4,' ', y:6:4, x0, y0, arrow_width, arrow_height, ' arrowhead'); writeln('stroke'); end { if }; end {with}; otherwise { do nothing } end {case}; end {with}; end { generate }; procedure trailer; { Write Trailer. } begin writeln('showpage'); writeln('end % fig2psdict'); writeln('grestore'); end { trailer }; begin p:= Objects; current_dashlength:= maxint; current_thickness:= maxint; header; while p <> nil do begin generate(p); p:= p^.next; end {while}; trailer; end { generate_postscript }; begin {fig2ps} if argc <> 2 then message('usage: fig2ps filename > filename') else begin { get the filename, and open the file for reading } argv(1,filename); reset(input, filename); read_file(Objects); compute_bbox(Objects, llx, lly, urx, ury); generate_postscript(Objects, llx, lly, urx, ury); end; {if} end. {fig2ps}