diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /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.awk | 375 |
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" +} |