summaryrefslogtreecommitdiff
path: root/graphics/MF-PS/epstomf/epstomf.awk
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/MF-PS/epstomf/epstomf.awk
Initial commit
Diffstat (limited to 'graphics/MF-PS/epstomf/epstomf.awk')
-rw-r--r--graphics/MF-PS/epstomf/epstomf.awk375
1 files changed, 375 insertions, 0 deletions
diff --git a/graphics/MF-PS/epstomf/epstomf.awk b/graphics/MF-PS/epstomf/epstomf.awk
new file mode 100644
index 0000000000..163a4ecd14
--- /dev/null
+++ b/graphics/MF-PS/epstomf/epstomf.awk
@@ -0,0 +1,375 @@
+# ---------------------------------------------------------------------------
+# This file belongs to the EPSTOMF package.
+# ---------------------------------------------------------------------------
+# You are entitled to do with the file whatever you wish. If you alter a file,
+# however, please remove the line containing the comment:
+#
+# `This file belongs to the EPSTOMF package.'
+#
+# in order to avoid mess.
+# ---------------------------------------------------------------------------
+# AUTHORS: B. Jackowski, P. Pianowski, M. Ry\'cko
+# HISTORY:
+# version 0.50: Tuesday, August 15th, 1995
+# * first less or more complete version
+# version 0.51: Monday, October 23rd, 1995
+# * comments adjusted to a new distribution
+# version 0.52: Monday, November 6th, 1995
+# * miter limit is a dimensionless quantity
+# version 0.53: Wednesday, March 19th, 1997
+# * degenerated (single-node) paths used to be processed improperly
+# * font dimens specified explicitly
+# * `plain' option added (a METAFONT code without referring to the
+# MFTOEPS package is generated if variable `plain' is set to 1)
+# version 0.54: Thursday, January 29th, 1998
+# * this and previous versions were stimulated (stipulated in fact :-)
+# by Samy Alex Za\"\i{}mi -- thanks!
+# * all kinds of end-of-line characters are accepted in
+# input files; this, however, necessitates using Gnu AWK
+# * a patch was added to cope (somehow) with PageDraw's (ver. 2.0)
+# EPSes that do not conform to the definition of a ``canonical''
+# EPS given below, nonetheless, they are ``nearly canonical''
+# and something can be done
+# * in order to avoid annoying gftodvi's messages
+# ``Too many labels'' and ``Too many labels and/or rules''
+# the command |labels| is preceded by a percent sign if
+# suspiciously many nodes occur
+# ---------------------------------------------------------------------------
+# This is an AWK program for the translation of a ``canonical'' (see below)
+# EPS file into METAFONT lingo; the resulting METAFONT program inputs MFTOEPS
+# macros (ver. >= 0.61). EPS files created using the MFTOEPS package are
+# accepted by this converter.
+# ---
+# The crucial features of a ``canonical'' EPS file are listed below:
+# 0. General assumptions:
+# a) parameters of a command appear in one line along with the command;
+# b) only explicit numerical values are admissible (variables are not
+# interpreted);
+# c) all numbers are expressed in PostScript points (called in TeX
+# ``big points'': 1/72in), i.e., no local transformations are involved;
+# d) prior to painting a curve (fill or stroke) its parameters
+# for filling or stroking are explicitly set;
+# e) only the commands listed in items 1--11 are interpreted.
+# 1. `gsave' and `grestore' are represented by `q' and `Q', respectively;
+# malformed grouping structure may yield unpredictable results.
+# 2. `moveto' is represented by `m'.
+# 3. `lineto' is represented by either `l' or `L'.
+# 4. `curveto' is represented by either `c' or `C'.
+# 5. `setlinewidth' is represented by `w'.
+# 6. `setlinejoin' is represented by `j'.
+# 7. `setlinecap' is represented by `J'.
+# 8. `setmiterlimit' is represented by `M'.
+# 9. `setdash' is represented by `d'.
+# 10. Curves start with `*u' and end with `*U'; no `q'/`Q' commands are
+# expected to occur inside a curve, i.e., between `*u' and `*U' commands;
+# `q'/`Q' pairs occuring outside a curve, i.e., between `*U' and `*u'
+# commands, are ignored; actually, the latter situation should not
+# occur either.
+# 11. Component paths of a multi-path curve end consistently either
+# with `f' (filling), or `s'/`S' (stroking of closed and open paths,
+# resp.), or `h W n' (clipping; in fact, only `n' is taken taken into
+# account).
+# 12. Structural comments `%%BoundingBox' and `%%EndSetup' should occur at
+# the beginning of the file (in this order).
+# ---
+# COMMENTS:
+# 1. The engine works in such a way that at first a necessary information
+# about paths is collected; during this stage only the coordinates of
+# nodes are written; after processing all the data the ``painting'' code
+# is generated; this complicates the AWK code a bit due to controlling
+# `gsave'/`grestore' nesting; a simplified approach is used: instead of
+# recording the full nesting tree, a ``backbone'' of a nesting structure
+# is reconstructed (cf. item 10 above).
+# 2. A little bit more complicated (in comparison with other commands) is
+# the translation of `d' (`setdash') command; in addition to the
+# assumptions specified above, it is assumed that at least one space
+# precedes `[' and `d', and follows `]'.
+# 3. Some complexity is also involved at the METAFONT level at the stage of
+# computing of a bounding box; as a default, the graphic object is shifted
+# such that the left lower corner of the bounding box coincides with
+# the origin of the coordinate system; by manual alteration of the
+# resulting METAFONT file the user can easily control the situation, e.g.,
+# vertical or horizontal shift (or both) can be prohibited, the original
+# bounding box can be preserved, etc.; one should also remember that
+# if clipping is involved, the computed bounding box may be invalid.
+# 4. Due to rounding errors the original EPS file and the EPS file generated
+# from a resulting METAFONT file may differ.
+# ---------------------------------------------------------------------------
+BEGIN {
+ skipping=1
+ path_max=0
+ group_max=0
+ node_max=0
+ xl=0; yl=0; xh=72; yh=72; # emergency default
+# `q'/`Q' nesting is controled by the following three variables
+# (`ignore_grestore' controls ignoring `q'/`Q' pairs between curves):
+ nesting_level=0; nesting_group=0; ignore_grestore=0
+ RS="\015|\012|\015\012"
+}
+# ---
+(skipping==1) && ($0 ~ /^%%BoundingBox:/) {xl=$2; yl=$3; xh=$4; yh=$5}
+# ---
+(skipping==1) && $0=="%%EndSetup" {skipping=0;
+ print "%%% fill fill_C draw_C clip_C set_BB find_BB close_path"
+ print "%%% fill fix_fill_cmyk fix_draw_cmyk"
+ print "%%% fill fix_line_width fix_line_join fix_line_cap"
+ print "%%% fill fix_miter_limit fix_dash"
+ print "%%% message write_preamble"
+ print "%%% endchar write_postamble g_save g_restore"
+ print "%%% addto ~"
+ print "%%\\input mftform"
+ if (!plain) print "input mftoeps;"
+ print "numeric w#, h#, d#, xl#, yl#, xh#, yh#, xs#, ys#;"
+ print "xl#=" xl "bp#; yl#=" yl "bp#; xh#=" xh "bp#; yh#=" yh "bp#;";
+ print "if false: noxs:=0; fi % no horizontal shift, ignored by default"
+ print "if false: noys:=0; fi % no vertical shift, ignored by default"
+ if (!plain) {
+ print "if false: oribb:=0; fi",
+ "% preserving the original bounding box, ignored by default"
+ print "pinbb:=0; % default: shifting the object such that |(xl,yl)=(0,0)|"
+ }
+ print "xs#=if known noxs: 0 else: -xl# fi;"
+ print "ys#=if known noys: 0 else: -yl# fi;"
+ print "w#=max(0,xh#+xs#); h#=max(0,yh#+ys#); d#=max(0,-yl#-ys#);"
+ print "%"
+ fn=FILENAME; gsub(/^.*[\/\\]/,"",fn); gsub(/\.[^\/\\]*$/,"",fn)
+ print "font_identifier:=\"" fn "\";";
+ print "font_size round(w#);"
+ print "font_slant 0;"
+ print "font_normal_space w#;"
+ print "font_normal_stretch 0;"
+ print "font_normal_shrink 0;"
+ print "font_x_height h#;"
+ print "font_quad w#;"
+ print "font_extra_space 0;"
+ print "message \"The font size = \" & decimal(designsize) & \"pt#\";"
+ print "message \"\";"
+ print "%"
+ if (!plain) print "extra_eps_setup:=\"pixels_per_inch:=72\";",
+ "% better resolution for this case"
+ print (plain ? "" : "eps_") "mode_setup; define_pixels(xs, ys);"
+ print "%"
+ print "def ~ text xy = \\\\ = (bp*xpart(xy)+xs,bp*ypart(xy)+ys) enddef;"
+ print "%%% step C B L M"
+ print "def M = M_ ( enddef;"
+ print "def M_(suffix $) = z$ enddef;"
+ print "def B = ) B_ ( enddef;"
+ print "def B_(suffix $) = .. controls z$a and z$b .. z$ enddef;"
+ print "def L = ) L_ ( enddef;"
+ print "def L_(suffix $) = -- z$ enddef;"
+ print "def C = ) enddef;"
+ print "def close_path suffix p ="
+ print " p:=p if (point 0 of p)=(point length(p) of p): & else: -- fi cycle;"
+ print "enddef;"
+ print "%%% labels B L M"
+ print "%%% fi C"
+ if (plain) {
+ print "% ---"
+ print "def eofill expr P ="
+ print " begingroup save pp_; picture pp_;"
+ print " interim turningcheck:=0;"
+ print "% the following |addto|s are supposed to fill disjoint areas:"
+ print " pp_:=nullpicture; addto pp_ contour P.t_;"
+ print " cull pp_ keeping (1,infinity); addto currentpicture also pp_;"
+ print " pp_:=nullpicture; addto pp_ contour reverse P.t_;"
+ print " cull pp_ keeping (1,infinity); addto currentpicture also pp_;"
+ print " cull currentpicture keeping(1,1);"
+ print " endgroup"
+ print "enddef;"
+ print "def fill_C text t ="
+ print " begingroup"
+ print " save rr_; picture rr_; % must not be |pp_| (see |eofill|)"
+ print " begingroup"
+ print " save currentpicture; def currentpicture = rr_ enddef; % danger!"
+ print " currentpicture:=nullpicture; for qq_:=t: eofill qq_; endfor"
+ print " endgroup;"
+ print " addto currentpicture also rr_; cullit;"
+ print " endgroup"
+ print "enddef;"
+ print "def draw_C text t = for pp_:=t: draw pp_; endfor enddef;"
+ print "def clip_C text t = enddef;"
+ }
+ print "% ---"
+ print "beginchar("0",w#,h#,d#); path p[\\\\];"
+}
+# ---
+skipping==0 {
+ for (i=1; i<=NF; i+=1) {
+# ---
+ if ($i=="q") {++nesting_level; ++ignore_grestore}
+# ---
+ if ($i=="Q") {
+ --nesting_level
+ if (ignore_grestore>0) {--ignore_grestore} else {++nesting_group}
+ }
+# ---
+ if ($i=="*u") {
+ print ""; print "% BEGIN of GROUP", group_max ";"
+ ignore_grestore=0; first_path[group_max]=path_max
+ }
+# ---
+ if ($i=="k") {
+ fix_fill_cmyk[group_max]=$(i-4) "," $(i-3) "," $(i-2) "," $(i-1)
+ }
+# ---
+ if ($i=="K") {
+ fix_draw_cmyk[group_max]=$(i-4) "," $(i-3) "," $(i-2) "," $(i-1)
+ }
+# ---
+ if ($i=="w") fix_line_width[group_max]=$(i-1) "bp"
+# ---
+ if ($i=="j") fix_line_join[group_max]=$(i-1)
+# ---
+ if ($i=="J") fix_line_cap[group_max]=$(i-1)
+# ---
+ if ($i=="M") fix_miter_limit[group_max]=$(i-1)
+# ---
+ if ($i=="d") {# this is a little bit more complex case (see comment 2)
+ l=i-2; # $(i-1)="d", $(i-1) is the offset
+ for (j=l; $j !~ /\[/; --j) {}
+# $j contains the opening bracket for `setdash'
+# $l contains the closing bracket for `setdash'
+ gsub(/\[/,"",$j); gsub(/\]/,"",$l) # delete both brackets
+ was_something=0
+ fix_dash[group_max]="("; # construct parameters for `fix_dash'
+ for (k=j; k<=l; ++k) {
+ if ($k != "") {
+ if (was_something==1) {aux=","} else {was_something=1; aux=""}
+ fix_dash[group_max]=fix_dash[group_max] aux $k "bp"
+ }
+ }
+ fix_dash[group_max]=fix_dash[group_max] ") " $(i-1) "bp"
+ }
+# ---
+ if ($i=="m") {
+ print "% begin of path", path_max ";"
+ print "%%\\BMU\\COLS"
+ print "z" node_max "~" $(i-2) "," $(i-1) ";"
+ node_path[node_max]=path_max; first_node[path_max]=node_max; ++node_max
+ }
+# ---
+ if (($i=="l") || ($i=="L")) {
+ print "z" node_max "~" $(i-2) "," $(i-1) ";"
+ node_path[node_max]=path_max; arc_type[node_max]="L"; ++node_max
+ }
+# ---
+ if (($i=="c") || ($i=="C")) {
+ print "z" node_max "a~" $(i-6) "," $(i-5) ";"
+ print "z" node_max "b~" $(i-4) "," $(i-3) ";"
+ print "z" node_max "~" $(i-2) "," $(i-1) ";"
+ node_path[node_max]=path_max; arc_type[node_max]="B"; ++node_max
+ }
+# ---
+ if (($i=="f") || ($i=="s") || ($i=="S") || ($i=="n")) {
+ print "%%\\EMU";
+ path_group[path_max]=group_max; last_node[path_max]=node_max-1;
+ group_type[group_max]=$i; # should be consistent for all paths in a group
+ if (($i=="f") || ($i=="s") || ($i=="n")) is_closed_path=1
+ else is_closed_path=0
+ aux="p" path_max "=M" first_node[path_max]
+ if (first_node[path_max]<last_node[path_max])
+ for (j=first_node[path_max]+1; j<=last_node[path_max]; ++j) {
+ aux=aux " " arc_type[j] j
+ if (j==last_node[path_max]) aux=aux " C;"
+ if (length(aux)>70) {print aux; aux=""}
+ } else aux=aux " C;" # degenerated case
+ if (aux!="") print aux
+ if (is_closed_path==1) print "close_path p" path_max ";"
+ print "% end of path", path_max ";"
+ ++path_max
+ }
+# ---
+ if ($i=="*U") {
+ print "% END of GROUP", group_max ";";
+ group_nesting_level[group_max]=nesting_level;
+ group_nesting_group[group_max]=nesting_group;
+ last_path[group_max]=path_max-1;
+ ++group_max
+ }
+ }
+}
+# ---
+END {
+ node_max--
+ path_max--
+ group_max--
+# ---
+ if (!plain) {
+ print ""
+ print "if known oribb:"
+ print " set_BB " xl "bp+xs," yl "bp+ys," xh "bp+xs," yh "bp+ys;"
+ print "elseif known pinbb:"
+ print " find_BB p0 for i:=1 upto " path_max": , p[i] endfor;"
+ print " for i:=0 upto " node_max":"
+ print " x[i]:=x[i]-xl_crd; y[i]:=y[i]-yl_crd;"
+ print " if known x[i]a: x[i]a:=x[i]a-xl_crd; fi"
+ print " if known x[i]b: x[i]b:=x[i]b-xl_crd; fi"
+ print " if known y[i]a: y[i]a:=y[i]a-yl_crd; fi"
+ print " if known y[i]b: y[i]b:=y[i]b-yl_crd; fi"
+ print " endfor"
+ print " for i:=0 upto " path_max": p[i]:=p[i] shifted -llxy; endfor"
+ print " set_BB origin, urxy-llxy;"
+ print "else:"
+ print " find_BB p0 for i:=1 upto " path_max": , p[i] endfor;"
+ print "fi"
+ print "write_preamble jobname;"
+ }
+# ---
+# one extra `gsave'/`grestore' pair is always added by MFTOEPS, hence `-2'
+ if (!plain) for (j=0; j<=group_nesting_level[0]-2; ++j) {print "g_save;"}
+ for (g=0; g<=group_max; ++g) {
+ if (plain) {
+ if (fix_line_width[g]!="")
+ print "pickup pencircle scaled " fix_line_width[g] ";"
+ } else {
+ if (g>0) {
+ k=group_nesting_group[g]-group_nesting_group[g-1];
+ # k == number of groups closed in the meantime
+ for (j=1; j<=k; ++j) print "g_restore;"
+ k=group_nesting_level[g-1]-k; l=group_nesting_level[g];
+ # k == current nesting level, l == resulting nesting level
+ for (j=1; j<=(k-l); ++j) print "g_restore;"
+ for (j=-1; j>=(k-l); --j) print "g_save;"
+ }
+ if (fix_fill_cmyk[g]!="") print "fix_fill_cmyk " fix_fill_cmyk[g] ";"
+ if (fix_draw_cmyk[g]!="") print "fix_draw_cmyk " fix_draw_cmyk[g] ";"
+ if (fix_line_width[g]!="") print "fix_line_width " fix_line_width[g] ";"
+ if (fix_line_join[g]!="") print "fix_line_join " fix_line_join[g] ";"
+ if (fix_line_cap[g]!="") print "fix_line_cap " fix_line_cap[g] ";"
+ if (fix_miter_limit[g]!="") print "fix_miter_limit " fix_miter_limit[g] ";"
+ if (fix_dash[g]!="") print "fix_dash " fix_dash[g] ";"
+ }
+ if (group_type[g]=="f") aux="fill_C"
+ if ((group_type[g]=="s") || (group_type[g]=="S")) aux="draw_C"
+ if (group_type[g]=="n") aux="clip_C"
+ for (j=first_path[g]; j<=last_path[g]; ++j) {
+ aux=aux " p" j (j==last_path[g] ? ";" : ",")
+ if (length(aux)>70) {print aux; aux=""}
+ }
+ if (aux!="") print aux
+ }
+# ---
+ if ((group_max<0) && (path_max>0)) {
+# something went wrong (non-conforming EPS?);
+# let's undertake a desperate defense of the nearly wasted task:
+ g=0; aux="fill_C" # emergency initialization
+ if (group_type[g]=="f") aux="fill_C"
+ if ((group_type[g]=="s") || (group_type[g]=="S")) aux="draw_C"
+ if (group_type[g]=="n") aux="clip_C"
+ for (j=0; j<=path_max; ++j) {
+ aux=aux " p" j (j==path_max ? ";" : ",")
+ if (length(aux)>70) {print aux; aux=""}
+ }
+ if (aux!="") print aux
+ }
+# ---
+# one extra `gsave'/`grestore' pair is always added by MFTOEPS, hence `-2'
+ for (j=0; j<=group_nesting_level[group_max]-2; ++j) print "g_restore;"
+ if (!plain) print "write_postamble;"
+ # not to many nodes please (otherwise gftodvi is likely to break down):
+ print (node_max>800 ? "% " : "") "labels(range" 1 "thru" node_max ");"
+ print "endchar;"
+ print "% ---"
+ print "end."
+ print "%%\\end"
+}