diff options
Diffstat (limited to 'metapost')
-rw-r--r-- | metapost/context/base/metafun.mpiv | 5 | ||||
-rw-r--r-- | metapost/context/base/mp-bare.mpiv | 93 | ||||
-rw-r--r-- | metapost/context/base/mp-base.mpii | 19 | ||||
-rw-r--r-- | metapost/context/base/mp-base.mpiv | 95 | ||||
-rw-r--r-- | metapost/context/base/mp-chem.mpiv | 115 | ||||
-rw-r--r-- | metapost/context/base/mp-form.mpiv | 2 | ||||
-rw-r--r-- | metapost/context/base/mp-func.mpiv | 33 | ||||
-rw-r--r-- | metapost/context/base/mp-grap.mpiv | 336 | ||||
-rw-r--r-- | metapost/context/base/mp-luas.mpiv | 99 | ||||
-rw-r--r-- | metapost/context/base/mp-mlib.mpiv | 571 | ||||
-rw-r--r-- | metapost/context/base/mp-page.mpiv | 522 | ||||
-rw-r--r-- | metapost/context/base/mp-tool.mpii | 2683 | ||||
-rw-r--r-- | metapost/context/base/mp-tool.mpiv | 218 | ||||
-rw-r--r-- | metapost/context/fonts/bidi-symbols.tex | 3 |
14 files changed, 2936 insertions, 1858 deletions
diff --git a/metapost/context/base/metafun.mpiv b/metapost/context/base/metafun.mpiv index a113675e6..b1d4f32e7 100644 --- a/metapost/context/base/metafun.mpiv +++ b/metapost/context/base/metafun.mpiv @@ -15,10 +15,14 @@ %D prevent dependency problems and in the end even may use a patched version, %D we prefer to use a copy. +prologues := 0 ; +mpprocset := 1 ; + input "mp-base.mpiv" ; input "mp-tool.mpiv" ; input "mp-mlib.mpiv" ; % "mp-core.mpiv" ; % todo: namespace and cleanup +input "mp-luas.mpiv" ; % experimental input "mp-page.mpiv" ; % todo: namespace and cleanup input "mp-butt.mpiv" ; % todo: namespace and cleanup input "mp-shap.mpiv" ; % will be improved @@ -46,6 +50,7 @@ let normalend = end ; if known mplib : def end = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; + def bye = ; message "" ; message metafunversion ; message "" ; endinput ; enddef ; else : def end = ; message "" ; message metafunversion ; message "" ; normalend ; enddef ; fi ; diff --git a/metapost/context/base/mp-bare.mpiv b/metapost/context/base/mp-bare.mpiv new file mode 100644 index 000000000..c6194b1ee --- /dev/null +++ b/metapost/context/base/mp-bare.mpiv @@ -0,0 +1,93 @@ +%D \module +%D [ file=mp-bare.mpiv, +%D version=2014.10.31, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=plain plugins, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See licen-en.pdf for +%C details. + +if known context_bare : endinput ; fi ; +boolean context_bare ; context_bare := true ; + +numeric mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; +numeric mfun_tt_n ; mfun_tt_n := 0 ; +picture mfun_tt_p ; mfun_tt_p := nullpicture ; +picture mfun_tt_o ; mfun_tt_o := nullpicture ; +picture mfun_tt_c ; mfun_tt_c := nullpicture ; + +if unknown mfun_trial_run : + boolean mfun_trial_run ; + mfun_trial_run := false ; +fi ; + +if unknown mfun_first_run : + boolean mfun_first_run ; + mfun_first_run := true ; +fi ; + +def mfun_reset_tex_texts = + mfun_tt_n := 0 ; + mfun_tt_p := nullpicture ; + mfun_tt_o := nullpicture ; % redundant + mfun_tt_c := nullpicture ; % redundant +enddef ; + +def mfun_flush_tex_texts = + addto currentpicture also mfun_tt_p +enddef ; + +extra_beginfig := extra_beginfig & "mfun_reset_tex_texts ;" ; +extra_endfig := "mfun_flush_tex_texts ; mfun_reset_tex_texts ; " & extra_endfig ; + +vardef colordecimals primary c = + if cmykcolor c : + decimal cyanpart c & ":" & decimal magentapart c & ":" & decimal yellowpart c & ":" & decimal blackpart c + elseif rgbcolor c : + decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c + else : + decimal c + fi +enddef ; + +vardef rawtextext(expr str) = % todo: avoid currentpicture + if str = "" : + nullpicture + else : + mfun_tt_n := mfun_tt_n + 1 ; + mfun_tt_c := nullpicture ; + if mfun_trial_run : + mfun_tt_o := nullpicture ; + addto mfun_tt_o doublepath origin _op_ ; % save drawoptions + addto mfun_tt_c doublepath unitsquare + withprescript "tx_number=" & decimal mfun_tt_n + withprescript "tx_stage=trial" + withprescript "tx_color=" & colordecimals colorpart mfun_tt_o + withpostscript str ; + addto mfun_tt_p also mfun_tt_c ; + elseif known mfun_tt_d[mfun_tt_n] : + addto mfun_tt_c doublepath unitsquare + xscaled mfun_tt_w[mfun_tt_n] + yscaled (mfun_tt_h[mfun_tt_n] + mfun_tt_d[mfun_tt_n]) + shifted (0,-mfun_tt_d[mfun_tt_n]) + withprescript "tx_number=" & decimal mfun_tt_n + withprescript "tx_stage=final" ; + else : + addto mfun_tt_c doublepath unitsquare ; % unitpicture + fi ; + mfun_tt_c + fi +enddef ; + +primarydef str infont name = % nasty hack + if name = "" : + rawtextext(str) + else : + rawtextext("\definedfont[" & name & "]" & str) + fi +enddef ; + diff --git a/metapost/context/base/mp-base.mpii b/metapost/context/base/mp-base.mpii index 0f8104447..7af4bc436 100644 --- a/metapost/context/base/mp-base.mpii +++ b/metapost/context/base/mp-base.mpii @@ -110,12 +110,15 @@ transform identity; for z=origin,right,up: z transformed identity = z; endfor % color constants -color black, white, red, green, blue, background; +color black, white, red, green, blue, cyan, magenta, yellow, background; black = (0,0,0); white = (1,1,1); red = (1,0,0); green = (0,1,0); blue = (0,0,1); +cyan = (0,1,1); +magenta = (1,0,1); +yellow = (1,1,0); background = white; % The user can reset this % color part selection for within @@ -360,9 +363,17 @@ enddef; def filldraw expr c = addto currentpicture contour c withpen currentpen _op_ enddef; -def drawdot expr z = - addto currentpicture contour makepath currentpen shifted z - _op_ enddef; +% def drawdot expr z = +% addto currentpicture contour makepath currentpen shifted z +% _op_ enddef; + +def drawdot expr p = + if pair p : + addto currentpicture doublepath p withpen currentpen _op_ + else : + errmessage("drawdot only accepts a pair expression") + fi +enddef ; def unfill expr c = fill c withcolor background enddef; def undraw expr p = draw p withcolor background enddef; diff --git a/metapost/context/base/mp-base.mpiv b/metapost/context/base/mp-base.mpiv index 2887cc462..28eb57fb8 100644 --- a/metapost/context/base/mp-base.mpiv +++ b/metapost/context/base/mp-base.mpiv @@ -195,7 +195,8 @@ yellow := (1,1,0) ; background := white ; % obsolete let graypart = greypart ; -let graycolor = greycolor ; +let greycolor = numeric ; +let graycolor = numeric ; % color part (will be overloaded) @@ -323,7 +324,7 @@ primarydef w dotprod z = enddef ; primarydef x**y = - if y=2 : + if y = 2 : x*x else : takepower y of x @@ -348,11 +349,46 @@ def takepower expr y of x = endfor fi else : - hide(errmessage "Undefined power: " & decimal x&"**"&decimal y) + hide(errmessage "Undefined power: " & decimal x & "**" & decimal y) fi fi enddef ; +% for big number systems: +% +% primarydef x**y = +% if y = 1 : +% x +% elseif y = 2 : +% x*x +% elseif y = 3 : +% x*x*x +% else : +% takepower y of x +% fi +% enddef ; +% +% vardef takepower expr y of x = +% if (x=0) and (y>0) : +% 0 +% else : +% 1 +% if y = floor y : +% if y >= 0 : +% for n=1 upto y : +% *x +% endfor +% else : +% for n=-1 downto y : +% /x +% endfor +% fi +% else : +% hide(errmessage "Undefined power: " & decimal x & "**" & decimal y) +% fi +% fi +% enddef ; + vardef direction expr t of p = postcontrol t of p - precontrol t of p enddef ; @@ -594,8 +630,36 @@ def filldraw expr c = addto currentpicture contour c withpen currentpen _op_ enddef ; -def drawdot expr z = - addto currentpicture contour makepath currentpen shifted z _op_ +% def drawdot expr z = +% addto currentpicture contour makepath currentpen shifted z _op_ +% enddef ; +% +% testcase DEK: +% +% for j=1 upto 9 : +% pickup pencircle xscaled .4 yscaled .2 ; +% drawdot (10j,0) withpen pencircle xscaled .5j yscaled .25j rotated 45 ; +% pickup pencircle xscaled .5j yscaled .25j rotated 45 ; +% drawdot (10j,10); +% endfor ; +% +% or: +% +%\startMPpage +% +% def drawdot expr z = +% addto currentpicture contour (makepath currentpen shifted z) _op_ +% enddef; +% +% drawdot origin shifted (0,-3cm) withpen pencircle scaled 2cm ; +% pickup pencircle scaled 2cm ; drawdot origin withcolor red ; + +def drawdot expr p = + if pair p : + addto currentpicture doublepath p withpen currentpen _op_ + else : + errmessage("drawdot only accepts a pair expression") + fi enddef ; def unfill expr c = fill c withcolor background enddef ; @@ -651,10 +715,10 @@ enddef ; def pen_pickup_ primary q = currentpen := q ; - pen_lft :=xpart penoffset down of currentpen ; - pen_rt :=xpart penoffset up of currentpen ; - pen_top :=ypart penoffset left of currentpen ; - pen_bot :=ypart penoffset right of currentpen ; + pen_lft := xpart penoffset down of currentpen ; + pen_rt := xpart penoffset up of currentpen ; + pen_top := ypart penoffset left of currentpen ; + pen_bot := ypart penoffset right of currentpen ; path currentpen_path ; enddef ; @@ -670,7 +734,8 @@ vardef savepen = pen_count_ enddef ; -def clearpen = currentpen:=nullpen; +def clearpen = + currentpen := nullpen; pen_lft := pen_rt := pen_top := pen_bot := 0 ; path currentpen_path ; enddef ; @@ -801,7 +866,7 @@ vardef labels@#(text t) = endfor enddef ; -% til lhere +% till lhere vardef dotlabels@#(text t) = forsuffixes $=t: @@ -817,17 +882,19 @@ vardef penlabels@#(text t) = endfor enddef ; +% range 4 thru 10 + def range expr x = - numtok[x] + _numtok_[x] enddef ; -def numtok suffix x = +def _numtok_ suffix x = x enddef ; tertiarydef m thru n = m for x=m+1 step 1 until n : - , numtok[x] + , _numtok_[x] endfor enddef ; diff --git a/metapost/context/base/mp-chem.mpiv b/metapost/context/base/mp-chem.mpiv index 2addb0a73..b861d3f12 100644 --- a/metapost/context/base/mp-chem.mpiv +++ b/metapost/context/base/mp-chem.mpiv @@ -11,7 +11,8 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -%D This module is incomplete and experimental. +%D This module is incomplete and experimental. Okay, it's not that bad but we do need +%D some disclaimer. % either consistent setting or not @@ -24,7 +25,7 @@ numeric chem_text_min, chem_text_max, chem_rotation, chem_adjacent, chem_stack_n, chem_substituent, chem_substituent.lft, chem_substituent.rt, - chem_setting_offset, chem_text_offset, chem_picture_offset, + chem_setting_offset, chem_text_offset, chem_center_offset, chem_dbl_offset, chem_bb_angle, chem_axis_rulethickness, chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b, @@ -72,19 +73,18 @@ chem_axis_rulethickness := 1pt ; chem_emwidth := 10pt ; % EmWidth or \the\emwidth does not work... chem_b_length := 3 chem_emwidth ; chem_text_offset := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2) -chem_center_offset := .5 chem_emwidth ; -chem_picture_offset := chem_emwidth ; +chem_center_offset := .5chem_emwidth ; chem_dbl_offset := .05 ; chem_bb_angle := angle(1,2chem_dbl_offset) ; chem_text_min := 0.75 ; chem_text_max := 1.25 ; -chem_dot_factor := 4 ; % *linewidth +chem_dot_factor := 2 ; % *linewidth chem_sb_pair := (0.25,0.75) ; %chem_sb_dash := dashpattern(off 0.25 on 0.5 off 0.25) ; chem_sb_pair.m := (0.25,1 ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ; chem_sb_pair.p := (0 ,0.75) ; %chem_sb_dash.p := dashpattern(on 0.75 off 0.25) ; -chem_sb_pair.b := (0, 1 ) ; %chem_sb_dash.b := dashpattern(on 1) ; +chem_sb_pair.b := (0 ,1 ) ; %chem_sb_dash.b := dashpattern(on 1) ; -chem_bd_wedge := false ; % true is incorrect, but quite common... +chem_bd_wedge := true ; % according to IUPAC 2005 def chem_reset = chem_rotation := 0 ; @@ -132,6 +132,8 @@ vardef chem_init_some (suffix $) (expr e) = fi if not chem_star[$] : scaled (.5/(sind .5chem_num1)) + % carbon-carbon benzene bond length + scaled (1.4/1.54) fi ; fi ; @@ -149,7 +151,7 @@ vardef chem_init_some (suffix $) (expr e) = chem_num2 := i ; fi endfor) - scaled (2*(abs(point chem_num2+.5 of chem_b_path[$]) - chem_dbl_offset)) + scaled (2*(abs(point chem_num2+.5 of chem_b_path[$]) - 2chem_dbl_offset)) fi ; chem_r_path[$] := @@ -301,17 +303,20 @@ enddef ; chem_init_all ; % WHY does this not work unless defined and then called? - % Like most often in ConTeXt, we will trap but then silently ignore mistaken use, % unless of course the error be too harmful... % \startchemical -def chem_start_structure(expr i, l, r, t, b, rotation, unit, factor, offset, axis, rulethickness, axiscolor) = +def chem_start_structure(expr i, l, r, t, b, rotation, unit, bond, scale, offset, axis, rulethickness, axiscolor) = save chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ; - chem_emwidth := unit ; - chem_b_length := factor * unit ; + chem_emwidth := unit ; % dynamically set for each structure. + chem_text_offset := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2) + chem_center_offset := .5chem_emwidth ; + chem_b_length := chem_emwidth * bond * scale ; + % scale (normally 1) scales the structure but not the text. + if numeric l : chem_setting_l := -l ; fi @@ -526,6 +531,17 @@ vardef chem_set (suffix $) = % This is a fairly complicated optimization and ajustement. It took some % thinking to get right, so beware! + % And then even more time fixing a bug of a rotation +- half the symmetry + % angle of a structure depending on the scale and/or the font size + % (through chem_b_length). + + % first save the symmetry angle of the structure (as in chem_rot): + chem_num0 := if chem_stacked[$] : 3 else : 0 fi ; + chem_num9 := if chem_tetra[$] : 360 else : + abs(angle(point 0+chem_num0 of chem_b_path[$]) - + angle(point 1+chem_num0 of chem_b_path[$])) + fi ; + if (chem_adjacent<>0) and chem_star[P] and chem_star[$] : % nop chem_adjacent := 0 ; @@ -578,7 +594,8 @@ vardef chem_set (suffix $) = -((point (chem_adjacent-1) of chem_b_path[P]) chem_transformed(P)) ; fi % adjust the bond angles - chem_rotation := (chem_rotation + angle(chem_pair1)-angle(chem_pair3)) mod 360 ; + chem_num4 := (angle(chem_pair1)-angle(chem_pair3)) zmod chem_num9 ; + chem_rotation := chem_rotation + chem_num4 ; if not chem_star[$] : chem_pair4 := if chem_star[P] : @@ -663,7 +680,8 @@ vardef chem_set (suffix $) = fi endfor if not chem_front[$] : % adjust rotation - chem_rotation := (chem_rotation + angle(chem_pair1)-angle(chem_pair3)) mod 360 ; + chem_num4 := angle(chem_pair1)-angle(chem_pair3) ; + chem_rotation := (chem_rotation + chem_num4) mod 360 ; fi ; chem_t := identity chem_transformed($) ; chem_pair4 := (point chem_num3 of chem_b_path[$]) transformed chem_t ; @@ -671,6 +689,9 @@ vardef chem_set (suffix $) = currentpicture := currentpicture shifted chem_pair4 ; chem_origin := chem_origin shifted chem_pair4 ; fi + if not chem_front[$] : % adjust rotation + chem_rotation := chem_rotation zmod chem_num9 ; + fi fi chem_substituent := 0 ; fi ; @@ -798,28 +819,39 @@ vardef chem_eb@# (suffix $) (expr f, t, r, c) = % EB enddef ; vardef chem_ad@# (suffix $) (expr f, t, r, c) = % AD - if not chem_star[$] : - chem_t := identity chem_transformed($) ; - for i=f upto t : - chem_drawarrow( - ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) - paralleled 2chem_dbl_offset) transformed chem_t, - r,c,) ; - endfor - fi + chem_t := identity chem_transformed($) ; + for i=f upto t : + chem_drawarrow( + ( + (subpath + if chem_star[$] : + chem_sb_pair@# of chem_r_fragment($,i) + ) paralleled 5chem_dbl_offset + else : + (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] + ) paralleled 2chem_dbl_offset + fi + ) transformed chem_t, + r,c,) ; + endfor enddef ; vardef chem_au@# (suffix $) (expr f, t, r, c) = % AU - if not chem_star[$] : - chem_t := identity chem_transformed($) ; - for i=f upto t : - chem_drawarrow( - reverse( - (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) - paralleled 2chem_dbl_offset) transformed chem_t, - r,c,) ; - endfor - fi + chem_t := identity chem_transformed($) ; + for i=f upto t : + chem_drawarrow( + ((reverse + subpath + if chem_star[$] : + chem_sb_pair@# of chem_r_fragment($,i) + ) paralleled -5chem_dbl_offset + else : + (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] + ) paralleled -2chem_dbl_offset + fi + ) transformed chem_t, + r,c,) ; + endfor enddef ; vardef chem_es@# (suffix $) (expr f, t, r, c) = % ES @@ -1004,6 +1036,15 @@ enddef ; vardef chem_hb@# (suffix $) (expr f, t, r, c) = % HB if chem_star[$] : chem_rh@#($,f,t,r,c) + else : + chem_t := identity chem_transformed($) ; + for i=f upto t : + chem_draw( + (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) + transformed chem_t, + chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ; + % not symmetric - needs to be tweaked... + endfor fi enddef ; @@ -1548,9 +1589,9 @@ vardef chem_rot (suffix $) (expr d, s) = % ROT chem_rotation := 0 else : chem_num0 := if chem_stacked[$] : 3 else : 0 fi ; - chem_num1 := .5(angle(point d+chem_num0 of chem_b_path[$]) - + chem_num1 := .5(angle(point d+chem_num0 of chem_b_path[$]) - angle(point d+chem_num0-1 of chem_b_path[$])) ; - chem_rotation := (chem_rotation + s*chem_num1) mod 360 ; + chem_rotation := (chem_rotation + s*chem_num1) zmod 360 ; fi fi enddef ; @@ -1561,7 +1602,7 @@ vardef chem_mir (suffix $) (expr d, s) = % MIR if not chem_front[$] : if d=0 : % inversion if chem_mirror=origin : - chem_rotation := (chem_rotation + 180*s) mod 360 ; + chem_rotation := (chem_rotation + 180*s) zmod 360 ; else : chem_mirror := chem_mirror rotated 90 ; fi @@ -1577,7 +1618,7 @@ vardef chem_mir (suffix $) (expr d, s) = % MIR chem_num0 := -360 - chem_num0 ; fi chem_num0 := chem_num0 * s ; - chem_rotation := (chem_rotation + 2chem_num0) mod 360 ; + chem_rotation := (chem_rotation + 2chem_num0) zmod 360 ; chem_mirror := origin ; fi fi diff --git a/metapost/context/base/mp-form.mpiv b/metapost/context/base/mp-form.mpiv index b58792e1a..88b15e097 100644 --- a/metapost/context/base/mp-form.mpiv +++ b/metapost/context/base/mp-form.mpiv @@ -27,4 +27,4 @@ string Fmfont_ ; Fmfont_ := "crap" ; vardef mfun_format_number(expr fmt, i) = "\ctxlua{metapost.formatnumber('" & fmt & "'," & if string i : i else : decimal i fi & ")}" -enddef +enddef ; diff --git a/metapost/context/base/mp-func.mpiv b/metapost/context/base/mp-func.mpiv index 58df711f2..b1b9d6d5d 100644 --- a/metapost/context/base/mp-func.mpiv +++ b/metapost/context/base/mp-func.mpiv @@ -23,30 +23,36 @@ mfun_pathconnectors[0] := "," ; mfun_pathconnectors[1] := "--" ; mfun_pathconnectors[2] := ".." ; mfun_pathconnectors[3] := "..." ; +mfun_pathconnectors[4] := "---" ; def pathconnectors = mfun_pathconnectors enddef ; vardef mfun_function (expr f) (expr u, t, b, e, s) = save x ; numeric x ; + save c ; string c ; c := if string f : f else : mfun_pathconnectors[f] fi ; for xx := b step s until e : hide (x := xx ;) if xx > b : - scantokens(mfun_pathconnectors[f]) + scantokens(c) fi (scantokens(u),scantokens(t)) endfor enddef ; -def function = mfun_function enddef ; % let doesn't work here -def punkedfunction = mfun_function (1) enddef ; -def curvedfunction = mfun_function (2) enddef ; -def tightfunction = mfun_function (3) enddef ; +def function = mfun_function enddef ; % let doesn't work here +def constructedfunction = mfun_function enddef ; +def straightfunction = mfun_function (1) enddef ; +def curvedfunction = mfun_function (2) enddef ; + +% def punkedfunction = mfun_function (1) enddef ; % same as straightfunction +% def tightfunction = mfun_function (3) enddef ; % same as curvedfunction vardef mfun_constructedpath (expr f) (text t) = save ok ; boolean ok ; ok := false ; + save c ; string c ; c := if string f : f else : mfun_pathconnectors[f] fi ; for i=t : if ok : - scantokens(mfun_pathconnectors[f]) + scantokens(c) else : ok := true ; fi @@ -55,24 +61,27 @@ vardef mfun_constructedpath (expr f) (text t) = enddef ; def constructedpath = mfun_constructedpath enddef ; % let doesn't work here -def punkedpath = mfun_constructedpath (1) enddef ; +def straightpath = mfun_constructedpath (1) enddef ; def curvedpath = mfun_constructedpath (2) enddef ; -def tightpath = mfun_constructedpath (3) enddef ; + +% def punkedpath = mfun_constructedpath (1) enddef ; % same as straightpath +% def tightpath = mfun_constructedpath (3) enddef ; % same as curvedpath vardef mfun_constructedpairs (expr f) (text p) = save i ; i := -1 ; + save c ; string c ; c := if string f : f else : mfun_pathconnectors[f] fi ; forever : exitif unknown p[incr(i)] ; if i>0 : - scantokens(mfun_pathconnectors[f]) + scantokens(c) fi p[i] endfor enddef ; def constructedpairs = mfun_constructedpairs enddef ; % let doesn't work here -def punkedpairs = mfun_constructedpairs (1) enddef ; +def straightpairs = mfun_constructedpairs (1) enddef ; def curvedpairs = mfun_constructedpairs (2) enddef ; -def tightpairs = mfun_constructedpairs (3) enddef ; - +% def punkedpairs = mfun_constructedpairs (1) enddef ; % same as straightpairs +% def tightpairs = mfun_constructedpairs (3) enddef ; % same as curvedpairs diff --git a/metapost/context/base/mp-grap.mpiv b/metapost/context/base/mp-grap.mpiv index 417bfbe69..4fd8ee5bd 100644 --- a/metapost/context/base/mp-grap.mpiv +++ b/metapost/context/base/mp-grap.mpiv @@ -17,7 +17,10 @@ boolean context_grap ; context_grap := true ; % Below is a modified graph.mp -if epsilon/4 = 0 : % numbersystem="scaled" : (not reliable...) +show numbersystem, numberprecision ; + +%if epsilon/4 = 0 : +if numbersystem <> "double" : errmessage "The graph macros require the double precision number system." ; endinput ; fi @@ -52,11 +55,11 @@ fi % endgraph end of graph--the result is a picture % option `plot <picture>' draws picture at each path knot, turns off pen -% Gtemplate.<tickcmd> template paths for tick marks and grid lines +% graph_template.<tickcmd> template paths for tick marks and grid lines % graph_margin_fraction.low, % graph_margin_fraction.high fractions determining margins when no setrange -% Glmarks[], Gumarks, Gemarks loop text strings used by auto.<x or y> -% Gmarks, Gminlog numeric parameters used by auto.<x or y> +% graph_log_marks[], graph_lin_marks, graph_exp_marks loop text strings used by auto.<x or y> +% graph_minimum_number_of_marks, graph_log_minimum numeric parameters used by auto.<x or y> % Autoform is the format string used by autogrid % Autoform_X, Autoform_Y if defined, are used instead @@ -64,23 +67,27 @@ fi % are of the form X_.<suffix>, Y_.<suffix>, or Z_.<suffix>, or they start % with `graph_' -% Depends on : -input string.mp +% Used to depend on : + +% input string.mp % Private version of a few marith macros, fixed for double math... -newinternal Mzero; Mzero := -16384; % Anything at least this small is treated as zero -newinternal mlogten ; mlogten := mlog(10) ; -newinternal singleinfinity ; singleinfinity := 2**128 ; -newinternal doubleinfinity ; doubleinfinity := 2**1024 ; -% Note that we get arithmetic overflows if we set to -doubleinfinity below. -% (but "only on odd days"...) + +newinternal Mzero ; Mzero := -16384; % Anything at least this small is treated as zero +newinternal mlogten ; mlogten := mlog(10) ; +newinternal largestmantissa ; largestmantissa := 2**52 ; % internal double warningcheck +newinternal singleinfinity ; singleinfinity := 2**128 ; +newinternal doubleinfinity ; doubleinfinity := 2**1024 ; +%Mzero := -largestmantissa ; % Note that we get arithmetic overflows if we set to -doubleinfinity % Safely convert a number to mlog form, trapping zero. + vardef graph_mlog primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x) fi enddef ; + vardef graph_exp primary x = if unknown x: whatever elseif x<=Mzero: 0 @@ -89,21 +96,25 @@ enddef ; % and add the following for utility/completeness % (replacing the definitions in mp-tool.mpiv). + vardef logten primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x)/mlog(10) fi enddef ; + vardef ln primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x)/256 fi enddef ; + vardef exp primary x = if unknown x: whatever elseif x<= Mzero: 0 else: (mexp 256)**x fi enddef ; + vardef powten primary x = if unknown x: whatever elseif x<= Mzero: 0 @@ -112,6 +123,7 @@ enddef ; % Convert x from mlog form into a pair whose xpart gives a mantissa and whose % ypart gives a power of ten. + vardef graph_Meform(expr x) = if x<=Mzero : origin else : @@ -122,6 +134,7 @@ vardef graph_Meform(expr x) = enddef ; % Modified from above. + vardef graph_Feform(expr x) = interim warningcheck :=0 ; if x=0 : origin @@ -146,6 +159,7 @@ def graph_suffix(suffix $) = % convert from x or y to X_ or Y_ enddef ; % New : + save graph_background ; color graph_background ; % if defined, fill the frame. save graph_close_file ; boolean graph_close_file ; graph_close_file = false ; @@ -200,17 +214,20 @@ enddef ; % user to alter the behavior of these macros. % Not very modifiable : log, linear, % graph_frame_pair_a, graph_frame_pair_b, graph_margin_pair -% Modifiable : Gtemplate.suffix, Glmarks[], Gumarks, Gemarks, Gmarks, -% Gminlog, Autoform +% Modifiable : graph_template.suffix, +% graph_log_marks[], graph_lin_marks, graph_exp_marks, +% graph_minimum_number_of_marks, +% graph_log_minimum, Autoform newinternal log, linear ; % coordinate system codes log :=1 ; linear :=2; + % note that mp-tool.mpiv defines log as log10. %%%%%%%%%%%%%%%%%%%%%% Coordinates : setcoords, setrange %%%%%%%%%%%%%%%%%%%%%% -% Graph-related usr input is `user graph coordinates' as specified by arguments +% Graph-related user input is `user graph coordinates' as specified by arguments % to setcoords. % `Internal graph coordinates' are used for graph_current_graph, graph_current_bb, Z_.low, Z_.high. % Their meaning depends on the appropriate component of Z_.graph_coordinate_type : @@ -227,14 +244,15 @@ vardef graph_set_default_bounds = % Set default Z_.low, Z_.high graph_margin_pair$ ; endfor enddef ; + pair graph_margin_pair.low, graph_margin_pair.high ; graph_margin_pair.high = -graph_margin_pair.low = (.00002,.00002) ; +% Set $, $$, $$$ so that shifting by $ then transforming by $$ and then $$$ maps +% the essential bounding box of graph_current_graph into (0,0)..Z_.graph_dimensions. +% The `essential bounding box' is either what Z_.low and Z_.high imply +% or the result of ignoring pen widths in graph_current_graph. -% Set $, $$, $$$ so that shifting by $ then transforming by $$ and then $$$ -% maps the essential bounding box of graph_current_graph into (0,0)..Z_.graph_dimensions. The -% `essential bounding box' is either what Z_.low and Z_.high imply or the -% result of ignoring pen widths in graph_current_graph. vardef graph_remap(suffix $,$$,$$$) = save p_ ; graph_set_default_bounds ; @@ -245,10 +263,10 @@ vardef graph_remap(suffix $,$$,$$$) = (Z_.high+$) transformed $$ = p_ ; p_ transformed $$$ = Z_.graph_dimensions ; enddef ; + graph_margin_fraction.low=-.07 ; % bbox fraction for default range start graph_margin_fraction.high=1.07 ; % bbox fraction for default range stop - def graph_with_pen_and_color(expr q) = withpen penpart q withcolor if colormodel q=1 : @@ -268,7 +286,7 @@ enddef ; % Pair o is the value of p that makes tp (0,0). This implements the trick % whereby using 1 instead of 0 for the width or height or the setbounds path % for a label picture suppresses shifting in x or y. -% + %vardef graph_picture_conversion@#(expr q, o)(text tp) = % save p ; % if stroked q : @@ -284,8 +302,9 @@ enddef ; % addto @# also q shifted ((tp)-llcorner q) ; % fi %enddef ; -% + % This new version makes gdraw clip the result to the window defined with setrange + vardef graph_picture_conversion@#(expr q, o)(text tp) = save p ; save do_clip, tp_clipped ; boolean do_clip ; do_clip := true ; @@ -315,12 +334,11 @@ enddef ; def graph_coordinate_multiplication(expr a,b) = (xpart a*xpart b, ypart a*ypart b) enddef ; - vardef graph_clear_bounds@# = numeric @#.low, @#.high ; enddef; - % Finalize anything drawn in the present coordinate system and set up a new % system as requested + vardef setcoords(expr tx, ty) = interim warningcheck :=0 ; if length graph_current_graph>0 : @@ -335,10 +353,10 @@ vardef setcoords(expr tx, ty) = X_.graph_coordinate_type := tx ; Y_.graph_coordinate_type := ty; enddef ; - % Set Z_.low and Z_.high to correspond to given range of user graph % coordinates. The text argument should be a sequence of pairs and/or strings % with 4 components in all. + vardef setrange(text t) = interim warningcheck :=0 ; save r_ ; r_=0; @@ -353,8 +371,8 @@ vardef setrange(text t) = endfor enddef ; - % @# is X_ or Y_ ; l and h are numeric or string + vardef graph_set_bounds@#(expr l, h) = graph_clear_bounds@# ; if @#graph_coordinate_type>0 : @@ -382,15 +400,12 @@ vardef graph_set_bounds@#(expr l, h) = fi enddef ; - - - - %%%%%%%%%%%%%%%%%%%%%%%%% Converting path coordinates %%%%%%%%%%%%%%%%%%%%%%%%% % Find the result of scanning path p and using macros tx and ty to adjust the % x and y parts of each coordinate pair. Boolean parameter c tells whether to % force the result to be polygonal. + vardef graph_scan_path(expr p, c)(suffix tx, ty) = if (str tx="") and (str ty="") : p else : @@ -409,26 +424,29 @@ vardef graph_scan_path(expr p, c)(suffix tx, ty) = if pair p : point 0 of fi r_ fi enddef ; -vardef graph_pair_adjust(expr p)(suffix tx, ty) = (tx xpart p, ty ypart p) enddef ; +vardef graph_pair_adjust(expr p)(suffix tx, ty) = (tx xpart p, ty ypart p) enddef ; % Convert path p from user graph coords to internal graph coords. + vardef graph_convert_user_path_to_internal primary p = interim warningcheck :=0 ; - graph_scan_path(p, - (abs X_.graph_coordinate_type<>linear) or (abs Y_.graph_coordinate_type<>linear), - if abs X_.graph_coordinate_type=log : graph_mlog fi, - if abs Y_.graph_coordinate_type=log : graph_mlog fi) - transformed (identity - if X_.graph_coordinate_type<0 : xscaled -1 fi - if Y_.graph_coordinate_type<0 : yscaled -1 fi) + if known p : + graph_scan_path(p, + (abs X_.graph_coordinate_type<>linear) or (abs Y_.graph_coordinate_type<>linear), + if abs X_.graph_coordinate_type=log : graph_mlog fi, + if abs Y_.graph_coordinate_type=log : graph_mlog fi) + transformed (identity + if X_.graph_coordinate_type<0 : xscaled -1 fi + if Y_.graph_coordinate_type<0 : yscaled -1 fi) + fi enddef ; - % Convert label location t_ from user graph coords to internal graph coords. % The label location should be a pair, or two numbers/strings. If t_ is empty % or a single item of non-pair type, just return t_. Unknown coordinates % produce unknown components in the result. + vardef graph_label_convert_user_to_internal(text t_) = save n_ ; n_=0; interim warningcheck :=0 ; @@ -448,23 +466,56 @@ vardef graph_label_convert_user_to_internal(text t_) = fi enddef ; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Reading data files %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Read a line from file f, extract whitespace-separated tokens ignoring any % initial "%", and return true if at least one token is found. The tokens % are stored in @#1, @#2, .. with "" in the last @#[] entry. + +% String manipulation routines for MetaPost +% It is harmless to input this file more than once. + +vardef isdigit primary d = + ("0"<=d)and(d<="9") +enddef ; + +% Number of initial characters of string s where `c <character>' is true + +vardef graph_cspan(expr s)(text c) = + 0 + for i=1 upto length s: + exitunless c substring (i-1,i) of s; + + 1 + endfor +enddef ; + +% String s is composed of items separated by white space. Lop off the first +% item and the surrounding white space and return just the item. + +vardef graph_loptok suffix s = + save t, k; + k = graph_cspan(s," ">=); + if k > 0 : + s := substring(k,infinity) of s ; + fi + k := graph_cspan(s," "<); + string t; + t = substring (0,k) of s; + s := substring (k,infinity) of s; + s := substring (graph_cspan(s," ">=),infinity) of s; + t +enddef ; + vardef graph_read_line@#(expr f) = save n_, s_ ; string s_; s_ = readfrom f ; string @#[] ; if s_<>EOF : @#0 := s_ ; - @#1 := loptok s_ ; + @#1 := graph_loptok s_ ; n_ = if @#1="%" : 0 else : 1 fi ; forever : - @#[incr n_] := loptok s_ ; + @#[incr n_] := graph_loptok s_ ; exitif @#[n_]="" ; endfor @#1<>"" @@ -472,12 +523,13 @@ vardef graph_read_line@#(expr f) = fi enddef ; - % Execute c for each line of data read from file f, and stop at the first % line with no data. Commands c can use line number i and tokens $1, $2, ... +% and j is the number of fields. + def gdata(expr f)(suffix $)(text c) = - boolean flag ; - for i=1 upto infinity : + %boolean flag ; % not used? + for i=1 upto largestmantissa : exitunless graph_read_line$(f) ; c endfor @@ -486,8 +538,8 @@ def gdata(expr f)(suffix $)(text c) = fi enddef ; - % Read a path from file f. The path is terminated by blank line or EOF. + vardef graph_readpath(expr f) = interim warningcheck :=0 ; save s ; @@ -497,9 +549,9 @@ vardef graph_readpath(expr f) = ) enddef ; - % Append coordinates t to polygonal path @#. The coordinates can be numerics, % strings, or a single pair. + vardef augment@#(text t) = interim warningcheck := 0 ; if not path begingroup @# endgroup : @@ -513,12 +565,11 @@ vardef augment@#(text t) = fi enddef ; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Drawing and filling %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Unknown pair components are set to 0 because glabel and gdotlabel understand % unknown coordinates as `0 in absolute units'. + vardef graph_unknown_pair_bbox(expr p) = interim warningcheck:=0 ; if known p : addto graph_current_bb doublepath p ; @@ -535,6 +586,7 @@ enddef ; % Initiate a gdraw or gfill command. This must be done before scanning the % argument, because that could invoke the `if known graph_plot_picture' test in a following % plot option . + def graph_addto = def graph_errorbar_text = enddef ; color graph_foreground ; @@ -542,8 +594,8 @@ def graph_addto = graph_last_drawn := graph_plot_picture := nullpicture ; addto graph_last_drawn enddef; +% Handle the part of a gdraw command that uses path or data file p. -% Handle the part of a Gdraw command that uses path or data file p. def graph_draw expr p = if string p : hide(graph_last_path := graph_readpath(p) ;) graph_convert_user_path_to_internal graph_last_path @@ -556,8 +608,8 @@ def graph_draw expr p = withpen currentpen graph_withlist _op_ enddef ; +% Handle the part of a gdraw command that uses path or data file p. -% Handle the part of a Gdraw command that uses path or data file p. def graph_fill expr p = if string p : hide(graph_last_path := graph_readpath(p) --cycle ;) graph_convert_user_path_to_internal graph_last_path @@ -571,8 +623,8 @@ enddef ; def gdraw = graph_addto doublepath graph_draw enddef ; def gfill = graph_addto contour graph_fill enddef ; - % This is used in graph_draw and graph_fill to allow postprocessing graph_last_drawn + def graph_withlist text t_ = t_ ; graph_post_draw; enddef; def witherrorbars(text t) text options = @@ -584,6 +636,8 @@ def witherrorbars(text t) text options = options enddef ; +% new feature: graph_errorbars + picture graph_errorbar_picture ; graph_errorbar_picture := image(draw (left--right) scaled .5 ;) ; %picture graph_xbar_picture ; graph_xbar_picture := image(draw (down--up) scaled .5 ;) ; %picture graph_ybar_picture ; graph_ybar_picture := image(draw (left--right) scaled .5 ;) ; @@ -646,6 +700,7 @@ enddef ; % Set graph_plot_picture so the postprocessing step will plot picture p at each path knot. % Also select nullpen to suppress stroking. + def plot expr p = if known graph_plot_picture : withpen nullpen @@ -657,20 +712,19 @@ def plot expr p = enddef ; % This hides a semicolon that could prematurely end graph_withlist's text argument + def graph_addto_currentpicture primary p = addto currentpicture also p ; enddef; def graph_setbounds = setbounds currentpicture to enddef ; - -def gdrawarrow = graph_number_of_arrowheads :=1 ; gdraw enddef; -def gdrawdblarrow = graph_number_of_arrowheads :=2 ; gdraw enddef; - +def gdrawarrow = graph_number_of_arrowheads := 1 ; gdraw enddef; +def gdrawdblarrow = graph_number_of_arrowheads := 2 ; gdraw enddef; % Post-process the filled or stroked picture graph_last_drawn as follows : (1) update % the bounding box information ; (2) transfer it to graph_current_graph unless the pen has % been set to nullpen to disable stroking ; (3) plot graph_plot_picture at each knot. + vardef graph_post_draw = - save p ; - path p ; p=pathpart graph_last_drawn; + save p ; path p ; p = pathpart graph_last_drawn ; graph_unknown_pair_bbox(p) ; if filled graph_last_drawn or not graph_is_null(penpart graph_last_drawn) : addto graph_current_graph also graph_last_drawn ; @@ -687,17 +741,23 @@ vardef graph_post_draw = if graph_number_of_arrowheads>1 : graph_draw_arrowhead(reverse p, graph_with_pen_and_color(graph_last_drawn)) ; fi - graph_number_of_arrowheads :=0 ; + graph_number_of_arrowheads := 0 ; fi enddef ; -vardef graph_is_null(expr p) = (urcorner p=origin) and (llcorner p=origin) enddef ; +vardef graph_is_null(expr p) = (urcorner p=origin) and (llcorner p=origin) enddef ; vardef graph_draw_arrowhead(expr p)(text w) = % Draw arrowhead for path p, with list w + %save r ; r := angle(precontrol infinity of p shifted -point infinity of p) ; addto graph_current_graph also - image(filldraw arrowhead( - graph_arrowhead_extent(precontrol infinity of p, point infinity of p)) w ; - graph_setbounds point infinity of p..cycle) ; + image(fill arrowhead (graph_arrowhead_extent(precontrol infinity of p,point infinity of p)) w ; + draw arrowhead (graph_arrowhead_extent(precontrol infinity of p,point infinity of p)) w + undashed ; +%if (r mod 90 <> 0) : % orientation can be wrong due to remapping +% draw textext("\tfxx " & decimal r) shifted point infinity of p withcolor blue ; +%fi + graph_setbounds point infinity of p..cycle ; + ) ; % rotatedabout(point infinity of p,-r) ; enddef ; vardef graph_arrowhead_extent(expr p, q) = @@ -705,8 +765,6 @@ vardef graph_arrowhead_extent(expr p, q) = q enddef ; - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Drawing labels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Argument c is a drawing command that needs an additional argument p that gives @@ -714,6 +772,7 @@ enddef ; % path. Unknown components of p cause the setbounds path to have width or height 1 instead of 0. % Then graph_unknown_pair_bbox sets these components to 0 and graph_picture_conversion % suppresses subsequent repositioning. + def graph_draw_label(expr p)(suffix $)(text c) = save sdim_ ; pair sdim_; sdim_ := (if unknown xpart p : 1+ fi 0, if unknown ypart p : 1+ fi 0) ; @@ -722,14 +781,13 @@ def graph_draw_label(expr p)(suffix $)(text c) = image(c(p) ; graph_setbounds p--p+sdim_--cycle) _op_ enddef ; - % Stash the result drawing command c in the graph_label table using with list w and % an index based on angle mfun_laboff$. + vardef graph_stash_label(suffix $)(text c) text w = graph_label[1.5+angle mfun_laboff$ /90] = image(c(origin) w) ; enddef ; - def graph_label_location primary p = if pair p : graph_draw_label(p) elseif numeric p : graph_draw_label(point p of pathpart graph_last_drawn) @@ -737,33 +795,31 @@ def graph_label_location primary p = fi enddef ; - % Place label p at user graph coords t using with list w. (t is a time, a pair % or 2 numerics or strings). + vardef glabel@#(expr p)(text t) text w = graph_label_location graph_label_convert_user_to_internal(t) (@#,label@#(p)) w ; enddef; - % Place label p at user graph coords t using with list w and draw a dot there. % (t is a time, a pair, or 2 numerics or strings). + vardef gdotlabel@#(expr p)(text t) text w = graph_label_location graph_label_convert_user_to_internal(t) (@#,dotlabel@#(p)) w ; enddef; - def OUT = enddef ; % location text for outside labels - - %%%%%%%%%%%%%%%%%%%%%%%%%% Grid lines, ticks, etc. %%%%%%%%%%%%%%%%%%%%%%%%%% % Grid lines and tick marks are transformed versions of the templates below. % In the template paths, (0,0) is on the edge of the frame and inward is to % the right. -path Gtemplate.tick, Gtemplate.itick, Gtemplate.otick, Gtemplate.grid ; -Gtemplate.tick = (-3.5bp,0)--(3.5bp,0) ; -Gtemplate.itick = origin--(7bp,0) ; -Gtemplate.otick = (-7bp,0)--origin ; -Gtemplate.grid = origin--(1,0) ; + +path graph_template.tick, graph_template.itick, graph_template.otick, graph_template.grid ; +graph_template.tick = (-3.5bp,0)--(3.5bp,0) ; +graph_template.itick = origin--(7bp,0) ; +graph_template.otick = (-7bp,0)--origin ; +graph_template.grid = origin--(1,0) ; vardef tick@#(expr f,u) text w = graph_tick_label(@#,@,false,f,u,w) ; enddef; @@ -774,75 +830,82 @@ vardef otick@#(expr f,u) text w = graph_tick_label(@#,@,false,f,u,w) ; enddef; vardef grid@#(expr f,u) text w = graph_tick_label(@#,@,true,f,u,w) ; enddef; -% Produce a tick or grid mark for label suffix $, Gtemplate suffix $$, -% coordinate value u, and with list w. Boolean c tells whether Gtemplate$$ +% Produce a tick or grid mark for label suffix $, graph_template suffix $$, +% coordinate value u, and with list w. Boolean c tells whether graph_template$$ % needs scaling by X_.graph_dimensions or Y_.graph_dimensions, % and f gives a format string or a label picture. + def graph_tick_label(suffix $,$$)(expr c, f, u)(text w) = - graph_draw_label(graph_label_convert_user_to_internal(graph_generate_label_position($,u)),,draw graph_gridline_picture$($$,c,f,u,w) shifted) + graph_draw_label(graph_label_convert_user_to_internal(graph_generate_label_position($,u)),, + draw graph_gridline_picture$($$,c,f,u,w) shifted) enddef ; - % Generate label positioning arguments appropriate for label suffix $ and % coordinate u. + def graph_generate_label_position(suffix $)(expr u) = - if xpart mfun_laboff.$=0 : u,whatever else : whatever,u fi + if pair u : u elseif xpart mfun_laboff.$=0 : u,whatever else : whatever,u fi enddef ; - % Generate a picture of a grid line labeled with coordinate value u, picture % or format string f, and with list w. Suffix @# is bot, top, lft, or rt, -% suffix $ identifies entries in the Gtemplate table, and boolean c tells -% whether to scale Gtemplate$. +% suffix $ identifies entries in the graph_template table, and boolean c tells +% whether to scale graph_template$. + vardef graph_gridline_picture@#(suffix $)(expr c, f, u)(text w) = if unknown u : graph_error(u,"Label coordinate should be known") ; nullpicture else : save p ; path p; interim warningcheck :=0 ; graph_autogrid_needed :=false ; - p = Gtemplate$ zscaled -mfun_laboff@# - if c : Gxyscale fi - shifted (((.5 + mfun_laboff@# dotprod (.5,.5)) * mfun_laboff@#) Gxyscale) ; + p = graph_template$ zscaled -mfun_laboff@# + if c : graph_xyscale fi + shifted (((.5 + mfun_laboff@# dotprod (.5,.5)) * mfun_laboff@#) graph_xyscale) ; image(draw p w ; label@#(if string f : format(f,u) else : f fi, point 0 of p)) fi enddef ; -def Gxyscale = xscaled X_.graph_dimensions yscaled Y_.graph_dimensions enddef ; +def graph_xyscale = xscaled X_.graph_dimensions yscaled Y_.graph_dimensions enddef ; % Draw the frame or the part corresponding to label suffix @# using with list w. + vardef frame@# text w = graph_frame_needed :=false ; picture p_ ; p_ = image(draw if str@#<>"" : subpath round(angle mfun_laboff@#*graph_frame_pair_a+graph_frame_pair_b) of fi - unitsquare Gxyscale w) ; + unitsquare graph_xyscale w) ; graph_draw_label((whatever,whatever),,draw p_ shifted) ; enddef ; -pair graph_frame_pair_a ; graph_frame_pair_a=(1,1)/90; % unitsquare subpath is linear in label angle -pair graph_frame_pair_b ; graph_frame_pair_b=(.75,2.25); - - +pair graph_frame_pair_a ; graph_frame_pair_a=(1,1)/90; % unitsquare subpath is linear in label angle +pair graph_frame_pair_b ; graph_frame_pair_b=(.75,2.25); %%%%%%%%%%%%%%%%%%%%%%%%%% Automatic grid selection %%%%%%%%%%%%%%%%%%%%%%%%%% -string Glmarks[] ; % marking options per decade for logarithmic scales -string Gumarks ; % mark spacing options per decade for linear scales -string Gemarks ; % exponent spacing options for logarithmic scales -newinternal Gmarks, Gminlog ; -Gmarks := 4 ; % minimum number marks generated by auto.x or auto.y -Gminlog := mlog 3 ; % revert to uniform marks when largest/smallest < this +string graph_log_marks[] ; % marking options per decade for logarithmic scales +string graph_lin_marks ; % mark spacing options per decade for linear scales +string graph_exp_marks ; % exponent spacing options for logarithmic scales +newinternal graph_minimum_number_of_marks, graph_log_minimum ; +graph_minimum_number_of_marks := 4 ; % minimum number marks generated by auto.x or auto.y +graph_log_minimum := mlog 3 ; % revert to uniform marks when largest/smallest < this + +def Gfor(text t) = for i=t endfor enddef ; % to shorten the mark templates below -def Gfor(text t) = for i=t endfor enddef ; % to shorten the mark templates below -Glmarks[1]="1,2,5" ; -Glmarks[2]="1,1.5,2,3,4,5,7" ; -Glmarks[3]="1Gfor(6upto10 :,i/5)Gfor(5upto10 :,i/2)Gfor(6upto9 :,i)" ; -Glmarks[4]="1Gfor(11upto20 :,i/10)Gfor(11upto25 :,i/5)Gfor(11upto19 :,i/2)" ; -Glmarks[5]="1Gfor(21upto40 :,i/20)Gfor(21upto50 :,i/10)Gfor(26upto49 :,i/5)" ; -Gumarks="10,5,2" ; % start with 10 and go down; a final `,1' is appended -Gemarks="20,10,5,2,1" ; +graph_log_marks[1]="1,2,5" ; +graph_log_marks[2]="1,1.5,2,3,4,5,7" ; +graph_log_marks[3]="1Gfor(6upto10 :,i/5)Gfor(5upto10 :,i/2)Gfor(6upto9 :,i)" ; +graph_log_marks[4]="1Gfor(11upto20 :,i/10)Gfor(11upto25 :,i/5)Gfor(11upto19 :,i/2)" ; +graph_log_marks[5]="1Gfor(21upto40 :,i/20)Gfor(21upto50 :,i/10)Gfor(26upto49 :,i/5)" ; +graph_lin_marks="10,5,2" ; % start with 10 and go down; a final `,1' is appended +graph_exp_marks="20,10,5,2,1" ; +Ten_to0 = 1 ; +Ten_to1 = 10 ; +Ten_to2 = 100 ; +Ten_to3 = 1000 ; +Ten_to4 = 10000 ; % Determine the X_ or Y_ bounds on the range to be covered by automatic grid % marks. Suffix @# is X_ or Y_. The result is log or linear to specify the @@ -851,6 +914,7 @@ Gemarks="20,10,5,2,1" ; % are upper and lower bounds in % `modified exponential form'. In modified exponential form, (x,y) means % (x/1000)*10^y, where 1000<=abs x<10000. + vardef graph_bounds@# = interim warningcheck :=0 ; save l, h ; @@ -859,28 +923,29 @@ vardef graph_bounds@# = if abs @#graph_coordinate_type=log : graph_modified_lower := graph_Meform(l)+graph_modified_bias ; graph_modified_higher := graph_Meform(h)+graph_modified_bias ; - if h-l >= Gminlog : log else : linear fi + if h-l >= graph_log_minimum : log else : linear fi else : graph_modified_lower := graph_Feform(l)+graph_modified_bias ; graph_modified_higher := graph_Feform(h)+graph_modified_bias ; linear fi enddef ; + pair graph_modified_bias ; graph_modified_bias=(0,3); pair graph_modified_lower, graph_modified_higher ; +% Scan graph_log_marks[k] and evaluate tokens t for each m where l<=m<=h. -% Scan Glmarks[k] and evaluate tokens t for each m where l<=m<=h. def graph_scan_marks(expr k, l, h)(text t) = - for m=scantokens Glmarks[k] : + for m=scantokens graph_log_marks[k] : exitif m>h ; if m>=l : t fi endfor enddef ; - -% Scan Gmark[k] and evaluate tokens t for each m and e where m*10^e belongs +% Scan graph_log_marks[k] and evaluate tokens t for each m and e where m*10^e belongs % between l and h (inclusive), where both l and h are in modified exponent form. + def graph_scan_mark(expr k, l, h)(text t) = for e=ypart l upto ypart h : graph_scan_marks(k, if e>ypart l : 1 else : xpart l/1000 fi, @@ -888,27 +953,29 @@ def graph_scan_mark(expr k, l, h)(text t) = endfor enddef ; - % Select a k for which graph_scan_mark(k,...) gives enough marks. + vardef graph_select_mark = save k ; k = 0 ; forever : - exitif unknown Glmarks[k+1] ; - exitif 0 graph_scan_mark(incr k, graph_modified_lower, graph_modified_higher, +1) >= Gmarks ; + exitif unknown graph_log_marks[k+1] ; + exitif 0 graph_scan_mark(incr k, graph_modified_lower, graph_modified_higher, +1) + >= graph_minimum_number_of_marks ; endfor k enddef ; - -% Try to select an exponent spacing from Gemarks. If successful, set @# and +% Try to select an exponent spacing from graph_exp_marks. If successful, set @# and % return true + vardef graph_select_exponent_mark@# = numeric @# ; - for e=scantokens Gemarks : + for e=scantokens graph_exp_marks : @# = e ; exitif floor(ypart graph_modified_higher/e) - - floor(graph_modified_exponent_ypart(graph_modified_lower)/e) >= Gmarks ; + floor(graph_modified_exponent_ypart(graph_modified_lower)/e) + >= graph_minimum_number_of_marks ; numeric @# ; endfor known @# @@ -916,17 +983,17 @@ enddef ; vardef graph_modified_exponent_ypart(expr p) = ypart p if xpart p=1000 : -1 fi enddef ; - % Compute the mark spacing d between xpart graph_modified_lower and xpart graph_modified_higher. + vardef graph_tick_mark_spacing = interim warningcheck :=0 ; save m, n, d ; - m = Gmarks ; + m = graph_minimum_number_of_marks ; n = 1 for i=1 upto (mlog(xpart graph_modified_higher-xpart graph_modified_lower) - mlog m)/mlogten : *10 endfor ; if n<=1000 : - for x=scantokens Gumarks : + for x=scantokens graph_lin_marks : d = n*x ; exitif 0 graph_generate_numbers(d,+1)>=m ; numeric d ; @@ -935,25 +1002,24 @@ vardef graph_tick_mark_spacing = if known d : d else : n fi enddef ; - def graph_generate_numbers(expr d)(text t) = for m = d*ceiling(xpart graph_modified_lower/d) step d until xpart graph_modified_higher : t endfor enddef ; - % Evaluate tokens t for exponents e in multiples of d in the range determined % by graph_modified_lower and graph_modified_higher. + def graph_generate_exponents(expr d)(text t) = for e = d*floor(graph_modified_exponent_ypart(graph_modified_lower)/d+1) step d until d*floor(ypart graph_modified_higher/d) : t endfor enddef ; - % Adjust graph_modified_lower and graph_modified_higher so their exponent parts match % and they are in true exponent form ((x,y) means x*10^y). Return the new exponent. + vardef graph_match_exponents = interim warningcheck := 0 ; save e ; @@ -966,10 +1032,10 @@ vardef graph_match_exponents = e enddef ; - % Assume e is an integer and either m=0 or 1<=abs(m)<10000. Find m*(10^e) % and represent the result as a string if its absolute value would be at least % 4096 or less than .1. It is OK to return 0 as a string or a numeric. + vardef graph_factor_and_exponent_to_string(expr m, e) = if (e>3)or(e<-4) : decimal m & "e" & decimal e @@ -984,7 +1050,6 @@ vardef graph_factor_and_exponent_to_string(expr m, e) = fi enddef ; - def auto suffix $ = hide(def graph_comma= hide(def graph_comma=,enddef) enddef) if graph_bounds.graph_suffix($)=log : @@ -1002,7 +1067,6 @@ def auto suffix $ = fi enddef ; - string Autoform ; Autoform = "%g"; %vardef autogrid(suffix tx, ty) text w = @@ -1053,12 +1117,11 @@ vardef autogrid(suffix tx, ty) text w = fi enddef ; - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% endgraph %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def endgraph = if graph_autogrid_needed : autogrid(otick.bot, otick.lft) ; fi - if graph_frame_needed : frame ; fi + if graph_frame_needed : frame ; fi setcoords(linear,linear) ; interim truecorners :=1 ; for b=bbox graph_finished_graph : @@ -1075,14 +1138,9 @@ enddef ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We format in luatex (using \mathematics{}) ... % we could pass via variables and save escaping as that is inefficient -Ten_to0 = 1 ; -Ten_to1 = 10 ; -Ten_to2 = 100 ; -Ten_to3 = 1000 ; -Ten_to4 = 10000 ; - if unknown context_mlib : vardef escaped_format(expr s) = @@ -1108,6 +1166,8 @@ if unknown context_mlib : fi ; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % A couple of extensions : % Define a function plotsymbol() returning a picture : 10 different shapes, diff --git a/metapost/context/base/mp-luas.mpiv b/metapost/context/base/mp-luas.mpiv new file mode 100644 index 000000000..c919ba215 --- /dev/null +++ b/metapost/context/base/mp-luas.mpiv @@ -0,0 +1,99 @@ +%D \module +%D [ file=mp-luas.mpiv, +%D version=2014.04.14, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=\LUA, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +if known context_luas : endinput ; fi ; + +% When I prototyped the runscript primitive I was just thinking of a usage like +% the original \directlua primitive in luatex: genererate something and pipe +% that back to metapost, and have access to some internals. Instead of compiling +% the code a the metapost end here we delegate that to the lua end. Only strings +% get passed. Of course in the end the real usage got a bit beyong the intended +% usage. So, in addition to some definitions here there are and will be use in +% other metafun modules too. Of course in retrospect I should have done this five +% years earlier. + +boolean context_luas ; context_luas := true ; + +% First variant: +% +% let lua = runscript ; +% +% Second variant: +% +% vardef lua (text t) = +% runscript(for s = t : s & endfor "") +% enddef; +% +% Third variant: +% +% vardef lua (text t) = +% runscript("" for s = t : +% if string s : +% & s +% elseif numeric s : +% & decimal s +% elseif boolean s : +% & if s : "true" else "false" fi +% fi endfor) +% enddef; +% +% Fourth variant: + +vardef mlib_luas_luacall(text t) = + runscript("" for s = t : + if string s : + & s + elseif numeric s : + & decimal s + elseif boolean s : + & if s : "true" else "false" fi + fi endfor + ) +enddef ; + +vardef mlib_luas_lualist(expr c)(text t) = + save b ; boolean b ; b := false ; + runscript(c & "(" for s = t : + if b : + & "," + else : + hide(b := true) + fi + if string s : + & ditto & s & ditto + elseif numeric s : + & decimal s + elseif boolean s : + & if s : "true" else "false" fi + fi endfor & ")" + ) +enddef ; + +def luacall = mlib_luas_luacall enddef ; % why no let + +vardef lualist@#(text t) = mlib_luas_lualist(str @#)(t) enddef ; + +string mlib_luas_s ; % saves save/restore + +vardef lua@#(text t) = + mlib_luas_s := str @# ; + if length(mlib_luas_s) > 0 : + mlib_luas_lualist(mlib_luas_s,t) + else : + mlib_luas_luacall(t) + fi +enddef ; + +vardef MP@#(text t) = + mlib_luas_lualist("MP." & str @#,t) +enddef ; diff --git a/metapost/context/base/mp-mlib.mpiv b/metapost/context/base/mp-mlib.mpiv index 12840b28e..b19f47f1e 100644 --- a/metapost/context/base/mp-mlib.mpiv +++ b/metapost/context/base/mp-mlib.mpiv @@ -60,32 +60,70 @@ def namedcolor (expr n) = withprescript "sp_name=" & n enddef ; +% def spotcolor(expr n, v) = +% 1 +% withprescript "sp_type=spot" +% withprescript "sp_name=" & n +% withprescript "sp_value=" & (if numeric v : decimal v else : v fi) +% enddef ; +% +% def multitonecolor(expr name, fractions, components, value) = +% 1 +% withprescript "sp_type=multitone" +% withprescript "sp_name=" & name +% withprescript "sp_fractions=" & decimal fractions +% withprescript "sp_components=" & components +% withprescript "sp_value=" & value +% enddef ; + def spotcolor(expr n, v) = 1 withprescript "sp_type=spot" withprescript "sp_name=" & n - withprescript "sp_value=" & v + withprescript "sp_value=" & colordecimals v enddef ; -def multitonecolor(expr name, fractions, components, value) = +def multitonecolor(expr name)(text t) = 1 withprescript "sp_type=multitone" - withprescript "sp_name=" & name - withprescript "sp_fractions=" & decimal fractions - withprescript "sp_components=" & components - withprescript "sp_value=" & value + withprescript "sp_name=" & name + withprescript "sp_value=" & colordecimalslist(t) enddef ; -def transparent(expr alternative, transparency)(text c) = +def transparent(expr a, t)(text c) = % use withtransparency instead 1 % this permits withcolor x intoshade y - withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative) - withprescript "tr_transparency=" & decimal transparency + withprescript "tr_alternative=" & decimal transparency_alternative_to_number(a) + withprescript "tr_transparency=" & decimal t withcolor c enddef ; -def withtransparency(expr alternative, transparency) = - withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative) - withprescript "tr_transparency=" & decimal transparency +% def withtransparency(expr a, t) = +% withprescript "tr_alternative=" & decimal transparency_alternative_to_number(a) +% withprescript "tr_transparency=" & decimal t +% enddef ; + +let transparency = pair ; + +% def withtransparency expr t = +% withprescript "tr_alternative=" & decimal transparency_alternative_to_number(xpart t) +% withprescript "tr_transparency=" & decimal ypart t +% enddef ; +% +% withtransparency (1,.5) +% withtransparency ("normal",.5) + +def withtransparency (expr t) (text rest) = + if pair t : + withprescript "tr_alternative=" & decimal transparency_alternative_to_number(xpart t) + withprescript "tr_transparency=" & decimal ypart t + else : + mfun_with_transparency (transparency_alternative_to_number(t)) + fi rest +enddef ; + +def mfun_with_transparency (expr a) expr t = + withprescript "tr_alternative=" & decimal a + withprescript "tr_transparency=" & decimal t enddef ; def cmyk(expr c, m, y, k) = % provided for downward compability @@ -96,7 +134,8 @@ enddef ; newinternal textextoffset ; textextoffset := 0 ; -numeric mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space) +%%%%%%% mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space) +color mfun_tt_b ; numeric mfun_tt_n ; mfun_tt_n := 0 ; picture mfun_tt_p ; mfun_tt_p := nullpicture ; picture mfun_tt_o ; mfun_tt_o := nullpicture ; @@ -135,44 +174,10 @@ extra_beginfig := extra_beginfig & "mfun_reset_tex_texts ;" ; % flush twice: once in location in order to pick up e.g. color properties, % and once at the end because we need to flush missing ones. -% vardef rawtextext(expr str) = -% if str = "" : -% nullpicture -% elseif mfun_trial_run : -% mfun_tt_n := mfun_tt_n + 1 ; -% mfun_tt_o := image(draw origin) ; % save drawoptions -% addto mfun_tt_p doublepath unitsquare -% withprescript "tx_number=" & decimal mfun_tt_n -% withprescript "tx_stage=extra" -% withpostscript str ; -% image ( -% addto currentpicture doublepath unitsquare -% withprescript "tx_number=" & decimal mfun_tt_n -% withprescript "tx_stage=trial" -% withprescript "tx_color=" & colordecimals colorpart mfun_tt_o -% withpostscript str -% ; ) -% else : -% mfun_tt_n := mfun_tt_n + 1 ; -% if known mfun_tt_d[mfun_tt_n] : -% image ( -% addto currentpicture doublepath unitsquare -% xscaled mfun_tt_w[mfun_tt_n] -% yscaled (mfun_tt_h[mfun_tt_n] + mfun_tt_d[mfun_tt_n]) -% withprescript "tx_number=" & decimal mfun_tt_n -% withprescript "tx_stage=final" -% % withpostscript str ; % for tracing -% ; ) shifted (0,-mfun_tt_d[mfun_tt_n]) -% else : -% image ( -% addto currentpicture doublepath unitsquare -% ; ) -% fi -% fi -% enddef ; +% see mp-keep.mpiv for older code -% vardef rawtextext(expr str) = % todo: avoid currentpicture -% if str = "" : +% vardef rawtextext(expr s) = % todo: avoid currentpicture +% if s = "" : % nullpicture % else : % mfun_tt_n := mfun_tt_n + 1 ; @@ -180,15 +185,12 @@ extra_beginfig := extra_beginfig & "mfun_reset_tex_texts ;" ; % if mfun_trial_run : % mfun_tt_o := nullpicture ; % addto mfun_tt_o doublepath origin _op_ ; % save drawoptions -% addto mfun_tt_p doublepath unitsquare -% withprescript "tx_number=" & decimal mfun_tt_n -% withprescript "tx_stage=extra" -% withpostscript str ; % addto mfun_tt_c doublepath unitsquare % withprescript "tx_number=" & decimal mfun_tt_n % withprescript "tx_stage=trial" % withprescript "tx_color=" & colordecimals colorpart mfun_tt_o -% withpostscript str ; +% withpostscript s ; +% addto mfun_tt_p also mfun_tt_c ; % elseif known mfun_tt_d[mfun_tt_n] : % addto mfun_tt_c doublepath unitsquare % xscaled mfun_tt_w[mfun_tt_n] @@ -203,8 +205,8 @@ extra_beginfig := extra_beginfig & "mfun_reset_tex_texts ;" ; % fi % enddef ; -vardef rawtextext(expr str) = % todo: avoid currentpicture - if str = "" : +vardef rawtextext(expr s) = % todo: avoid currentpicture + if s = "" : nullpicture else : mfun_tt_n := mfun_tt_n + 1 ; @@ -216,17 +218,16 @@ vardef rawtextext(expr str) = % todo: avoid currentpicture withprescript "tx_number=" & decimal mfun_tt_n withprescript "tx_stage=trial" withprescript "tx_color=" & colordecimals colorpart mfun_tt_o - withpostscript str ; + withpostscript s ; addto mfun_tt_p also mfun_tt_c ; - elseif known mfun_tt_d[mfun_tt_n] : + else : + mfun_tt_b := lua.mp.tt_dimensions(mfun_tt_n) ; addto mfun_tt_c doublepath unitsquare - xscaled mfun_tt_w[mfun_tt_n] - yscaled (mfun_tt_h[mfun_tt_n] + mfun_tt_d[mfun_tt_n]) - shifted (0,-mfun_tt_d[mfun_tt_n]) + xscaled redpart mfun_tt_b + yscaled (greenpart mfun_tt_b + bluepart mfun_tt_b) + shifted (0,- bluepart mfun_tt_b) withprescript "tx_number=" & decimal mfun_tt_n withprescript "tx_stage=final" ; - else : - addto mfun_tt_c doublepath unitsquare ; % unitpicture fi ; mfun_tt_c fi @@ -234,7 +235,10 @@ enddef ; % More text -defaultfont := "Mono" ; % was cmr10, could be lmmono10-regular, but is fed into context anyway +defaultfont := "Mono" ; +defaultscale := 1 ; + +extra_beginfig := extra_beginfig & "defaultscale:=1;" ; vardef fontsize expr name = save size ; numeric size ; @@ -366,6 +370,8 @@ vardef thetextext@#(expr p,z) = % interim labeloffset := textextoffset ; if string p : thetextext@#(rawtextext(p),z) + elseif numeric p : + thetextext@#(rawtextext(decimal p),z) else : p if (mfun_labtype@# >= 10) : @@ -401,19 +407,171 @@ enddef ; let normalinfont = infont ; -primarydef str infont name = % nasty hack +primarydef s infont name = % nasty hack if name = "" : - textext(str) + textext(s) else : - textext("\definedfont[" & name & "]" & str) + textext("\definedfont[" & name & "]" & s) fi enddef ; +% Helper + +string mfun_prescript_separator ; mfun_prescript_separator := char(13) ; + % Shades -newinternal shadefactor ; shadefactor := 1 ; -pair shadeoffset ; shadeoffset := origin ; -boolean trace_shades ; trace_shades := false ; +% for while we had this: + +newinternal shadefactor ; shadefactor := 1 ; % currently obsolete +pair shadeoffset ; shadeoffset := origin ; % currently obsolete +boolean trace_shades ; trace_shades := false ; % still there + +% def withlinearshading (expr a, b) = +% withprescript "sh_type=linear" +% withprescript "sh_domain=0 1" +% withprescript "sh_factor=" & decimal shadefactor +% withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) +% withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) +% enddef ; +% +% def withcircularshading (expr a, b, ra, rb) = +% withprescript "sh_type=circular" +% withprescript "sh_domain=0 1" +% withprescript "sh_factor=" & decimal shadefactor +% withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) +% withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) +% withprescript "sh_radius_a=" & decimal ra +% withprescript "sh_radius_b=" & decimal rb +% enddef ; +% +% def withshading (expr how)(text rest) = +% if how = "linear" : +% withlinearshading(rest) +% elseif how = "circular" : +% withcircularshading(rest) +% else : +% % nothing +% fi +% enddef ; +% +% def withfromshadecolor expr t = +% withprescript "sh_color=into" +% withprescript "sh_color_a=" & colordecimals t +% enddef ; + +% def withtoshadecolor expr t = +% withprescript "sh_color=into" +% withprescript "sh_color_b=" & colordecimals t +% enddef ; + +% but this is nicer + +path mfun_shade_path ; + +primarydef p withshademethod m = + hide(mfun_shade_path := p ;) + p + withprescript "sh_domain=0 1" + withprescript "sh_color=into" + withprescript "sh_color_a=" & colordecimals white + withprescript "sh_color_b=" & colordecimals black + if m = "linear" : + withprescript "sh_type=linear" + withprescript "sh_factor=1" + withprescript "sh_center_a=" & ddecimal llcorner p + withprescript "sh_center_b=" & ddecimal urcorner p + else : + withprescript "sh_type=circular" + withprescript "sh_factor=1.2" + withprescript "sh_center_a=" & ddecimal center p + withprescript "sh_center_b=" & ddecimal center p + withprescript "sh_radius_a=" & decimal 0 + withprescript "sh_radius_b=" & decimal ( max ( + (xpart center p - xpart llcorner p) ++ (ypart center p - ypart llcorner p), + (xpart center p - xpart ulcorner p) ++ (ypart ulcorner p - ypart center p), + (xpart lrcorner p - xpart center p) ++ (ypart center p - ypart lrcorner p), + (xpart urcorner p - xpart center p) ++ (ypart urcorner p - ypart center p) + ) ) + fi +enddef ; + +def withshadevector expr a = + withprescript "sh_center_a=" & ddecimal (point xpart a of mfun_shade_path) + withprescript "sh_center_b=" & ddecimal (point ypart a of mfun_shade_path) +enddef ; + +def withshadecenter expr a = + withprescript "sh_center_a=" & ddecimal ( + center mfun_shade_path shifted ( + xpart a * bbwidth (mfun_shade_path)/2, + ypart a * bbheight(mfun_shade_path)/2 + ) + ) +enddef ; + +def withshadedomain expr d = + withprescript "sh_domain=" & ddecimal d +enddef ; + +def withshadefactor expr f = + withprescript "sh_factor=" & decimal f +enddef ; + +def withshadecolors (expr a, b) = + withprescript "sh_color=into" + withprescript "sh_color_a=" & colordecimals a + withprescript "sh_color_b=" & colordecimals b +enddef ; + +primarydef a shadedinto b = % withcolor red shadedinto green + 1 % does not work with transparency + withprescript "sh_color=into" + withprescript "sh_color_a=" & colordecimals a + withprescript "sh_color_b=" & colordecimals b +enddef ; + +primarydef p withshade sc = + p withprescript mfun_defined_cs_pre[sc] +enddef ; + +def defineshade suffix s = + mfun_defineshade(str s) +enddef ; + +def mfun_defineshade (expr s) text t = + expandafter def scantokens s = t enddef ; +enddef ; + +def shaded text s = + s +enddef ; + +% Old macros: + +def withcircularshade (expr a, b, ra, rb, ca, cb) = + withprescript "sh_type=circular" + withprescript "sh_domain=0 1" + withprescript "sh_factor=1" + withprescript "sh_color_a=" & colordecimals ca + withprescript "sh_color_b=" & colordecimals cb + withprescript "sh_center_a=" & ddecimal a % (a shifted shadeoffset) + withprescript "sh_center_b=" & ddecimal b % (b shifted shadeoffset) + withprescript "sh_radius_a=" & decimal ra + withprescript "sh_radius_b=" & decimal rb +enddef ; + +def withlinearshade (expr a, b, ca, cb) = + withprescript "sh_type=linear" + withprescript "sh_domain=0 1" + withprescript "sh_factor=1" + withprescript "sh_color_a=" & colordecimals ca + withprescript "sh_color_b=" & colordecimals cb + withprescript "sh_center_a=" & ddecimal a % (a shifted shadeoffset) + withprescript "sh_center_b=" & ddecimal b % (b shifted shadeoffset) +enddef ; + +% replaced (obsolete): def set_linear_vector (suffix a,b)(expr p,n) = if (n=1) : a := llcorner p ; b := urcorner p ; @@ -428,7 +586,7 @@ def set_linear_vector (suffix a,b)(expr p,n) = fi ; enddef ; -def set_circular_vector (suffix ab, r)(expr p,n) = +def set_circular_vector (suffix ab,r)(expr p,n) = if (n=1) : ab := llcorner p ; elseif (n=2) : ab := lrcorner p ; elseif (n=3) : ab := urcorner p ; @@ -451,7 +609,7 @@ enddef ; def linear_shade (expr p, n, ca, cb) = begingroup ; - save a, b, sh ; pair a, b ; + save a, b ; pair a, b ; set_linear_vector(a,b)(p,n) ; fill p withlinearshade(a,b,ca,cb) ; if trace_shades : @@ -460,43 +618,19 @@ def linear_shade (expr p, n, ca, cb) = endgroup ; enddef ; -def withcircularshade (expr a, b, ra, rb, ca, cb) = - withprescript "sh_type=circular" - withprescript "sh_domain=0 1" - withprescript "sh_factor=" & decimal shadefactor - withprescript "sh_color_a=" & colordecimals ca - withprescript "sh_color_b=" & colordecimals cb - withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) - withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) - withprescript "sh_radius_a=" & decimal ra - withprescript "sh_radius_b=" & decimal rb -enddef ; - -def withlinearshade (expr a, b, ca, cb) = - withprescript "sh_type=linear" - withprescript "sh_domain=0 1" - withprescript "sh_factor=" & decimal shadefactor - withprescript "sh_color_a=" & colordecimals ca - withprescript "sh_color_b=" & colordecimals cb - withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) - withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) -enddef ; - string mfun_defined_cs_pre[] ; numeric mfun_defined_cs ; mfun_defined_cs := 0 ; -string mfun_prescript_separator ; mfun_prescript_separator := char(13) ; - vardef define_circular_shade (expr a, b, ra, rb, ca, cb) = mfun_defined_cs := mfun_defined_cs + 1 ; mfun_defined_cs_pre[mfun_defined_cs] := "sh_type=circular" - & mfun_prescript_separator & "sh_domain=0 1" - & mfun_prescript_separator & "sh_factor=" & decimal shadefactor - & mfun_prescript_separator & "sh_color_a=" & colordecimals ca - & mfun_prescript_separator & "sh_color_b=" & colordecimals cb - & mfun_prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset) - & mfun_prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset) - & mfun_prescript_separator & "sh_radius_a=" & decimal ra - & mfun_prescript_separator & "sh_radius_b=" & decimal rb + & mfun_prescript_separator & "sh_domain=0 1" + & mfun_prescript_separator & "sh_factor=1" + & mfun_prescript_separator & "sh_color_a=" & colordecimals ca + & mfun_prescript_separator & "sh_color_b=" & colordecimals cb + & mfun_prescript_separator & "sh_center_a=" & ddecimal a % (a shifted shadeoffset) + & mfun_prescript_separator & "sh_center_b=" & ddecimal b % (b shifted shadeoffset) + & mfun_prescript_separator & "sh_radius_a=" & decimal ra + & mfun_prescript_separator & "sh_radius_b=" & decimal rb ; mfun_defined_cs enddef ; @@ -504,52 +638,49 @@ enddef ; vardef define_linear_shade (expr a, b, ca, cb) = mfun_defined_cs := mfun_defined_cs + 1 ; mfun_defined_cs_pre[mfun_defined_cs] := "sh_type=linear" - & mfun_prescript_separator & "sh_domain=0 1" - & mfun_prescript_separator & "sh_factor=" & decimal shadefactor - & mfun_prescript_separator & "sh_color_a=" & colordecimals ca - & mfun_prescript_separator & "sh_color_b=" & colordecimals cb - & mfun_prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset) - & mfun_prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset) + & mfun_prescript_separator & "sh_domain=0 1" + & mfun_prescript_separator & "sh_factor=1" + & mfun_prescript_separator & "sh_color_a=" & colordecimals ca + & mfun_prescript_separator & "sh_color_b=" & colordecimals cb + & mfun_prescript_separator & "sh_center_a=" & ddecimal a % (a shifted shadeoffset) + & mfun_prescript_separator & "sh_center_b=" & ddecimal b % (b shifted shadeoffset) ; mfun_defined_cs enddef ; -primarydef p withshade sc = - p withprescript mfun_defined_cs_pre[sc] -enddef ; - - -vardef define_sampled_linear_shade(expr a,b,n)(text t) = - mfun_defined_cs := mfun_defined_cs + 1 ; - mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=linear" - & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) - & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) - & mfun_prescript_separator & "ssh_nofcolors=" & decimal n - & mfun_prescript_separator & "ssh_domain=" & domstr - & mfun_prescript_separator & "ssh_extend=" & extstr - & mfun_prescript_separator & "ssh_colors=" & colstr - & mfun_prescript_separator & "ssh_bounds=" & bndstr - & mfun_prescript_separator & "ssh_ranges=" & ranstr - ; - mfun_defined_cs -enddef ; - -vardef define_sampled_circular_shade(expr a,b,ra,rb,n)(text t) = - mfun_defined_cs := mfun_defined_cs + 1 ; - mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=circular" - & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) - & mfun_prescript_separator & "ssh_radius_a=" & decimal ra - & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) - & mfun_prescript_separator & "ssh_radius_b=" & decimal rb - & mfun_prescript_separator & "ssh_nofcolors=" & decimal n - & mfun_prescript_separator & "ssh_domain=" & domstr - & mfun_prescript_separator & "ssh_extend=" & extstr - & mfun_prescript_separator & "ssh_colors=" & colstr - & mfun_prescript_separator & "ssh_bounds=" & bndstr - & mfun_prescript_separator & "ssh_ranges=" & ranstr - ; - mfun_defined_cs -enddef ; +% I lost the example code that uses this: +% +% vardef define_sampled_linear_shade(expr a,b,n)(text t) = +% mfun_defined_cs := mfun_defined_cs + 1 ; +% mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=linear" +% & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) +% & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) +% & mfun_prescript_separator & "ssh_nofcolors=" & decimal n +% & mfun_prescript_separator & "ssh_domain=" & domstr +% & mfun_prescript_separator & "ssh_extend=" & extstr +% & mfun_prescript_separator & "ssh_colors=" & colstr +% & mfun_prescript_separator & "ssh_bounds=" & bndstr +% & mfun_prescript_separator & "ssh_ranges=" & ranstr +% ; +% mfun_defined_cs +% enddef ; +% +% vardef define_sampled_circular_shade(expr a,b,ra,rb,n)(text t) = +% mfun_defined_cs := mfun_defined_cs + 1 ; +% mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=circular" +% & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) +% & mfun_prescript_separator & "ssh_radius_a=" & decimal ra +% & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) +% & mfun_prescript_separator & "ssh_radius_b=" & decimal rb +% & mfun_prescript_separator & "ssh_nofcolors=" & decimal n +% & mfun_prescript_separator & "ssh_domain=" & domstr +% & mfun_prescript_separator & "ssh_extend=" & extstr +% & mfun_prescript_separator & "ssh_colors=" & colstr +% & mfun_prescript_separator & "ssh_bounds=" & bndstr +% & mfun_prescript_separator & "ssh_ranges=" & ranstr +% ; +% mfun_defined_cs +% enddef ; % vardef predefined_linear_shade (expr p, n, ca, cb) = % save a, b, sh ; pair a, b ; @@ -564,53 +695,6 @@ enddef ; % define_circular_shade(ab,ab,0,r,ca,cb) % enddef ; -% NEW EXPERIMENTAL CODE - -def withlinearshading (expr a, b) = - withprescript "sh_type=linear" - withprescript "sh_domain=0 1" - withprescript "sh_factor=" & decimal shadefactor - withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) - withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) -enddef ; - -def withcircularshading (expr a, b, ra, rb) = - withprescript "sh_type=circular" - withprescript "sh_domain=0 1" - withprescript "sh_factor=" & decimal shadefactor - withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset) - withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) - withprescript "sh_radius_a=" & decimal ra - withprescript "sh_radius_b=" & decimal rb -enddef ; - -def withfromshadecolor expr t = - withprescript "sh_color=into" - withprescript "sh_color_a=" & colordecimals t -enddef ; - -def withtoshadecolor expr t = - withprescript "sh_color=into" - withprescript "sh_color_b=" & colordecimals t -enddef ; - -def withshading (expr how)(text rest) = - if how = "linear" : - withlinearshading(rest) - elseif how = "circular" : - withcircularshading(rest) - else : - % nothing - fi -enddef ; - -primarydef a shadedinto b = - 1 % does not work with transparency - withprescript "sh_color=into" - withprescript "sh_color_a=" & colordecimals a - withprescript "sh_color_b=" & colordecimals b -enddef ; - % Layers def onlayer primary name = @@ -655,10 +739,10 @@ enddef ; % Positions -def register (expr label, width, height, offset) = +def register (expr tag, width, height, offset) = % draw image ( addto currentpicture doublepath unitsquare xscaled width yscaled height shifted offset - withprescript "ps_label=" & label ; + withprescript "ps_label=" & tag ; % ) ; % no transformations enddef ; @@ -670,8 +754,8 @@ extra_endfig := extra_endfig & "mfun_reset_tex_texts ; " ; % Bonus -vardef verbatim(expr str) = - ditto & "\detokenize{" & str & "}" & ditto +vardef verbatim(expr s) = + ditto & "\detokenize{" & s & "}" & ditto enddef ; % New @@ -747,7 +831,7 @@ primarydef t asgroup s = % s = isolated|knockout endgroup enddef ; -% Also experimental +% Also experimental ... needs to be made better ... so it can change! string mfun_auto_align[] ; @@ -781,6 +865,9 @@ enddef ; % passvariable("boolean",false) ; % passvariable("path",fullcircle scaled 1cm) ; +% we could use the new lua interface but there is not that much gain i.e. +% we still need to serialize + vardef mfun_point_to_string(expr p,i) = decimal xpart (point i of p) & " " & decimal ypart (point i of p) & " " & @@ -821,6 +908,10 @@ vardef mfun_cmykcolor_to_string(expr c) = decimal blackpart c enddef ; +vardef mfun_greycolor_to_string(expr n) = + decimal n +enddef ; + vardef mfun_path_to_string(expr p) = mfun_point_to_string(p,0) for i=1 upto length(p) : & " " & mfun_point_to_string(p,i) endfor enddef ; @@ -847,6 +938,7 @@ vardef tostring(expr value) = elseif pair value : mfun_pair_to_string(value) elseif rgbcolor value : mfun_rgbcolor_to_string(value) elseif cmykcolor value : mfun_cmykcolor_to_string(value) + elseif greycolor value : mfun_greycolor_to_string(value) elseif boolean value : mfun_boolean_to_string(value) elseif path value : mfun_path_to_string(value) elseif transform value : mfun_transform_to_string(value) @@ -1042,23 +1134,80 @@ enddef ; % moved here from mp-grap.mpiv +% vardef escaped_format(expr s) = +% "" for n=0 upto length(s) : & +% if ASCII substring (n,n+1) of s = 37 : +% "@" +% else : +% substring (n,n+1) of s +% fi +% endfor +% enddef ; + +numeric mfun_esc_b ; % begin +numeric mfun_esc_l ; % length +string mfun_esc_s ; % character + +mfun_esc_s := "%" ; % or: char(37) + +% this one is the fastest when we have a match + +% vardef escaped_format(expr s) = +% "" for n=0 upto length(s)-1 : & +% % if ASCII substring (n,n+1) of s = 37 : +% if substring (n,n+1) of s = mfun_esc_s : +% "@" +% else : +% substring (n,n+1) of s +% fi +% endfor +% enddef ; + +% this one wins when we have no match + vardef escaped_format(expr s) = - "" for n=0 upto length(s) : & - if ASCII substring (n,n+1) of s = 37 : - "@" - else : - substring (n,n+1) of s + mfun_esc_b := 0 ; + mfun_esc_l := length(s) ; + for n=0 upto mfun_esc_l-1 : + % if ASCII substring (n,n+1) of s = 37 : + if substring (n,n+1) of s = mfun_esc_s : + if mfun_esc_b = 0 : + "" + fi + if n >= mfun_esc_b : + & (substring (mfun_esc_b,n) of s) + exitif numeric begingroup mfun_esc_b := n+1 endgroup ; % hide + fi + & "@" fi endfor + if mfun_esc_b = 0 : + s + % elseif mfun_esc_b > 0 : + elseif mfun_esc_b < mfun_esc_l : + & (substring (mfun_esc_b,mfun_esc_l) of s) + fi enddef ; -vardef strfmt(expr f, x) = % maybe use mfun_ namespace - "\MPgraphformat{" & escaped_format(f) & "}{" & mfun_tagged_string(x) & "}" -enddef ; - -vardef varfmt(expr f, x) = % maybe use mfun_ namespace - "\MPformatted{" & escaped_format(f) & "}{" & mfun_tagged_string(x) & "}" -enddef ; +vardef strfmt(expr f, x) = "\MPgraphformat{" & escaped_format(f) & "}{" & mfun_tagged_string(x) & "}" enddef ; +vardef varfmt(expr f, x) = "\MPformatted{" & escaped_format(f) & "}{" & mfun_tagged_string(x) & "}" enddef ; vardef format (expr f, x) = textext(strfmt(f, x)) enddef ; vardef formatted(expr f, x) = textext(varfmt(f, x)) enddef ; + +% could be this (something to discuss with alan as it involves graph): +% +% vardef format (expr f,x) = lua.mp.graphformat(f,mfun_tagged_string(x) enddef ; +% vardef formatted(expr f,x) = lua.mp.format (f, x) enddef ; +% +% def strfmt = format enddef ; % old +% def varfmt = formatted enddef ; % old + +% new + +def eofill text t = fill t withpostscript "evenodd" enddef ; +%%% eoclip text t = clip t withpostscript "evenodd" enddef ; % no postscripts yet + +% def withrule expr r = +% if (t = "even-odd") or (t = "evenodd") : withpostscript "evenodd" fi +% enddef ; diff --git a/metapost/context/base/mp-page.mpiv b/metapost/context/base/mp-page.mpiv index 9c538d42a..a6fa3fba3 100644 --- a/metapost/context/base/mp-page.mpiv +++ b/metapost/context/base/mp-page.mpiv @@ -11,73 +11,309 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This module is rather preliminary and subjected to -%D changes. +%D This module is rather preliminary and subjected to changes. if known context_page : endinput ; fi ; boolean context_page ; context_page := true ; +% def LoadPageState = +% % now always set +% enddef ; +% +% if unknown PageStateAvailable : +% boolean PageStateAvailable ; +% PageStateAvailable := false ; +% fi ; +% +% if unknown OnRightPage : +% boolean OnRightPage ; +% OnRightPage := true ; +% fi ; +% +% if unknown OnOddPage : +% boolean OnOddPage ; +% OnOddPage := true ; +% fi ; +% +% if unknown InPageBody : +% boolean InPageBody ; +% InPageBody := false ; +% fi ; +% +% string CurrentLayout ; +% +% CurrentLayout := "default" ; +% +% PageNumber := 0 ; +% PaperHeight := 845.04684pt ; +% PaperWidth := 597.50787pt ; +% PrintPaperHeight := 845.04684pt ; +% PrintPaperWidth := 597.50787pt ; +% TopSpace := 71.12546pt ; +% BottomSpace := 0.0pt ; +% BackSpace := 71.13275pt ; +% CutSpace := 0.0pt ; +% MakeupHeight := 711.3191pt ; +% MakeupWidth := 426.78743pt ; +% TopHeight := 0.0pt ; +% TopDistance := 0.0pt ; +% HeaderHeight := 56.90294pt ; +% HeaderDistance := 0.0pt ; +% TextHeight := 597.51323pt ; +% FooterDistance := 0.0pt ; +% FooterHeight := 56.90294pt ; +% BottomDistance := 0.0pt ; +% BottomHeight := 0.0pt ; +% LeftEdgeWidth := 0.0pt ; +% LeftEdgeDistance := 0.0pt ; +% LeftMarginWidth := 75.58197pt ; +% LeftMarginDistance := 11.99829pt ; +% TextWidth := 426.78743pt ; +% RightMarginDistance := 11.99829pt ; +% RightMarginWidth := 75.58197pt ; +% RightEdgeDistance := 0.0pt ; +% RightEdgeWidth := 0.0pt ; +% +% PageOffset := 0.0pt ; +% PageDepth := 0.0pt ; +% +% LayoutColumns := 0 ; +% LayoutColumnDistance:= 0.0pt ; +% LayoutColumnWidth := 0.0pt ; +% +% LeftEdge := -4 ; Top := -40 ; +% LeftEdgeSeparator := -3 ; TopSeparator := -30 ; +% LeftMargin := -2 ; Header := -20 ; +% LeftMarginSeparator := -1 ; HeaderSeparator := -10 ; +% Text := 0 ; Text := 0 ; +% RightMarginSeparator := +1 ; FooterSeparator := +10 ; +% RightMargin := +2 ; Footer := +20 ; +% RightEdgeSeparator := +3 ; BottomSeparator := +30 ; +% RightEdge := +4 ; Bottom := +40 ; +% +% Margin := LeftMargin ; % obsolete +% Edge := LeftEdge ; % obsolete +% InnerMargin := RightMargin ; % obsolete +% InnerEdge := RightEdge ; % obsolete +% OuterMargin := LeftMargin ; % obsolete +% OuterEdge := LeftEdge ; % obsolete +% +% InnerMarginWidth := 0pt ; +% OuterMarginWidth := 0pt ; +% InnerMarginDistance := 0pt ; +% OuterMarginDistance := 0pt ; +% +% InnerEdgeWidth := 0pt ; +% OuterEdgeWidth := 0pt ; +% InnerEdgeDistance := 0pt ; +% OuterEdgeDistance := 0pt ; +% +% % path Area[][] ; +% % pair Location[][] ; +% % path Field[][] ; +% +% % numeric Hstep[] ; +% % numeric Hsize[] ; +% % numeric Vstep[] ; +% % numeric Vsize[] ; +% +% path Page ; +% +% numeric HorPos ; +% numeric VerPos ; +% +% % for VerPos=Top step 10 until Bottom: +% % for HorPos=LeftEdge step 1 until RightEdge: +% % Area[HorPos][VerPos] := origin--cycle ; +% % Area[VerPos][HorPos] := Area[HorPos][VerPos] ; +% % Location[HorPos][VerPos] := origin ; +% % Location[VerPos][HorPos] := Location[HorPos][VerPos] ; +% % Field[HorPos][VerPos] := origin--cycle ; +% % Field[VerPos][HorPos] := Field[HorPos][VerPos] ; +% % endfor ; +% % endfor ; +% +% % def LoadPageState = +% % scantokens "input mp-state.tmp" ; +% % enddef ; +% +% numeric mfun_temp ; +% +% def SwapPageState = +% if not OnRightPage : +% BackSpace := PaperWidth-MakeupWidth-BackSpace ; +% CutSpace := PaperWidth-MakeupWidth-CutSpace ; +% mfun_temp := LeftMarginWidth ; +% LeftMarginWidth := RightMarginWidth ; +% RightMarginWidth := mfun_temp ; +% mfun_temp := LeftMarginDistance ; +% LeftMarginDistance := RightMarginDistance ; +% RightMarginDistance := mfun_temp ; +% mfun_temp := LeftEdgeWidth ; +% LeftEdgeWidth := RightEdgeWidth ; +% RightEdgeWidth := mfun_temp ; +% mfun_temp := LeftEdgeDistance ; +% LeftEdgeDistance := RightEdgeDistance ; +% RightEdgeDistance := mfun_temp ; +% +% % these are now available as ..Width and ..Distance +% +% Margin := LeftMargin ; +% Edge := LeftEdge ; +% InnerMargin := RightMargin ; +% InnerEdge := RightEdge ; +% OuterMargin := LeftMargin ; +% OuterEdge := LeftEdge ; +% else : +% Margin := RightMargin ; +% Edge := RightEdge ; +% InnerMargin := LeftMargin ; +% InnerEdge := LeftEdge ; +% OuterMargin := RightMargin ; +% OuterEdge := RightEdge ; +% fi ; +% enddef ; + +% the new way: + +def LoadPageState = + % now always set +enddef ; + if unknown PageStateAvailable : boolean PageStateAvailable ; PageStateAvailable := false ; fi ; -if unknown OnRightPage : - boolean OnRightPage ; - OnRightPage := true ; -fi ; +string CurrentLayout ; CurrentLayout := "default" ; + +vardef PaperHeight = lua.mp.PaperHeight () enddef ; +vardef PaperWidth = lua.mp.PaperWidth () enddef ; +vardef PrintPaperHeight = lua.mp.PrintPaperHeight () enddef ; +vardef PrintPaperWidth = lua.mp.PrintPaperWidth () enddef ; +vardef TopSpace = lua.mp.TopSpace () enddef ; +vardef BottomSpace = lua.mp.BottomSpace () enddef ; +vardef BackSpace = lua.mp.BackSpace () enddef ; +vardef CutSpace = lua.mp.CutSpace () enddef ; +vardef MakeupHeight = lua.mp.MakeupHeight () enddef ; +vardef MakeupWidth = lua.mp.MakeupWidth () enddef ; +vardef TopHeight = lua.mp.TopHeight () enddef ; +vardef TopDistance = lua.mp.TopDistance () enddef ; +vardef HeaderHeight = lua.mp.HeaderHeight () enddef ; +vardef HeaderDistance = lua.mp.HeaderDistance () enddef ; +vardef TextHeight = lua.mp.TextHeight () enddef ; +vardef FooterDistance = lua.mp.FooterDistance () enddef ; +vardef FooterHeight = lua.mp.FooterHeight () enddef ; +vardef BottomDistance = lua.mp.BottomDistance () enddef ; +vardef BottomHeight = lua.mp.BottomHeight () enddef ; +vardef LeftEdgeWidth = lua.mp.LeftEdgeWidth () enddef ; +vardef LeftEdgeDistance = lua.mp.LeftEdgeDistance () enddef ; +vardef LeftMarginWidth = lua.mp.LeftMarginWidth () enddef ; +vardef LeftMarginDistance = lua.mp.LeftMarginDistance () enddef ; +vardef TextWidth = lua.mp.TextWidth () enddef ; +vardef RightMarginDistance = lua.mp.RightMarginDistance () enddef ; +vardef RightMarginWidth = lua.mp.RightMarginWidth () enddef ; +vardef RightEdgeDistance = lua.mp.RightEdgeDistance () enddef ; +vardef RightEdgeWidth = lua.mp.RightEdgeWidth () enddef ; +vardef InnerMarginDistance = lua.mp.InnerMarginDistance () enddef ; +vardef InnerMarginWidth = lua.mp.InnerMarginWidth () enddef ; +vardef OuterMarginDistance = lua.mp.OuterMarginDistance () enddef ; +vardef OuterMarginWidth = lua.mp.OuterMarginWidth () enddef ; +vardef InnerEdgeDistance = lua.mp.InnerEdgeDistance () enddef ; +vardef InnerEdgeWidth = lua.mp.InnerEdgeWidth () enddef ; +vardef OuterEdgeDistance = lua.mp.OuterEdgeDistance () enddef ; +vardef OuterEdgeWidth = lua.mp.OuterEdgeWidth () enddef ; +vardef PageOffset = lua.mp.PageOffset () enddef ; +vardef PageDepth = lua.mp.PageDepth () enddef ; +vardef LayoutColumns = lua.mp.LayoutColumns () enddef ; +vardef LayoutColumnDistance = lua.mp.LayoutColumnDistance() enddef ; +vardef LayoutColumnWidth = lua.mp.LayoutColumnWidth () enddef ; + +vardef OnRightPage = lua.mp.OnRightPage () enddef ; +vardef OnOddPage = lua.mp.OnOddPage () enddef ; +vardef InPageBody = lua.mp.InPageBody () enddef ; + +vardef RealPageNumber = lua.mp.RealPageNumber () enddef ; +vardef PageNumber = lua.mp.PageNumber () enddef ; +vardef NOfPages = lua.mp.NOfPages () enddef ; +vardef LastPageNumber = lua.mp.LastPageNumber () enddef ; % duplicates + +vardef CurrentColumn = lua.mp.CurrentColumn () enddef ; +vardef NOfColumns = lua.mp.NOfColumns () enddef ; + +vardef BaseLineSkip = lua.mp.BaseLineSkip () enddef ; +vardef LineHeight = lua.mp.LineHeight () enddef ; +vardef BodyFontSize = lua.mp.BodyFontSize () enddef ; + +vardef TopSkip = lua.mp.TopSkip () enddef ; +vardef StrutHeight = lua.mp.StrutHeight () enddef ; +vardef StrutDepth = lua.mp.StrutDepth () enddef ; + +vardef CurrentWidth = lua.mp.CurrentWidth () enddef ; +vardef CurrentHeight = lua.mp.CurrentHeight () enddef ; + +vardef HSize = lua.mp.HSize () enddef ; % duplicates +vardef VSize = lua.mp.VSize () enddef ; % duplicates + +vardef EmWidth = lua.mp.EmWidth () enddef ; +vardef ExHeight = lua.mp.ExHeight () enddef ; + +vardef PageFraction = lua.mp.PageFraction () enddef ; + +vardef SpineWidth = lua.mp.SpineWidth () enddef ; +vardef PaperBleed = lua.mp.PaperBleed () enddef ; + +boolean mfun_swapped ; -if unknown OnOddPage : - boolean OnOddPage ; - OnOddPage := true ; -fi ; +def SwapPageState = + mfun_swapped := true ; % eventually this will go ! +enddef ; -if unknown InPageBody : - boolean InPageBody ; - InPageBody := false ; -fi ; +extra_beginfig := extra_beginfig & "mfun_swapped := false ;" ; + +vardef LeftMarginWidth = if mfun_swapped and not OnRightPage : lua.mp.RightMarginWidth () else : lua.mp.LeftMarginWidth () fi enddef ; +vardef RightMarginWidth = if mfun_swapped and not OnRightPage : lua.mp.LeftMarginWidth () else : lua.mp.RightMarginWidth () fi enddef ; +vardef LeftMarginDistance = if mfun_swapped and not OnRightPage : lua.mp.RightMarginDistance() else : lua.mp.LeftMarginDistance () fi enddef ; +vardef RightMarginDistance = if mfun_swapped and not OnRightPage : lua.mp.LeftMarginDistance () else : lua.mp.RightMarginDistance() fi enddef ; + +vardef LeftEdgeWidth = if mfun_swapped and not OnRightPage : lua.mp.RightEdgeWidth () else : lua.mp.LeftEdgeWidth () fi enddef ; +vardef RightEdgeWidth = if mfun_swapped and not OnRightPage : lua.mp.LeftEdgeWidth () else : lua.mp.RightEdgeWidth () fi enddef ; +vardef LeftEdgeDistance = if mfun_swapped and not OnRightPage : lua.mp.RightEdgeDistance () else : lua.mp.LeftEdgeDistance () fi enddef ; +vardef RightEdgeDistance = if mfun_swapped and not OnRightPage : lua.mp.LeftEdgeDistance () else : lua.mp.RightEdgeDistance () fi enddef ; + +vardef BackSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi lua.mp.BackSpace() enddef ; +vardef CutSpace = if mfun_swapped and not OnRightPage : PaperWidth - MakeupWidth - fi lua.mp.CutSpace () enddef ; + +% better use: + +vardef OuterMarginWidth = if not OnRightPage : lua.mp.LeftMarginWidth () else : lua.mp.RightMarginWidth () fi enddef ; +vardef InnerMarginWidth = if not OnRightPage : lua.mp.RightMarginWidth () else : lua.mp.LeftMarginWidth () fi enddef ; +vardef OuterMarginDistance = if not OnRightPage : lua.mp.LeftMarginDistance () else : lua.mp.RightMarginDistance() fi enddef ; +vardef InnerMarginDistance = if not OnRightPage : lua.mp.RightMarginDistance() else : lua.mp.leftMarginDistance () fi enddef ; + +vardef OuterEdgeWidth = if not OnRightPage : lua.mp.LeftEdgeWidth () else : lua.mp.RightEdgeWidth () fi enddef ; +vardef InnerEdgeWidth = if not OnRightPage : lua.mp.RightEdgeWidth () else : lua.mp.LeftEdgeWidth () fi enddef ; +vardef OuterEdgeDistance = if not OnRightPage : lua.mp.LeftEdgeDistance () else : lua.mp.RightEdgeDistance () fi enddef ; +vardef InnerEdgeDistance = if not OnRightPage : lua.mp.RightEdgeDistance () else : lua.mp.leftEdgeDistance () fi enddef ; -string CurrentLayout ; - -CurrentLayout := "default" ; - -PageNumber := 0 ; -PaperHeight := 845.04684pt ; -PaperWidth := 597.50787pt ; -PrintPaperHeight := 845.04684pt ; -PrintPaperWidth := 597.50787pt ; -TopSpace := 71.12546pt ; -BottomSpace := 0.0pt ; -BackSpace := 71.13275pt ; -CutSpace := 0.0pt ; -MakeupHeight := 711.3191pt ; -MakeupWidth := 426.78743pt ; -TopHeight := 0.0pt ; -TopDistance := 0.0pt ; -HeaderHeight := 56.90294pt ; -HeaderDistance := 0.0pt ; -TextHeight := 597.51323pt ; -FooterDistance := 0.0pt ; -FooterHeight := 56.90294pt ; -BottomDistance := 0.0pt ; -BottomHeight := 0.0pt ; -LeftEdgeWidth := 0.0pt ; -LeftEdgeDistance := 0.0pt ; -LeftMarginWidth := 75.58197pt ; -LeftMarginDistance := 11.99829pt ; -TextWidth := 426.78743pt ; -RightMarginDistance := 11.99829pt ; -RightMarginWidth := 75.58197pt ; -RightEdgeDistance := 0.0pt ; -RightEdgeWidth := 0.0pt ; - -PageOffset := 0.0pt ; -PageDepth := 0.0pt ; - -LayoutColumns := 0 ; -LayoutColumnDistance:= 0.0pt ; -LayoutColumnWidth := 0.0pt ; +vardef OuterSpaceWidth = if not OnRightPage : lua.mp.BackSpace () else : lua.mp.CutSpace () fi enddef ; +vardef InnerSpaceWidth = if not OnRightPage : lua.mp.CutSpace () else : lua.mp.BackSpace () fi enddef ; + +% vardef CurrentLayout = lua.mp.CurrentLayout () enddef ; + +vardef OverlayWidth = lua.mp.OverlayWidth () enddef ; +vardef OverlayHeight = lua.mp.OverlayHeight () enddef ; +vardef OverlayDepth = lua.mp.OverlayDepth () enddef ; +vardef OverlayLineWidth = lua.mp.OverlayLineWidth() enddef ; +vardef OverlayOffset = lua.mp.OverlayOffset () enddef ; + +vardef defaultcolormodel = lua.mp.defaultcolormodel() enddef ; + +% def OverlayLineColor = lua.mp.OverlayLineColor() enddef ; +% def OverlayColor = lua.mp.OverlayColor () enddef ; + +% Next we implement the the page area model. First some constants. LeftEdge := -4 ; Top := -40 ; LeftEdgeSeparator := -3 ; TopSeparator := -30 ; @@ -89,37 +325,28 @@ RightMargin := +2 ; Footer := +20 ; RightEdgeSeparator := +3 ; BottomSeparator := +30 ; RightEdge := +4 ; Bottom := +40 ; -Margin := LeftMargin ; % obsolete -Edge := LeftEdge ; % obsolete -InnerMargin := RightMargin ; % obsolete -InnerEdge := RightEdge ; % obsolete -OuterMargin := LeftMargin ; % obsolete -OuterEdge := LeftEdge ; % obsolete +% Margin := LeftMargin ; % obsolete +% Edge := LeftEdge ; % obsolete +% InnerMargin := RightMargin ; % obsolete +% InnerEdge := RightEdge ; % obsolete +% OuterMargin := LeftMargin ; % obsolete +% OuterEdge := LeftEdge ; % obsolete -InnerMarginWidth := 0pt ; -OuterMarginWidth := 0pt ; -InnerMarginDistance := 0pt ; -OuterMarginDistance := 0pt ; +numeric HorPos ; HorPos := 0 ; +numeric VerPos ; VerPos := 0 ; -InnerEdgeWidth := 0pt ; -OuterEdgeWidth := 0pt ; -InnerEdgeDistance := 0pt ; -OuterEdgeDistance := 0pt ; +% We used to initialize these variables each (sub)run but at some point MP +% became too slow for this. See later. % path Area[][] ; % pair Location[][] ; % path Field[][] ; - +% % numeric Hstep[] ; % numeric Hsize[] ; % numeric Vstep[] ; % numeric Vsize[] ; - -path Page ; - -numeric HorPos ; -numeric VerPos ; - +% % for VerPos=Top step 10 until Bottom: % for HorPos=LeftEdge step 1 until RightEdge: % Area[HorPos][VerPos] := origin--cycle ; @@ -130,46 +357,8 @@ numeric VerPos ; % Field[VerPos][HorPos] := Field[HorPos][VerPos] ; % endfor ; % endfor ; - -% def LoadPageState = -% scantokens "input mp-state.tmp" ; -% enddef ; - -def SwapPageState = - if not OnRightPage : - BackSpace := PaperWidth-MakeupWidth-BackSpace ; - CutSpace := PaperWidth-MakeupWidth-CutSpace ; - i := LeftMarginWidth ; - LeftMarginWidth := RightMarginWidth ; - RightMarginWidth := i ; - i := LeftMarginDistance ; - LeftMarginDistance := RightMarginDistance ; - RightMarginDistance := i ; - i := LeftEdgeWidth ; - LeftEdgeWidth := RightEdgeWidth ; - RightEdgeWidth := i ; - i := LeftEdgeDistance ; - LeftEdgeDistance := RightEdgeDistance ; - RightEdgeDistance := i ; - - % these are now available as ..Width and ..Distance - - Margin := LeftMargin ; - Edge := LeftEdge ; - InnerMargin := RightMargin ; - InnerEdge := RightEdge ; - OuterMargin := LeftMargin ; - OuterEdge := LeftEdge ; - else : - Margin := RightMargin ; - Edge := RightEdge ; - InnerMargin := LeftMargin ; - InnerEdge := LeftEdge ; - OuterMargin := RightMargin ; - OuterEdge := RightEdge ; - fi ; -enddef ; - +% +% % def SetPageAreas = % % numeric Vsize[], Hsize[], Vstep[], Hstep[] ; @@ -338,29 +527,55 @@ def SetPageField = endfor ; enddef ; -def SetPagePage = - path Page ; - Page := unitsquare xscaled PaperWidth yscaled PaperHeight ; +def mfun_page_Area = hide(SetPageArea ;) Area enddef ; +def mfun_page_Location = hide(SetPageLocation ;) Location enddef ; +def mfun_page_Field = hide(SetPageField ;) Field enddef ; +def mfun_page_Vsize = hide(SetPageVsize ;) Vsize enddef ; +def mfun_page_Hsize = hide(SetPageHsize ;) Hsize enddef ; +def mfun_page_Vstep = hide(SetPageVstep ;) Vstep enddef ; +def mfun_page_Hstep = hide(SetPageHstep ;) Hstep enddef ; + +def SetAreaVariables = + let Area = mfun_page_Area ; + let Location = mfun_page_Location ; + let Field = mfun_page_Field ; + let Vsize = mfun_page_Vsize ; + let Hsize = mfun_page_Hsize ; + let Vstep = mfun_page_Vstep ; + let Hstep = mfun_page_Hstep ; enddef ; -def mfun_page_Area = hide(SetPageArea ;) Area enddef ; -def mfun_page_Location = hide(SetPageLocation ;) Location enddef ; -def mfun_page_Field = hide(SetPageField ;) Field enddef ; -def mfun_page_Vsize = hide(SetPageVsize ;) Vsize enddef ; -def mfun_page_Hsize = hide(SetPageHsize ;) Hsize enddef ; -def mfun_page_Vstep = hide(SetPageVstep ;) Vstep enddef ; -def mfun_page_Hstep = hide(SetPageHstep ;) Hstep enddef ; -def mfun_page_Page = hide(SetPagePage ;) Page enddef ; +% we should make Page no path .. from now on don't assume this .. for a while we keek it + +vardef FrontPageWidth = PaperWidth enddef ; +vardef BackPageWidth = PaperWidth enddef ; +vardef CoverWidth = 2 * PaperWidth + SpineWidth enddef ; +vardef CoverHeight = PaperHeight enddef ; + +vardef FrontPageHeight = PaperHeight enddef ; +vardef BackPageHeight = PaperHeight enddef ; +vardef SpineHeight = PaperHeight enddef ; + +def SetPagePage = path Page ; Page := unitsquare xscaled PaperWidth yscaled PaperHeight ; enddef ; +def SetPageCoverPage = path CoverPage ; CoverPage := unitsquare xscaled CoverWidth yscaled CoverHeight ; enddef ; +def SetPageSpine = path Spine ; Spine := unitsquare xscaled SpineWidth yscaled CoverHeight shifted (BackPageWidth,0) ; enddef ; +def SetPageBackPage = path BackPage ; BackPage := unitsquare xscaled BackPageWidth yscaled CoverHeight ; enddef ; +def SetPageFrontPage = path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth yscaled CoverHeight shifted (BackPageWidth+SpineWidth,0) ; enddef ; + +def mfun_page_Page = hide(SetPagePage ;) Page enddef ; +def mfun_page_CoverPage = hide(SetPageCoverPage;) CoverPage enddef ; +def mfun_page_Spine = hide(SetPageSpine ;) Spine enddef ; +def mfun_page_BackPage = hide(SetPageBackPage ;) BackPage enddef ; +def mfun_page_FrontPage = hide(SetPageFrontPage;) FrontPage enddef ; def SetPageVariables = - let Area = mfun_page_Area ; - let Location = mfun_page_Location ; - let Field = mfun_page_Field ; - let Vsize = mfun_page_Vsize ; - let Hsize = mfun_page_Hsize ; - let Vstep = mfun_page_Vstep ; - let Hstep = mfun_page_Hstep ; - let Page = mfun_page_Page ; + SetAreaVariables ; + % + let Page = mfun_page_Page ; + let CoverPage = mfun_page_CoverPage ; + let Spine = mfun_page_Spine ; + let BackPage = mfun_page_BackPage ; + let FrontPage = mfun_page_FrontPage ; enddef ; SetPageVariables ; @@ -393,45 +608,10 @@ enddef ; def BoundCoverAreas = % todo: add cropmarks - bboxmargin := 0 ; setbounds currentpicture to Paper enlarged PaperBleed ; -enddef ; - -def SetCoverAreas = - - if unknown SpineWidth : - SpineWidth := 8mm ; - fi ; - - if unknown PaperBleed : - PaperBleed := 0 ; - fi ; - - FrontPageWidth := PaperWidth ; - BackPageWidth := PaperWidth ; - PaperWidth := 2 * PaperWidth + SpineWidth ; - - FrontPageHeight := PaperHeight ; - BackPageHeight := PaperHeight ; - PaperHeight := PaperHeight ; - SpineHeight := PaperHeight ; - - path Paper ; Paper := unitsquare xscaled PaperWidth yscaled PaperHeight ; - path Spine ; Spine := unitsquare xscaled SpineWidth yscaled PaperHeight shifted (BackPageWidth,0); - path BackPage ; BackPage := unitsquare xscaled BackPageWidth yscaled PaperHeight ; - path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth yscaled PaperHeight shifted (BackPageWidth+SpineWidth,0) ; - + bboxmargin := 0 ; setbounds currentpicture to CoverPage enlarged PaperBleed ; enddef ; -% def StartCover = -% begingroup ; -% if PageStateAvailable : -% LoadPageState ; -% % SwapPageState ; -% fi ; -% SetPageAreas ; -% SetCoverAreas ; -% BoundCoverAreas ; -% enddef ; +let SetCoverAreas = SetPageVariables ; % compatiblity def StartCover = begingroup ; diff --git a/metapost/context/base/mp-tool.mpii b/metapost/context/base/mp-tool.mpii index f363f655e..a5bb345a1 100644 --- a/metapost/context/base/mp-tool.mpii +++ b/metapost/context/base/mp-tool.mpii @@ -5,17 +5,13 @@ %D subtitle=auxiliary macros, %D author=Hans Hagen, %D date=\currentdate, -%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% a cleanup is needed, like using image and alike -% use a few more "newinternal"'s - -%D This module is rather preliminary and subjected to -%D changes. +% def loadfile(expr name) = scantokens("input " & name & ";") enddef ; if known context_tool : endinput ; fi ; @@ -32,6 +28,8 @@ let @## = @# ; if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ; +newinternal metapostversion ; metapostversion := scantokens(mpversion) ; + % vardef mpversiongt(expr s) = % scantokens (mpversion & " > " & if numeric s : decimal s else : s fi) % enddef ; @@ -85,20 +83,14 @@ mpprocset := 1 ; % % protect ; -%D By including this module, \METAPOST\ automatically writes a -%D high resolution boundingbox to the \POSTSCRIPT\ file. This -%D hack is due to John Hobby himself. - -% When somehow the first one gets no HiRes, then make sure -% that the format matches the mem sizes in the config file. - -string space ; space = char 32 ; +string space ; space := char 32 ; +string CRLF ; CRLF := char 10 & char 13 ; vardef ddecimal primary p = - decimal xpart p & " " & decimal ypart p + decimal xpart p & " " & decimal ypart p enddef ; -%D Plain compatibility +%D Plain compatibility: string plain_compatibility_data ; plain_compatibility_data := "" ; @@ -112,7 +104,7 @@ def stopplaincompatibility = enddef ; % is now built in - +% % extra_endfig := extra_endfig % & "special " % & "(" @@ -124,6 +116,11 @@ enddef ; % & "&ddecimal urcorner currentpicture" % & ");"; +%D More neutral: + +let triplet = rgbcolor ; +let quadruplet = cmykcolor ; + %D Crap (experimental, not used): def forcemultipass = @@ -132,12 +129,28 @@ enddef ; %D Colors: -nocolormodel := 1 ; -greycolormodel := 3 ; -rgbcolormodel := 5 ; -cmykcolormodel := 7 ; +newinternal nocolormodel ; nocolormodel := 1 ; +newinternal greycolormodel ; greycolormodel := 3 ; +newinternal graycolormodel ; graycolormodel := 3 ; +newinternal rgbcolormodel ; rgbcolormodel := 5 ; +newinternal cmykcolormodel ; cmykcolormodel := 7 ; let grayscale = numeric ; +let greyscale = numeric ; + +vardef colorpart expr c = + if not picture c : + 0 + elseif colormodel c = greycolormodel : + greypart c + elseif colormodel c = rgbcolormodel : + (redpart c,greenpart c,bluepart c) + elseif colormodel c = cmykcolormodel : + (cyanpart c,magentapart c,yellowpart c,blackpart c) + else : + 0 % black + fi +enddef ; vardef colorlike(text c) text v = % colorlike(a) b, c, d ; save _p_ ; picture _p_ ; @@ -148,25 +161,19 @@ vardef colorlike(text c) text v = % colorlike(a) b, c, d ; elseif (colormodel _p_ = rgbcolormodel) : rgbcolor i ; else : - grayscale i ; + greycolor i ; fi ; endfor ; enddef ; -% if (unknown colormodel) : -% def colormodel = -% rgbcolormodel -% enddef ; -% fi ; - %D Also handy (when we flush colors): vardef dddecimal primary c = - decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c + decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c enddef ; vardef ddddecimal primary c = - decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c + decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c enddef ; vardef colordecimals primary c = @@ -193,39 +200,34 @@ enddef ; %D we need some trickery when we have multiple files. if unknown collapse_data : - boolean collapse_data ; collapse_data := false ; + boolean collapse_data ; + collapse_data := false ; fi ; boolean savingdata ; savingdata := false ; boolean savingdatadone ; savingdatadone := false ; def savedata expr txt = - if collapse_data : - write txt to data_mpd_file ; - else : - write if savingdata : txt else : - "\MPdata{" & decimal charcode & "}{" & txt & "}" - fi - & "%" to data_mpd_file ; - fi ; + write if collapse_data : + txt + else : + if savingdata : txt else : "\MPdata{" & decimal charcode & "}{" & txt & "}" fi & "%" + fi to data_mpd_file ; enddef ; def startsavingdata = - savingdata := true ; - savingdatadone := true ; - if collapse_data : - write - "\MPdata{" & decimal charcode & "}{%" - to - data_mpd_file ; - fi ; + savingdata := true ; + savingdatadone := true ; + if collapse_data : + write "\MPdata{" & decimal charcode & "}{%" to data_mpd_file ; + fi ; enddef ; def stopsavingdata = - if collapse_data : - write "}%" to data_mpd_file ; - fi ; - savingdata := false ; + if collapse_data : + write "}%" to data_mpd_file ; + fi ; + savingdata := false ; enddef ; def finishsavingdata = @@ -253,119 +255,130 @@ def newpair text v = forsuffixes i=v : save i ; pair i ; endfor ; endd %D box, draw the graphics that may not count, and restore the %D bounding box. %D -%D \starttypen +%D \starttyping %D push_boundingbox currentpicture; %D pop_boundingbox currentpicture; -%D \stoptypen +%D \stoptyping %D %D The bounding box can be called with: %D -%D \starttypen +%D \starttyping %D boundingbox currentpicture %D inner_boundingbox currentpicture %D outer_boundingbox currentpicture -%D \stoptypen +%D \stoptyping %D %D Especially the latter one can be of use when we include %D the graphic in a document that is clipped to the bounding %D box. In such occasions one can use: %D -%D \starttypen +%D \starttyping %D set_outer_boundingbox currentpicture; -%D \stoptypen +%D \stoptyping %D %D Its counterpart is: %D -%D \starttypen +%D \starttyping %D set_inner_boundingbox p -%D \stoptypen +%D \stoptyping -path pushed_boundingbox; +path mfun_boundingbox_stack ; +numeric mfun_boundingbox_stack_depth ; -def push_boundingbox text p = - pushed_boundingbox := boundingbox p; -enddef; +mfun_boundingbox_stack_depth := 0 ; -def pop_boundingbox text p = - setbounds p to pushed_boundingbox; -enddef; +def pushboundingbox text p = + mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth + 1 ; + mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := boundingbox p ; +enddef ; + +def popboundingbox text p = + setbounds p to mfun_boundingbox_stack[mfun_boundingbox_stack_depth] ; + mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := origin ; + mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth - 1 ; +enddef ; + +let push_boundingbox = pushboundingbox ; % downward compatible +let pop_boundingbox = popboundingbox ; % downward compatible vardef boundingbox primary p = - if (path p) or (picture p) : - llcorner p -- lrcorner p -- urcorner p -- ulcorner p - else : - origin - fi -- cycle + if (path p) or (picture p) : + llcorner p -- lrcorner p -- urcorner p -- ulcorner p + else : + origin + fi -- cycle enddef; -vardef inner_boundingbox primary p = - top rt llcorner p -- - top lft lrcorner p -- - bot lft urcorner p -- - bot rt ulcorner p -- cycle +vardef innerboundingbox primary p = + top rt llcorner p -- + top lft lrcorner p -- + bot lft urcorner p -- + bot rt ulcorner p -- cycle enddef; -vardef outer_boundingbox primary p = - bot lft llcorner p -- - bot rt lrcorner p -- - top rt urcorner p -- - top lft ulcorner p -- cycle +vardef outerboundingbox primary p = + bot lft llcorner p -- + bot rt lrcorner p -- + top rt urcorner p -- + top lft ulcorner p -- cycle enddef; -def innerboundingbox = inner_boundingbox enddef ; -def outerboundingbox = outer_boundingbox enddef ; +def inner_boundingbox = innerboundingbox enddef ; +def outer_boundingbox = outerboundingbox enddef ; -vardef set_inner_boundingbox text q = - setbounds q to inner_boundingbox q; +vardef set_inner_boundingbox text q = % obsolete + setbounds q to innerboundingbox q; enddef; -vardef set_outer_boundingbox text q = - setbounds q to outer_boundingbox q; +vardef set_outer_boundingbox text q = % obsolete + setbounds q to outerboundingbox q; enddef; -%D Some missing functions can be implemented rather -%D straightforward: - -numeric Pi ; Pi := 3.1415926 ; +%D Some missing functions can be implemented rather straightforward (thanks to +%D Taco and others): -vardef sqr primary x = (x*x) enddef ; -vardef log primary x = (if x=0: 0 else: mlog(x)/mlog(10) fi) enddef ; -vardef ln primary x = (if x=0: 0 else: mlog(x)/256 fi) enddef ; -vardef exp primary x = ((mexp 256)**x) enddef ; -vardef inv primary x = (if x=0: 0 else: x**-1 fi) enddef ; +pi := 3.14159265358979323846 ; radian := 180/pi ; % 2pi*radian = 360 ; -vardef pow (expr x,p) = (x**p) enddef ; +% let +++ = ++ ; -vardef asin primary x = (x+(x**3)/6+3(x**5)/40) enddef ; -vardef acos primary x = (asin(-x)) enddef ; -vardef atan primary x = (x-(x**3)/3+(x**5)/5-(x**7)/7) enddef ; -vardef tand primary x = (sind(x)/cosd(x)) enddef ; +numeric Pi ; Pi := pi ; % for some old compatibility reasons i guess -%D Here are Taco Hoekwater's alternatives (but -%D vardef'd and primaried). +vardef sqr primary x = x*x enddef ; +vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; +vardef ln primary x = if x=0: 0 else: mlog(x)/256 fi enddef ; +vardef exp primary x = (mexp 256)**x enddef ; +vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; -pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ; +vardef pow (expr x,p) = x**p enddef ; -vardef tand primary x = (sind(x)/cosd(x)) enddef ; -vardef cotd primary x = (cosd(x)/sind(x)) enddef ; +vardef tand primary x = sind(x)/cosd(x) enddef ; +vardef cotd primary x = cosd(x)/sind(x) enddef ; -vardef sin primary x = (sind(x*radian)) enddef ; -vardef cos primary x = (cosd(x*radian)) enddef ; -vardef tan primary x = (sin(x)/cos(x)) enddef ; -vardef cot primary x = (cos(x)/sin(x)) enddef ; +vardef sin primary x = sind(x*radian) enddef ; +vardef cos primary x = cosd(x*radian) enddef ; +vardef tan primary x = sin(x)/cos(x) enddef ; +vardef cot primary x = cos(x)/sin(x) enddef ; -vardef asin primary x = angle((1+-+x,x)) enddef ; -vardef acos primary x = angle((x,1+-+x)) enddef ; +vardef asin primary x = angle((1+-+x,x)) enddef ; +vardef acos primary x = angle((x,1+-+x)) enddef ; +vardef atan primary x = angle(1,x) enddef ; -vardef invsin primary x = ((asin(x))/radian) enddef ; -vardef invcos primary x = ((acos(x))/radian) enddef ; +vardef invsin primary x = (asin(x))/radian enddef ; +vardef invcos primary x = (acos(x))/radian enddef ; +vardef invtan primary x = (atan(x))/radian enddef ; -vardef acosh primary x = ln(x+(x+-+1)) enddef ; -vardef asinh primary x = ln(x+(x++1)) enddef ; +vardef acosh primary x = ln(x+(x+-+1)) enddef ; +vardef asinh primary x = ln(x+(x++1)) enddef ; vardef sinh primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ; vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ; +%D Sometimes this is handy: + +def undashed = + dashed nullpicture +enddef ; + %D We provide two macros for drawing stripes across a shape. %D The first method (with the n suffix) uses another method, %D slower in calculation, but more efficient when drawn. The @@ -374,101 +387,218 @@ vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ; %D the second argument identifier the way the shape is to be %D drawn. %D -%D \starttypen +%D \starttyping %D stripe_path_n %D (dashed evenly withcolor blue) %D (filldraw) %D fullcircle xscaled 100 yscaled 40 shifted (50,50) withpen pencircle scaled 4; -%D \stoptypen +%D \stoptyping %D %D The a (or angle) alternative supports arbitrary angles and %D is therefore more versatile. %D -%D \starttypen +%D \starttyping %D stripe_path_a %D (withpen pencircle scaled 2 withcolor red) %D (draw) %D fullcircle xscaled 100 yscaled 40 withcolor blue; -%D \stoptypen +%D \stoptyping +%D +%D We have two alternatives, controlled by arguments or defaults (when arguments +%D are zero). +%D +%D The newer and nicer interface is used as follows (triggered by a question by Mari): +%D +%D \starttyping +%D draw image (draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green) numberstriped (1,10,3) withcolor red ; +%D draw image (draw fullcircle scaled 3cm shifted (3cm,0cm) withcolor green) numberstriped (2,20,3) withcolor green ; +%D draw image (draw fullcircle scaled 3cm shifted (3cm,3cm) withcolor green) numberstriped (3,10,5) withcolor blue ; +%D draw image (draw fullcircle scaled 3cm shifted (0cm,3cm) withcolor green) numberstriped (4,20,5) withcolor yellow ; +%D +%D draw image (draw fullcircle scaled 3cm shifted (6cm,0cm) withcolor green) anglestriped (1,20,2) withcolor red ; +%D draw image (draw fullcircle scaled 3cm shifted (9cm,0cm) withcolor green) anglestriped (2,40,2) withcolor green ; +%D draw image (draw fullcircle scaled 3cm shifted (9cm,3cm) withcolor green) anglestriped (3,60,2) withcolor blue ; +%D draw image (draw fullcircle scaled 3cm shifted (6cm,3cm) withcolor green) anglestriped (4,80,2) withcolor yellow ; %D -%D The first alternative obeys: +%D draw image ( +%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; +%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; +%D ) shifted (9cm,0cm) numberstriped (1,10,3) withcolor red ; +%D +%D draw image ( +%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; +%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; +%D ) shifted (12cm,0cm) numberstriped (2,10,3) withcolor red ; +%D +%D draw image ( +%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; +%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; +%D ) shifted (9cm,5cm) numberstriped (3,10,3) withcolor red ; +%D +%D draw image ( +%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; +%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; +%D ) shifted (12cm,5cm) numberstriped (4,10,3) withcolor red ; +%D \stoptyping stripe_n := 10; stripe_slot := 3; - -%D When no pen dimensions are passed, the slot determines -%D the spacing. -%D -%D The angle alternative is influenced by: - stripe_gap := 5; stripe_angle := 45; +def mfun_tool_striped_number_action text extra = + for i = 1/used_n step 1/used_n until 1 : + draw point (1+i) of bounds -- point (3-i) of bounds withpen pencircle scaled penwidth extra ; + endfor ; + for i = 0 step 1/used_n until 1 : + draw point (3+i) of bounds -- point (1-i) of bounds withpen pencircle scaled penwidth extra ; + endfor ; +enddef ; + +def mfun_tool_striped_set_options(expr option) = + save isinner, swapped ; + boolean isinner, swapped ; + if option = 1 : + isinner := false ; + swapped := false ; + elseif option = 2 : + isinner := true ; + swapped := false ; + elseif option = 3 : + isinner := false ; + swapped := true ; + elseif option = 4 : + isinner := true ; + swapped := true ; + else : + isinner := false ; + swapped := false ; + fi ; +enddef ; + +vardef mfun_tool_striped_number(expr option, p, s_n, s_slot) text extra = + image ( + begingroup ; + save pattern, shape, bounds, penwidth, used_n, used_slot ; + picture pattern, shape ; path bounds ; numeric used_s, used_slot ; + mfun_tool_striped_set_options(option) ; + used_slot := if s_slot = 0 : stripe_slot else : s_slot fi ; + used_n := if s_n = 0 : stripe_n else : s_n fi ; + shape := image(draw p) ; + bounds := boundingbox shape ; + penwidth := min(ypart urcorner shape - ypart llcorner shape, xpart urcorner shape - xpart llcorner shape) / (used_slot * used_n) ; + pattern := image ( + if isinner : + mfun_tool_striped_number_action extra ; + for s within shape : + if stroked s or filled s : + clip currentpicture to pathpart s ; + fi + endfor ; + else : + for s within shape : + if stroked s or filled s : + draw image ( + mfun_tool_striped_number_action extra ; + clip currentpicture to pathpart s ; + ) ; + fi ; + endfor ; + fi ; + ) ; + if swapped : + addto currentpicture also shape ; + addto currentpicture also pattern ; + else : + addto currentpicture also pattern ; + addto currentpicture also shape ; + fi ; + endgroup ; + ) +enddef ; + +def mfun_tool_striped_angle_action text extra = + for i = minimum -.5used_gap step used_gap until maximum : + draw (minimum,i) -- (maximum,i) extra ; + endfor ; + currentpicture := currentpicture rotated used_angle ; +enddef ; + +vardef mfun_tool_striped_angle(expr option, p, s_angle, s_gap) text extra = + image ( + begingroup ; + save pattern, shape, mask, maximum, minimum, centrum, used_angle, used_gap ; + picture pattern, shape, mask ; numeric maximum, minimum ; pair centrum ; numeric used_angle, used_gap ; + mfun_tool_striped_set_options(option) ; + used_angle := if s_angle = 0 : stripe_angle else : s_angle fi ; + used_gap := if s_gap = 0 : stripe_gap else : s_gap fi ; + shape := image(draw p) ; + centrum := center shape ; + shape := shape shifted - centrum ; + mask := shape rotated used_angle ; + maximum := max (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ; + minimum := min (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ; + pattern := image ( + if isinner : + mfun_tool_striped_angle_action extra ; + for s within shape : + if stroked s or filled s : + clip currentpicture to pathpart s ; + fi + endfor ; + else : + for s within shape : + if stroked s or filled s : + draw image ( + mfun_tool_striped_angle_action extra ; + clip currentpicture to pathpart s ; + ) ; + fi ; + endfor ; + fi ; + ) ; + if swapped : + addto currentpicture also shape ; + addto currentpicture also pattern ; + else : + addto currentpicture also pattern ; + addto currentpicture also shape ; + fi ; + currentpicture := currentpicture shifted - centrum ; + endgroup ; + ) +enddef; + +newinternal striped_normal_inner ; striped_normal_inner := 1 ; +newinternal striped_reverse_inner ; striped_reverse_inner := 2 ; +newinternal striped_normal_outer ; striped_normal_outer := 3 ; +newinternal striped_reverse_outer ; striped_reverse_outer := 4 ; + +secondarydef p anglestriped s = + mfun_tool_striped_angle(redpart s,p,greenpart s,bluepart s) +enddef ; + +secondarydef p numberstriped s = + mfun_tool_striped_number(redpart s,p,greenpart s,bluepart s) +enddef ; + +% for old times sake: + def stripe_path_n (text s_spec) (text s_draw) expr s_path = - do_stripe_path_n (s_spec) (s_draw) (s_path) + do_stripe_path_n (s_spec) (s_draw) (s_path) enddef; def do_stripe_path_n (text s_spec) (text s_draw) (expr s_path) text s_text = - begingroup - save curpic, newpic, bb, pp, ww; - picture curpic, newpic; - path bb, pp; - pp := s_path; - curpic := currentpicture; - currentpicture := nullpicture; - s_draw pp s_text; - bb := boundingbox currentpicture; - newpic := currentpicture; - currentpicture := nullpicture; - ww := min(ypart urcorner newpic - ypart llcorner newpic, - xpart urcorner newpic - xpart llcorner newpic); - ww := ww/(stripe_slot*stripe_n); - for i=1/stripe_n step 1/stripe_n until 1: - draw point (1+i) of bb -- point (3-i) of bb - withpen pencircle scaled ww s_spec ; - endfor; - for i=0 step 1/stripe_n until 1: - draw point (3+i) of bb -- point (1-i) of bb - withpen pencircle scaled ww s_spec; - endfor; - clip currentpicture to pp; - addto newpic also currentpicture; - currentpicture := curpic; - addto currentpicture also newpic; - endgroup -enddef; + draw image(s_draw s_path s_text) numberstriped(3,0,0) s_spec ; +enddef ; def stripe_path_a (text s_spec) (text s_draw) expr s_path = - do_stripe_path_a (s_spec) (s_draw) (s_path) + do_stripe_path_a (s_spec) (s_draw) (s_path) enddef; def do_stripe_path_a (text s_spec) (text s_draw) (expr s_path) text s_text = - begingroup - save curpic, newpic, pp; picture curpic, newpic; path pp ; - pp := s_path ; - curpic := currentpicture; - currentpicture := nullpicture; - s_draw pp s_text ; - def do_stripe_rotation (expr p) = - (currentpicture rotatedaround(center p,stripe_angle)) - enddef ; - s_max := max - (xpart llcorner do_stripe_rotation(currentpicture), - xpart urcorner do_stripe_rotation(currentpicture), - ypart llcorner do_stripe_rotation(currentpicture), - ypart urcorner do_stripe_rotation(currentpicture)); - newpic := currentpicture; - currentpicture := nullpicture; - for i=-s_max-.5stripe_gap step stripe_gap until s_max: - draw (-s_max,i)--(s_max,i) s_spec; - endfor; - currentpicture := do_stripe_rotation(newpic); - clip currentpicture to pp ; - addto newpic also currentpicture; - currentpicture := curpic; - addto currentpicture also newpic; - endgroup -enddef; + draw image(s_draw s_path s_text) anglestriped(3,0,0) s_spec ; +enddef ; %D A few normalizing macros: %D @@ -507,46 +637,43 @@ enddef; % natural_width := xpart urcorner currentpicture - xpart llcorner currentpicture; % currentpicture := currentpicture scaled (the_width/natural_width) ; -% TODO TODO TODO TODO, not yet ok - primarydef p xsized w = - (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi) + (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi) enddef ; primarydef p ysized h = - (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi) + (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi) enddef ; primarydef p xysized s = - begingroup ; + begingroup save wh, w, h ; pair wh ; numeric w, h ; wh := paired (s) ; w := bbwidth(p) ; h := bbheight(p) ; - (p if (w>0) and (h>0) : - if xpart wh > 0 : xscaled (xpart wh/w) fi - if ypart wh > 0 : yscaled (ypart wh/h) fi - fi) - endgroup + p + if (w>0) and (h>0) : + if xpart wh > 0 : xscaled (xpart wh/w) fi + if ypart wh > 0 : yscaled (ypart wh/h) fi + fi + endgroup enddef ; -primarydef p sized wh = - (p xysized wh) -enddef ; +let sized = xysized ; -def xscale_currentpicture(expr w) = - currentpicture := currentpicture xsized w ; +def xscale_currentpicture(expr w) = % obsolete + currentpicture := currentpicture xsized w ; enddef; -def yscale_currentpicture(expr h) = - currentpicture := currentpicture ysized h ; +def yscale_currentpicture(expr h) = % obsolete + currentpicture := currentpicture ysized h ; enddef; -def xyscale_currentpicture(expr w, h) = - currentpicture := currentpicture xysized (w,h) ; +def xyscale_currentpicture(expr w, h) = % obsolete + currentpicture := currentpicture xysized (w,h) ; enddef; -def scale_currentpicture(expr w, h) = - currentpicture := currentpicture xsized w ; - currentpicture := currentpicture ysized h ; +def scale_currentpicture(expr w, h) = % obsolete + currentpicture := currentpicture xsized w ; + currentpicture := currentpicture ysized h ; enddef; %D A full circle is centered at the origin, while a unitsquare @@ -562,28 +689,28 @@ unitcircle := fullcircle shifted urcorner fullcircle ; path urcircle, ulcircle, llcircle, lrcircle ; -urcircle := origin--(+.5,0)&(+.5,0){up} ..(0,+.5)&(0,+.5)--cycle ; -ulcircle := origin--(0,+.5)&(0,+.5){left} ..(-.5,0)&(-.5,0)--cycle ; -llcircle := origin--(-.5,0)&(-.5,0){down} ..(0,-.5)&(0,-.5)--cycle ; -lrcircle := origin--(0,-.5)&(0,-.5){right}..(+.5,0)&(+.5,0)--cycle ; +urcircle := origin -- (+.5,0) & (+.5,0){up} .. (0,+.5) & (0,+.5) -- cycle ; +ulcircle := origin -- (0,+.5) & (0,+.5){left} .. (-.5,0) & (-.5,0) -- cycle ; +llcircle := origin -- (-.5,0) & (-.5,0){down} .. (0,-.5) & (0,-.5) -- cycle ; +lrcircle := origin -- (0,-.5) & (0,-.5){right} .. (+.5,0) & (+.5,0) -- cycle ; path tcircle, bcircle, lcircle, rcircle ; -tcircle = origin--(+.5,0)&(+.5,0){up} ..(0,+.5)..{down} (-.5,0)--cycle ; -bcircle = origin--(-.5,0)&(-.5,0){down} ..(0,-.5)..{up} (+.5,0)--cycle ; -lcircle = origin--(0,+.5)&(0,+.5){left} ..(-.5,0)..{right}(0,-.5)--cycle ; -rcircle = origin--(0,-.5)&(0,-.5){right}..(+.5,0)..{left} (0,+.5)--cycle ; +tcircle = origin -- (+.5,0) & (+.5,0) {up} .. (0,+.5) .. {down} (-.5,0) -- cycle ; +bcircle = origin -- (-.5,0) & (-.5,0) {down} .. (0,-.5) .. {up} (+.5,0) -- cycle ; +lcircle = origin -- (0,+.5) & (0,+.5) {left} .. (-.5,0) .. {right} (0,-.5) -- cycle ; +rcircle = origin -- (0,-.5) & (0,-.5) {right} .. (+.5,0) .. {left} (0,+.5) -- cycle ; -path urtriangle, ultriangle, lltriangle, lrtriangle ; +path urtriangle, ultriangle, lltriangle, lrtriangle ; % watch out: it's contrary to what you expect and starts in the origin -urtriangle := origin--(+.5,0)--(0,+.5)--cycle ; -ultriangle := origin--(0,+.5)--(-.5,0)--cycle ; -lltriangle := origin--(-.5,0)--(0,-.5)--cycle ; -lrtriangle := origin--(0,-.5)--(+.5,0)--cycle ; +urtriangle := origin -- (+.5,0) -- (0,+.5) -- cycle ; +ultriangle := origin -- (0,+.5) -- (-.5,0) -- cycle ; +lltriangle := origin -- (-.5,0) -- (0,-.5) -- cycle ; +lrtriangle := origin -- (0,-.5) -- (+.5,0) -- cycle ; path unitdiamond, fulldiamond ; -unitdiamond := (.5,0)--(1,.5)--(.5,1)--(0,.5)--cycle ; +unitdiamond := (.5,0) -- (1,.5) -- (.5,1) -- (0,.5) -- cycle ; fulldiamond := unitdiamond shifted - center unitdiamond ; %D More robust: @@ -598,46 +725,49 @@ fulldiamond := unitdiamond shifted - center unitdiamond ; %D Shorter -primarydef p xyscaled q = - begingroup ; save qq ; pair qq ; qq = paired(q) ; - ( p - if xpart qq<>0 : xscaled (xpart qq) fi - if ypart qq<>0 : yscaled (ypart qq) fi ) - endgroup +primarydef p xyscaled q = % secundarydef does not work out well + begingroup + save qq ; pair qq ; + qq = paired(q) ; + p + if xpart qq <> 0 : xscaled (xpart qq) fi + if ypart qq <> 0 : yscaled (ypart qq) fi + endgroup enddef ; -%D Experimenteel, zie folder-3.tex. +%D Some personal code that might move to another module def set_grid(expr w, h, nx, ny) = - boolean grid[][] ; boolean grid_full ; - grid_w := w ; - grid_h := h ; - grid_nx := nx ; - grid_ny := ny ; - grid_x := round(w/grid_nx) ; % +.5) ; - grid_y := round(h/grid_ny) ; % +.5) ; - grid_left := (1+grid_x)*(1+grid_y) ; - grid_full := false ; - for i=0 upto grid_x: - for j=0 upto grid_y: - grid[i][j] := false ; + boolean grid[][] ; boolean grid_full ; + numeric grid_w, grid_h, grid_nx, grid_ny, grid_x, grid_y, grid_left ; + grid_w := w ; + grid_h := h ; + grid_nx := nx ; + grid_ny := ny ; + grid_x := round(w/grid_nx) ; % +.5) ; + grid_y := round(h/grid_ny) ; % +.5) ; + grid_left := (1+grid_x)*(1+grid_y) ; + grid_full := false ; + for i=0 upto grid_x : + for j=0 upto grid_y : + grid[i][j] := false ; + endfor ; endfor ; - endfor ; enddef ; vardef new_on_grid(expr _dx_, _dy_) = - dx := _dx_ ; - dy := _dy_ ; - ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ; - ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ; - if not grid_full and not grid[ddx][ddy]: - grid[ddx][ddy] := true ; - grid_left := grid_left-1 ; - grid_full := (grid_left=0) ; - true - else: - false - fi + dx := _dx_ ; + dy := _dy_ ; + ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ; + ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ; + if not grid_full and not grid[ddx][ddy] : + grid[ddx][ddy] := true ; + grid_left := grid_left-1 ; + grid_full := (grid_left=0) ; + true + else : + false + fi enddef ; %D usage: \type{innerpath peepholed outerpath}. @@ -650,79 +780,71 @@ enddef ; %D endfig; secondarydef p peepholed q = - begingroup ; - save start ; pair start ; start := point 0 of p ; - if xpart start >= xpart center p : - if ypart start >= ypart center p : - urcorner q -- ulcorner q -- llcorner q -- lrcorner q -- - reverse p -- lrcorner q -- cycle - else : - lrcorner q -- urcorner q -- ulcorner q -- llcorner q -- - reverse p -- llcorner q -- cycle - fi - else : - if ypart start > ypart center p : - ulcorner q -- llcorner q -- lrcorner q -- urcorner q -- - reverse p -- urcorner q -- cycle + begingroup + save start ; pair start ; + start := point 0 of p ; + if xpart start >= xpart center p : + if ypart start >= ypart center p : + urcorner q -- ulcorner q -- llcorner q -- lrcorner q -- + reverse p -- lrcorner q -- cycle + else : + lrcorner q -- urcorner q -- ulcorner q -- llcorner q -- + reverse p -- llcorner q -- cycle + fi else : - llcorner q -- lrcorner q -- urcorner q -- ulcorner q -- - reverse p -- ulcorner q -- cycle + if ypart start > ypart center p : + ulcorner q -- llcorner q -- lrcorner q -- urcorner q -- + reverse p -- urcorner q -- cycle + else : + llcorner q -- lrcorner q -- urcorner q -- ulcorner q -- + reverse p -- ulcorner q -- cycle + fi fi - fi - endgroup + endgroup enddef ; boolean intersection_found ; secondarydef p intersection_point q = - begingroup + begingroup save x_, y_ ; (x_,y_) = p intersectiontimes q ; if x_<0 : - intersection_found := false ; - center p % origin + intersection_found := false ; + center p % origin else : - intersection_found := true ; - .5[point x_ of p, point y_ of q] + intersection_found := true ; + .5[point x_ of p, point y_ of q] fi - endgroup + endgroup enddef ; %D New, undocumented, experimental: vardef tensecircle (expr width, height, offset) = - ((-width/2,-height/2) ... (0,-height/2-offset) ... - (+width/2,-height/2) ... (+width/2+offset,0) ... - (+width/2,+height/2) ... (0,+height/2+offset) ... - (-width/2,+height/2) ... (-width/2-offset,0) ... cycle) + (-width/2,-height/2) ... (0,-height/2-offset) ... + (+width/2,-height/2) ... (+width/2+offset,0) ... + (+width/2,+height/2) ... (0,+height/2+offset) ... + (-width/2,+height/2) ... (-width/2-offset,0) ... cycle enddef ; -%vardef tensecircle (expr width, height, offset) = -% ((-width/2,-height/2)..(0,-height/2-offset)..(+width/2,-height/2) & -% (+width/2,-height/2)..(+width/2+offset,0)..(+width/2,+height/2) & -% (+width/2,+height/2)..(0,+height/2+offset)..(-width/2,+height/2) & -% (-width/2,+height/2)..(-width/2-offset,0)..(-width/2,-height/2)..cycle) -%enddef ; - vardef roundedsquare (expr width, height, offset) = - ((offset,0)--(width-offset,0){right} .. - (width,offset)--(width,height-offset){up} .. - (width-offset,height)--(offset,height){left} .. - (0,height-offset)--(0,offset){down} .. cycle) + (offset,0) -- (width-offset,0) {right} .. + (width,offset) -- (width,height-offset) {up} .. + (width-offset,height) -- (offset,height) {left} .. + (0,height-offset) -- (0,offset) {down} .. cycle enddef ; %D Some colors. -color cyan ; cyan = (0,1,1) ; -color magenta ; magenta = (1,0,1) ; -color yellow ; yellow = (1,1,0) ; - def colortype(expr c) = if cmykcolor c : cmykcolor elseif rgbcolor c : rgbcolor else : grayscale fi enddef ; + vardef whitecolor(expr c) = if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi enddef ; + vardef blackcolor(expr c) = if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi enddef ; @@ -730,112 +852,74 @@ enddef ; %D Well, this is the dangerous and naive version: def drawfill text t = - fill t ; - draw t ; + fill t ; + draw t ; enddef; %D This two step approach saves the path first, since it can %D be a function. Attributes must not be randomized. def drawfill expr c = - path _c_ ; _c_ := c ; - do_drawfill + path _c_ ; _c_ := c ; + mfun_do_drawfill enddef ; -def do_drawfill text t = - draw _c_ t ; - fill _c_ t ; +def mfun_do_drawfill text t = + draw _c_ t ; + fill _c_ t ; enddef; def undrawfill expr c = - drawfill c withcolor background + drawfill c withcolor background % rather useless enddef ; %D Moved from mp-char.mp -vardef paired (expr d) = - if pair d : d else : (d,d) fi -enddef ; - -vardef tripled (expr d) = - if color d : d else : (d,d,d) fi -enddef ; - -primarydef p enlarged d = - (p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle) -enddef; - -primarydef p llenlarged d = - (p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle) -enddef ; - -primarydef p lrenlarged d = - (llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle) +vardef paired primary d = + if pair d : d else : (d,d) fi enddef ; -primarydef p urenlarged d = - (llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle) +vardef tripled primary d = + if color d : d else : (d,d,d) fi enddef ; -primarydef p ulenlarged d = - (llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle) -enddef ; +% maybe secondaries: -primarydef p llmoved d = - ((llcorner p) shifted (-xpart paired(d),-ypart paired(d))) -enddef ; +primarydef p enlarged d = ( p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle ) enddef ; +primarydef p llenlarged d = ( p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle ) enddef ; +primarydef p lrenlarged d = ( llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle ) enddef ; +primarydef p urenlarged d = ( llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle ) enddef ; +primarydef p ulenlarged d = ( llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle ) enddef ; -primarydef p lrmoved d = - ((lrcorner p) shifted (+xpart paired(d),-ypart paired(d))) -enddef ; - -primarydef p urmoved d = - ((urcorner p) shifted (+xpart paired(d),+ypart paired(d))) -enddef ; - -primarydef p ulmoved d = - ((ulcorner p) shifted (-xpart paired(d),+ypart paired(d))) -enddef ; - -primarydef p leftenlarged d = - ((llcorner p) shifted (-d,0) -- lrcorner p -- - urcorner p -- (ulcorner p) shifted (-d,0) -- cycle) -enddef ; - -primarydef p rightenlarged d = - (llcorner p -- (lrcorner p) shifted (d,0) -- - (urcorner p) shifted (d,0) -- ulcorner p -- cycle) -enddef ; - -primarydef p topenlarged d = - (llcorner p -- lrcorner p -- - (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle) -enddef ; +primarydef p llmoved d = ( (llcorner p) shifted (-xpart paired(d),-ypart paired(d)) ) enddef ; +primarydef p lrmoved d = ( (lrcorner p) shifted (+xpart paired(d),-ypart paired(d)) ) enddef ; +primarydef p urmoved d = ( (urcorner p) shifted (+xpart paired(d),+ypart paired(d)) ) enddef ; +primarydef p ulmoved d = ( (ulcorner p) shifted (-xpart paired(d),+ypart paired(d)) ) enddef ; -primarydef p bottomenlarged d = - (llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- - urcorner p -- ulcorner p -- cycle) -enddef ; +primarydef p leftenlarged d = ( (llcorner p) shifted (-d,0) -- lrcorner p -- urcorner p -- (ulcorner p) shifted (-d,0) -- cycle ) enddef ; +primarydef p rightenlarged d = ( llcorner p -- (lrcorner p) shifted (d,0) -- (urcorner p) shifted (d,0) -- ulcorner p -- cycle ) enddef ; +primarydef p topenlarged d = ( llcorner p -- lrcorner p -- (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle ) enddef ; +primarydef p bottomenlarged d = ( llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- urcorner p -- ulcorner p -- cycle ) enddef ; %D Handy for testing/debugging: -primarydef p crossed d = +primarydef p crossed d = ( if pair p : - (p shifted (-d, 0) -- p -- - p shifted ( 0,-d) -- p -- - p shifted (+d, 0) -- p -- - p shifted ( 0,+d) -- p -- cycle) + p shifted (-d, 0) -- p -- + p shifted ( 0,-d) -- p -- + p shifted (+d, 0) -- p -- + p shifted ( 0,+d) -- p -- cycle else : - (center p shifted (-d, 0) -- llcorner p -- - center p shifted ( 0,-d) -- lrcorner p -- - center p shifted (+d, 0) -- urcorner p -- - center p shifted ( 0,+d) -- ulcorner p -- cycle) + center p shifted (-d, 0) -- llcorner p -- + center p shifted ( 0,-d) -- lrcorner p -- + center p shifted (+d, 0) -- urcorner p -- + center p shifted ( 0,+d) -- ulcorner p -- cycle fi -enddef ; +) enddef ; %D Also handy (math ladders): -vardef laddered expr p = +vardef laddered primary p = % was expr point 0 of p for i=1 upto length(p) : -- (xpart (point i of p), ypart (point (i-1) of p)) -- (point i of p) @@ -849,182 +933,143 @@ enddef ; % vardef topboundary primary p = (urcorner p -- ulcorner p) enddef ; % vardef leftboundary primary p = (ulcorner p -- llcorner p) enddef ; -vardef bottomboundary primary p = - if pair p : p else : (llcorner p -- lrcorner p) fi -enddef ; - -vardef rightboundary primary p = - if pair p : p else : (lrcorner p -- urcorner p) fi -enddef ; - -vardef topboundary primary p = - if pair p : p else : (urcorner p -- ulcorner p) fi -enddef ; - -vardef leftboundary primary p = - if pair p : p else : (ulcorner p -- llcorner p) fi -enddef ; +vardef bottomboundary primary p = if pair p : p else : (llcorner p -- lrcorner p) fi enddef ; +vardef rightboundary primary p = if pair p : p else : (lrcorner p -- urcorner p) fi enddef ; +vardef topboundary primary p = if pair p : p else : (urcorner p -- ulcorner p) fi enddef ; +vardef leftboundary primary p = if pair p : p else : (ulcorner p -- llcorner p) fi enddef ; %D Nice too: primarydef p superellipsed s = - superellipse - (.5[lrcorner p,urcorner p], - .5[urcorner p,ulcorner p], - .5[ulcorner p,llcorner p], - .5[llcorner p,lrcorner p], - s) -enddef ; + superellipse ( + .5[lrcorner p,urcorner p], + .5[urcorner p,ulcorner p], + .5[ulcorner p,llcorner p], + .5[llcorner p,lrcorner p], + s + ) +enddef ; + +primarydef p squeezed s = ( + (llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) & + (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) & + (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) & + (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle +) enddef ; -primarydef p squeezed s = - ((llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) & - (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) & - (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) & - (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle) +primarydef p randomshifted s = + begingroup ; + save ss ; pair ss ; + ss := paired(s) ; + p shifted (-.5xpart ss + uniformdeviate xpart ss,-.5ypart ss + uniformdeviate ypart ss) + endgroup enddef ; -primarydef p randomshifted s = - begingroup ; save ss ; pair ss ; ss := paired(s) ; - p shifted (-.5xpart ss + uniformdeviate xpart ss, - -.5ypart ss + uniformdeviate ypart ss) - endgroup -enddef ; - -%primarydef p randomized s = -% for i=0 upto length(p)-1 : -% ((point i of p) randomshifted s) .. controls -% ((postcontrol i of p) randomshifted s) and -% ((precontrol (i+1) of p) randomshifted s) .. -% endfor cycle -%enddef ; - -primarydef p randomized s = - (if path p : - for i=0 upto length(p)-1 : - ((point i of p) randomshifted s) .. controls - ((postcontrol i of p) randomshifted s) and - ((precontrol (i+1) of p) randomshifted s) .. - endfor - if cycle p : - cycle - else : - ((point length(p) of p) randomshifted s) - fi - elseif pair p : - p randomshifted s - elseif cmykcolor p : - if color s : - (uniformdeviate cyanpart s * cyanpart p, - uniformdeviate magentapart s * magentapart p, - uniformdeviate yellowpart s * yellowpart p, - uniformdeviate blackpart s * blackpart p) - elseif pair s : - ((xpart s + uniformdeviate (ypart s - xpart s)) * p) - else : - (uniformdeviate s * p) - fi - elseif rgbcolor p : - if color s : - (uniformdeviate redpart s * redpart p, - uniformdeviate greenpart s * greenpart p, - uniformdeviate bluepart s * bluepart p) - elseif pair s : - ((xpart s + uniformdeviate (ypart s - xpart s)) * p) - else : - (uniformdeviate s * p) - fi - elseif color p : - if color s : - (uniformdeviate graypart s * graypart p) - elseif pair s : - ((xpart s + uniformdeviate (ypart s - xpart s)) * p) +primarydef p randomized s = ( + if path p : + for i=0 upto length(p)-1 : + ((point i of p) randomshifted s) .. controls + ((postcontrol i of p) randomshifted s) and + ((precontrol (i+1) of p) randomshifted s) .. + endfor + if cycle p : + cycle + else : + ((point length(p) of p) randomshifted s) + fi + elseif pair p : + p randomshifted s + elseif cmykcolor p : + if color s : + ((uniformdeviate cyanpart s) * cyanpart p, + (uniformdeviate magentapart s) * magentapart p, + (uniformdeviate yellowpart s) * yellowpart p, + (uniformdeviate blackpart s) * blackpart p) + elseif pair s : + ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) + else : + ((uniformdeviate s) * p) + fi + elseif rgbcolor p : + if color s : + ((uniformdeviate redpart s) * redpart p, + (uniformdeviate greenpart s) * greenpart p, + (uniformdeviate bluepart s) * bluepart p) + elseif pair s : + ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) + else : + ((uniformdeviate s) * p) + fi + elseif color p : + if color s : + ((uniformdeviate greypart s) * greypart p) + elseif pair s : + ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) + else : + ((uniformdeviate s) * p) + fi else : - (uniformdeviate s * p) + p + uniformdeviate s fi - else : - p + uniformdeviate s - fi) -enddef ; +) enddef ; %D Not perfect (alternative for interpath) vardef interpolated(expr s, p, q) = - save m ; m := max(length(p),length(q)) ; - (if path p : - for i=0 upto m-1 : - s[point (i /m) along p, - point (i /m) along q] .. controls - s[postcontrol (i /m) along p, - postcontrol (i /m) along q] and - s[precontrol ((i+1)/m) along p, - precontrol ((i+1)/m) along q] .. - endfor - if cycle p : - cycle - else : - s[point infinity of p, - point infinity of q] - fi - else : - a[p,q] - fi) + save m ; numeric m ; + m := max(length(p),length(q)) ; + if path p : + for i=0 upto m-1 : + s[point (i /m) along p,point (i /m) along q] .. controls + s[postcontrol (i /m) along p,postcontrol (i /m) along q] and + s[precontrol ((i+1)/m) along p,precontrol ((i+1)/m) along q] .. + endfor + if cycle p : + cycle + else : + s[point infinity of p,point infinity of q] + fi + else : + a[p,q] + fi enddef ; %D Interesting too: -% primarydef p parallel s = -% begingroup ; save q, b ; path q ; numeric b ; -% b := xpart (lrcorner p - llcorner p) ; -% q := p if b>0 : scaled ((b+2s)/b) fi ; -% (q shifted (center p-center q)) -% endgroup -% enddef ; - -%primarydef p parallel s = -% begingroup ; save q, w,h ; path q ; numeric w, h ; -% w := bbwidth(p) ; h := bbheight(p) ; -% q := p if (w>0) and (h>0) : -% xyscaled ((w+2*xpart paired(s))/w,(h+2*ypart paired(s))/h) fi ; -% (q shifted (center p-center q)) -% endgroup -%enddef ; - -primarydef p paralleled d = +primarydef p paralleled d = ( p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p) -enddef ; +) enddef ; vardef punked primary p = - (point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor - if cycle p : -- cycle else : -- point length(p) of p fi) + point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor + if cycle p : -- cycle else : -- point length(p) of p fi enddef ; vardef curved primary p = - (point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor - if cycle p : .. cycle else : .. point length(p) of p fi) + point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor + if cycle p : .. cycle else : .. point length(p) of p fi enddef ; primarydef p blownup s = - begingroup - save _p_ ; path _p_ ; _p_ := p xysized - (bbwidth (p)+2(xpart paired(s)), - bbheight(p)+2(ypart paired(s))) ; - (_p_ shifted (center p - center _p_)) - endgroup + begingroup + save _p_ ; path _p_ ; + _p_ := p xysized (bbwidth(p)+2(xpart paired(s)),bbheight(p)+2(ypart paired(s))) ; + (_p_ shifted (center p - center _p_)) + endgroup enddef ; %D Rather fundamental. % not yet ok -def leftrightpath(expr p, l) = % used in s-pre-19 - save q, r, t, b ; path q, r ; pair t, b ; - t := (ulcorner p -- urcorner p) intersection_point p ; - b := (llcorner p -- lrcorner p) intersection_point p ; - r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed - q := r cutbefore if l: t else: b fi ; - q := q if xpart point 0 of r > 0 : & - r fi cutafter if l: b else: t fi ; - q +vardef leftrightpath(expr p, l) = % used in s-pre-19 + save q, r, t, b ; path q, r ; pair t, b ; + t := (ulcorner p -- urcorner p) intersection_point p ; + b := (llcorner p -- lrcorner p) intersection_point p ; + r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed + q := r cutbefore if l: t else: b fi ; + q := q if xpart point 0 of r > 0 : & r fi cutafter if l: b else: t fi ; + q enddef ; vardef leftpath expr p = leftrightpath(p,true ) enddef ; @@ -1033,10 +1078,10 @@ vardef rightpath expr p = leftrightpath(p,false) enddef ; %D Drawoptions def saveoptions = - save _op_ ; def _op_ = enddef ; + save _op_ ; def _op_ = enddef ; enddef ; -%D Tracing. +%D Tracing. (not yet in lexer) let normaldraw = draw ; let normalfill = fill ; @@ -1046,7 +1091,6 @@ let normalfill = fill ; def normalfill expr c = addto currentpicture contour c _op_ enddef ; def normaldraw expr p = addto currentpicture if picture p: also p else: doublepath p withpen currentpen fi _op_ enddef ; - def drawlineoptions (text t) = def _lin_opt_ = t enddef ; enddef ; def drawpointoptions (text t) = def _pnt_opt_ = t enddef ; enddef ; def drawcontroloptions(text t) = def _ctr_opt_ = t enddef ; enddef ; @@ -1056,13 +1100,13 @@ def drawboundoptions (text t) = def _bnd_opt_ = t enddef ; enddef ; def drawpathoptions (text t) = def _pth_opt_ = t enddef ; enddef ; def resetdrawoptions = - drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ; - drawpointoptions (withpen pencircle scaled 4pt withcolor black) ; - drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ; - drawlabeloptions () ; - draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ; - drawboundoptions (dashed evenly _ori_opt_) ; - drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ; + drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ; + drawpointoptions (withpen pencircle scaled 4pt withcolor black) ; + drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ; + drawlabeloptions () ; + draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ; + drawboundoptions (dashed evenly _ori_opt_) ; + drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ; enddef ; resetdrawoptions ; @@ -1070,96 +1114,95 @@ resetdrawoptions ; %D Path. def drawpath expr p = - normaldraw p _pth_opt_ + normaldraw p _pth_opt_ enddef ; %D Arrow. vardef drawarrowpath expr p = - save autoarrows ; boolean autoarrows ; autoarrows := true ; - drawarrow p _pth_opt_ + save autoarrows ; boolean autoarrows ; autoarrows := true ; + drawarrow p _pth_opt_ enddef ; -%def drawarrowpath expr p = -% begingroup ; -% save autoarrows ; boolean autoarrows ; autoarrows := true ; -% save arrowpath ; path arrowpath ; arrowpath := p ; -% _drawarrowpath_ -%enddef ; +% def drawarrowpath expr p = +% begingroup ; +% save autoarrows ; boolean autoarrows ; autoarrows := true ; +% save arrowpath ; path arrowpath ; arrowpath := p ; +% _drawarrowpath_ +% enddef ; % -%def _drawarrowpath_ text t = -% drawarrow arrowpath _pth_opt_ t ; -% endgroup ; -%enddef ; +% def _drawarrowpath_ text t = +% drawarrow arrowpath _pth_opt_ t ; +% endgroup ; +% enddef ; def midarrowhead expr p = - arrowhead p cutafter - (point length(p cutafter point .5 along p)+ahlength on p) + arrowhead p cutafter (point length(p cutafter point .5 along p)+ahlength on p) enddef ; vardef arrowheadonpath (expr p, s) = - save autoarrows ; boolean autoarrows ; autoarrows := true ; - set_ahlength(scaled ahfactor) ; % added - arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi + save autoarrows ; boolean autoarrows ; + autoarrows := true ; + set_ahlength(scaled ahfactor) ; % added + arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi enddef ; %D Points. def drawpoint expr c = - if string c : - string _c_ ; _c_ := "(" & c & ")" ; - dotlabel.urt(_c_, scantokens _c_) ; - drawdot scantokens _c_ - else : - dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ; - drawdot c - fi _pnt_opt_ + if string c : + string _c_ ; + _c_ := "(" & c & ")" ; + dotlabel.urt(_c_, scantokens _c_) ; + drawdot scantokens _c_ + else : + dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ; + drawdot c + fi _pnt_opt_ enddef ; %D PathPoints. -def drawpoints expr c = path _c_ ; _c_ := c ; do_drawpoints enddef ; -def drawcontrolpoints expr c = path _c_ ; _c_ := c ; do_drawcontrolpoints enddef ; -def drawcontrollines expr c = path _c_ ; _c_ := c ; do_drawcontrollines enddef ; -def drawpointlabels expr c = path _c_ ; _c_ := c ; do_drawpointlabels enddef ; +def drawpoints expr c = path _c_ ; _c_ := c ; mfun_draw_points enddef ; +def drawcontrolpoints expr c = path _c_ ; _c_ := c ; mfun_draw_controlpoints enddef ; +def drawcontrollines expr c = path _c_ ; _c_ := c ; mfun_draw_controllines enddef ; +def drawpointlabels expr c = path _c_ ; _c_ := c ; mfun_draw_pointlabels enddef ; -def do_drawpoints text t = - for _i_=0 upto length(_c_) : - normaldraw point _i_ of _c_ _pnt_opt_ t ; - endfor ; +def mfun_draw_points text t = + for _i_=0 upto length(_c_) : + normaldraw point _i_ of _c_ _pnt_opt_ t ; + endfor ; enddef; -def do_drawcontrolpoints text t = - for _i_=0 upto length(_c_) : - normaldraw precontrol _i_ of _c_ _ctr_opt_ t ; - normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ; - endfor ; +def mfun_draw_controlpoints text t = + for _i_=0 upto length(_c_) : + normaldraw precontrol _i_ of _c_ _ctr_opt_ t ; + normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ; + endfor ; enddef; -def do_drawcontrollines text t = - for _i_=0 upto length(_c_) : - normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ; - normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ; - endfor ; +def mfun_draw_controllines text t = + for _i_=0 upto length(_c_) : + normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ; + normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ; + endfor ; enddef; boolean swappointlabels ; swappointlabels := false ; -def do_drawpointlabels text t = - for _i_=0 upto length(_c_) : - pair _u_ ; _u_ := unitvector(direction _i_ of _c_) - rotated if swappointlabels : - fi 90 ; - pair _p_ ; _p_ := (point _i_ of _c_) ; - _u_ := 12 * defaultscale * _u_ ; - normaldraw thelabel ( decimal _i_, - _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ; - endfor ; +def mfun_draw_pointlabels text t = + for _i_=0 upto length(_c_) : + pair _u_ ; _u_ := unitvector(direction _i_ of _c_) rotated if swappointlabels : - fi 90 ; + pair _p_ ; _p_ := (point _i_ of _c_) ; + _u_ := 12 * defaultscale * _u_ ; + normaldraw thelabel ( decimal _i_, _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ; + endfor ; enddef; %D Bounding box. def drawboundingbox expr p = - normaldraw boundingbox p _bnd_opt_ + normaldraw boundingbox p _bnd_opt_ enddef ; %D Origin. @@ -1167,10 +1210,8 @@ enddef ; numeric originlength ; originlength := .5cm ; def draworigin text t = - normaldraw (origin shifted (0, originlength) -- - origin shifted (0,-originlength)) _ori_opt_ t ; - normaldraw (origin shifted ( originlength,0) -- - origin shifted (-originlength,0)) _ori_opt_ t ; + normaldraw (origin shifted (0, originlength) -- origin shifted (0,-originlength)) _ori_opt_ t ; + normaldraw (origin shifted ( originlength,0) -- origin shifted (-originlength,0)) _ori_opt_ t ; enddef; %D Axis. @@ -1178,101 +1219,108 @@ enddef; numeric tickstep ; tickstep := 5mm ; numeric ticklength ; ticklength := 2mm ; -def drawxticks expr c = path _c_ ; _c_ := c ; do_drawxticks enddef ; -def drawyticks expr c = path _c_ ; _c_ := c ; do_drawyticks enddef ; -def drawticks expr c = path _c_ ; _c_ := c ; do_drawticks enddef ; +def drawxticks expr c = path _c_ ; _c_ := c ; mfun_draw_xticks enddef ; +def drawyticks expr c = path _c_ ; _c_ := c ; mfun_draw_yticks enddef ; +def drawticks expr c = path _c_ ; _c_ := c ; mfun_draw_ticks enddef ; % Adding eps prevents disappearance due to rounding errors. -def do_drawxticks text t = - for i=0 step -tickstep until xpart llcorner _c_ - eps : - if (i<=xpart lrcorner _c_) : - normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; - fi ; - endfor ; - for i=0 step tickstep until xpart lrcorner _c_ + eps : - if (i>=xpart llcorner _c_) : - normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; - fi ; - endfor ; - normaldraw (llcorner _c_ -- ulcorner _c_) - shifted (-xpart llcorner _c_,0) _ori_opt_ t ; +def mfun_draw_xticks text t = + for i=0 step -tickstep until xpart llcorner _c_ - eps : + if (i<=xpart lrcorner _c_) : + normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; + fi ; + endfor ; + for i=0 step tickstep until xpart lrcorner _c_ + eps : + if (i>=xpart llcorner _c_) : + normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; + fi ; + endfor ; + normaldraw (llcorner _c_ -- ulcorner _c_) shifted (-xpart llcorner _c_,0) _ori_opt_ t ; enddef ; -def do_drawyticks text t = - for i=0 step -tickstep until ypart llcorner _c_ - eps : - if (i<=ypart ulcorner _c_) : - normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; - fi ; - endfor ; - for i=0 step tickstep until ypart ulcorner _c_ + eps : - if (i>=ypart llcorner _c_) : - normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; - fi ; - endfor ; - normaldraw (llcorner _c_ -- lrcorner _c_) - shifted (0,-ypart llcorner _c_) _ori_opt_ t ; +def mfun_draw_yticks text t = + for i=0 step -tickstep until ypart llcorner _c_ - eps : + if (i<=ypart ulcorner _c_) : + normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; + fi ; + endfor ; + for i=0 step tickstep until ypart ulcorner _c_ + eps : + if (i>=ypart llcorner _c_) : + normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; + fi ; + endfor ; + normaldraw (llcorner _c_ -- lrcorner _c_) shifted (0,-ypart llcorner _c_) _ori_opt_ t ; enddef ; -def do_drawticks text t = - drawxticks _c_ t ; - drawyticks _c_ t ; +def mfun_draw_ticks text t = + drawxticks _c_ t ; + drawyticks _c_ t ; enddef ; %D All of it except axis. def drawwholepath expr p = - draworigin ; - drawpath p ; - drawcontrollines p ; - drawcontrolpoints p ; - drawpoints p ; - drawboundingbox p ; - drawpointlabels p ; + draworigin ; + drawpath p ; + drawcontrollines p ; + drawcontrolpoints p ; + drawpoints p ; + drawboundingbox p ; + drawpointlabels p ; enddef ; %D Tracing. def visualizeddraw expr c = - if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi + if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi enddef ; def visualizedfill expr c = - if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi + if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi enddef ; def do_visualizeddraw text t = - draworigin ; - drawpath _c_ t ; - drawcontrollines _c_ ; - drawcontrolpoints _c_ ; - drawpoints _c_ ; - drawboundingbox _c_ ; - drawpointlabels _c_ ; + draworigin ; + drawpath _c_ t ; + drawcontrollines _c_ ; + drawcontrolpoints _c_ ; + drawpoints _c_ ; + drawboundingbox _c_ ; + drawpointlabels _c_ ; enddef ; def do_visualizedfill text t = - if cycle _c_ : normalfill _c_ t fi ; - draworigin ; - drawcontrollines _c_ ; - drawcontrolpoints _c_ ; - drawpoints _c_ ; - drawboundingbox _c_ ; - drawpointlabels _c_ ; + if cycle _c_ : normalfill _c_ t fi ; + draworigin ; + drawcontrollines _c_ ; + drawcontrolpoints _c_ ; + drawpoints _c_ ; + drawboundingbox _c_ ; + drawpointlabels _c_ ; enddef ; def visualizepaths = - let fill = visualizedfill ; - let draw = visualizeddraw ; + let fill = visualizedfill ; + let draw = visualizeddraw ; enddef ; def naturalizepaths = - let fill = normalfill ; - let draw = normaldraw ; + let fill = normalfill ; + let draw = normaldraw ; enddef ; extra_endfig := extra_endfig & " naturalizepaths ; " ; +%D Nice tracer: + +def drawboundary primary p = + draw p dashed evenly withcolor white ; + draw p dashed oddly withcolor black ; + draw (- llcorner p) withpen pencircle scaled 3 withcolor white ; + draw (- llcorner p) withpen pencircle scaled 1.5 withcolor black ; +enddef ; + %D Also handy: extra_beginfig := extra_beginfig & " truecorners := 0 ; " ; % restores @@ -1287,46 +1335,57 @@ boolean autoarrows ; autoarrows := false ; numeric ahfactor ; ahfactor := 2.5 ; def set_ahlength (text t) = -% ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added -% problem: _op_ can contain color so a no-go, we could apply the transform -% but i need to figure out the best way (fakepicture and take components). - ahlength := (ahfactor*pen_size(t)) ; + % ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added + % problem: _op_ can contain color so a no-go, we could apply the transform + % but i need to figure out the best way (fakepicture and take components). + ahlength := (ahfactor*pen_size(t)) ; enddef ; vardef pen_size (text t) = - save p ; picture p ; p := nullpicture ; - addto p doublepath (top origin -- bot origin) t ; - (ypart urcorner p - ypart lrcorner p) + save p ; picture p ; p := nullpicture ; + addto p doublepath (top origin -- bot origin) t ; + (ypart urcorner p - ypart lrcorner p) enddef ; %D The next two macros are adapted versions of plain %D \METAPOST\ definitions. +vardef arrowpath expr p = % patch by Peter Rolf: supports squared pen and shifting (hh: maybe just use center of head as first) + (p cutafter makepath(pencircle scaled 2(ahlength*cosd(.5ahangle)) shifted point length p of p)) +enddef; + +% def _finarr text t = +% if autoarrows : set_ahlength (t) fi ; +% draw arrowpath _apth t ; % arrowpath added +% filldraw arrowhead _apth t ; +% enddef; + def _finarr text t = - if autoarrows : set_ahlength (t) fi ; - draw _apth t ; - filldraw arrowhead _apth t ; + if autoarrows : set_ahlength (t) fi ; + draw arrowpath _apth t ; % arrowpath added + fill arrowhead _apth t ; + draw arrowhead _apth t ; enddef; -def _findarr text t = - if autoarrows : set_ahlength (t) fi ; - draw _apth t ; - fill arrowhead _apth withpen currentpen t ; - fill arrowhead reverse _apth withpen currentpen t ; -enddef ; +def _finarr text t = + if autoarrows : set_ahlength (t) fi ; + draw arrowpath _apth t ; % arrowpath added + fill arrowhead _apth t ; + draw arrowhead _apth t undashed ; +enddef; %D Handy too ...... vardef pointarrow (expr pat, loc, len, off) = - save l, r, s, t ; path l, r ; numeric s ; pair t ; - t := if pair loc : loc else : point loc along pat fi ; - s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ; - r := pat cutbefore t ; - r := (r cutafter point (arctime s of r) of r) ; - s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ; - l := reverse (pat cutafter t) ; - l := (reverse (l cutafter point (arctime s of l) of l)) ; - (l..r) + save l, r, s, t ; path l, r ; numeric s ; pair t ; + t := if pair loc : loc else : point loc along pat fi ; + s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ; + r := pat cutbefore t ; + r := (r cutafter point (arctime s of r) of r) ; + s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ; + l := reverse (pat cutafter t) ; + l := (reverse (l cutafter point (arctime s of l) of l)) ; + (l..r) enddef ; def rightarrow (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ; @@ -1336,23 +1395,19 @@ def centerarrow (expr pat,tim,len) = pointarrow(pat,tim,len, 0) enddef ; %D The \type {along} and \type {on} operators can be used %D as follows: %D -%D \starttypen +%D \starttyping %D drawdot point .5 along somepath ; %D drawdot point 3cm on somepath ; -%D \stoptypen +%D \stoptyping %D %D The number denotes a percentage (fraction). primarydef pct along pat = % also negative - (arctime (pct * (arclength pat)) of pat) of pat + (arctime (pct * (arclength pat)) of pat) of pat enddef ; -% primarydef len on pat = -% (arctime len of pat) of pat -% enddef ; - -primarydef len on pat = - (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat +primarydef len on pat = % no outer ( ) .. somehow fails + (arctime if len>=0 : len else : (arclength(pat)+len) fi of pat) of pat enddef ; % this cuts of a piece from both ends @@ -1365,69 +1420,55 @@ enddef ; % enddef ; tertiarydef pat cutends len = - begingroup ; save tap ; path tap ; - tap := pat cutbefore (point (xpart paired(len)) on pat) ; - (tap cutafter (point -(ypart paired(len)) on tap)) - endgroup + begingroup + save tap ; path tap ; + tap := pat cutbefore (point (xpart paired(len)) on pat) ; + (tap cutafter (point -(ypart paired(len)) on tap)) + endgroup enddef ; %D To be documented. path freesquare ; -freesquare := ((-1,0)--(-1,-1)--(0,-1)--(+1,-1)-- - (+1,0)--(+1,+1)--(0,+1)--(-1,+1)--cycle) scaled .5 ; +freesquare := ( + (-1,0) -- (-1,-1) -- (0,-1) -- (+1,-1) -- + (+1,0) -- (+1,+1) -- (0,+1) -- (-1,+1) -- cycle +) scaled .5 ; numeric freelabeloffset ; freelabeloffset := 3pt ; numeric freedotlabelsize ; freedotlabelsize := 3pt ; vardef thefreelabel (expr str, loc, ori) = - save s, p, q, l ; picture s ; path p, q ; pair l ; - interim labeloffset := freelabeloffset ; - s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; - setbounds s to boundingbox s enlarged freelabeloffset ; - p := fullcircle scaled (2*length(loc-ori)) shifted ori ; - q := freesquare xyscaled (urcorner s - llcorner s) ; -% l := point (xpart (p intersectiontimes (ori--loc))) of q ; - l := point xpart (p intersectiontimes - (ori--((1+eps)*arclength(ori--loc)*unitvector(loc-ori)))) of q ; - setbounds s to boundingbox s enlarged -freelabeloffset ; % new - %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; - (s shifted -l) -enddef ; - -% better? - -vardef thefreelabel (expr str, loc, ori) = - save s, p, q, l ; picture s ; path p, q ; pair l ; - interim labeloffset := freelabeloffset ; - s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; - setbounds s to boundingbox s enlarged freelabeloffset ; - p := fullcircle scaled (2*length(loc-ori)) shifted ori ; - q := freesquare xyscaled (urcorner s - llcorner s) ; - l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ; - setbounds s to boundingbox s enlarged -freelabeloffset ; % new - %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; - (s shifted -l) + save s, p, q, l ; picture s ; path p, q ; pair l ; + interim labeloffset := freelabeloffset ; + s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; + setbounds s to boundingbox s enlarged freelabeloffset ; + p := fullcircle scaled (2*length(loc-ori)) shifted ori ; + q := freesquare xyscaled (urcorner s - llcorner s) ; + l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ; + setbounds s to boundingbox s enlarged -freelabeloffset ; % new + % draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; + (s shifted -l) enddef ; vardef freelabel (expr str, loc, ori) = - draw thefreelabel(str,loc,ori) ; + draw thefreelabel(str,loc,ori) ; enddef ; vardef freedotlabel (expr str, loc, ori) = - interim linecap:=rounded ; - draw loc withpen pencircle scaled freedotlabelsize ; - draw thefreelabel(str,loc,ori) ; + interim linecap := rounded ; + draw loc withpen pencircle scaled freedotlabelsize ; + draw thefreelabel(str,loc,ori) ; enddef ; -%D \starttypen +%D \starttyping %D drawarrow anglebetween(line_a,line_b,somelabel) ; -%D \stoptypen +%D \stoptyping -% angleoffset ; angleoffset := 0pt ; -numeric anglelength ; anglelength := 20pt ; -numeric anglemethod ; anglemethod := 1 ; +newinternal angleoffset ; angleoffset := 0pt ; +newinternal anglelength ; anglelength := 20pt ; +newinternal anglemethod ; anglemethod := 1 ; % vardef anglebetween (expr a, b, str) = % path path string % save pointa, pointb, common, middle, offset ; @@ -1466,63 +1507,66 @@ numeric anglemethod ; anglemethod := 1 ; % enddef ; vardef anglebetween (expr a, b, str) = % path path string - save pointa, pointb, common, middle, offset ; - pair pointa, pointb, common, middle, offset ; - save curve ; path curve ; - save where ; numeric where ; - if round point 0 of a = round point 0 of b : - common := point 0 of a ; - else : - common := a intersectionpoint b ; - fi ; - pointa := point anglelength on a ; - pointb := point anglelength on b ; - where := turningnumber (common--pointa--pointb--cycle) ; - middle := (reverse(common--pointa) rotatedaround (pointa,-where*90)) - intersection_point - (reverse(common--pointb) rotatedaround (pointb, where*90)) ; - if not intersection_found : - middle := point .5 along - ((reverse(common--pointa) rotatedaround (pointa,-where*90)) -- - ( (common--pointb) rotatedaround (pointb, where*90))) ; - fi ; - if anglemethod = 0 : - curve := pointa{unitvector(middle-pointa)}.. pointb; - middle := point .5 along curve ; - curve := common ; - elseif anglemethod = 1 : - curve := pointa{unitvector(middle-pointa)}.. pointb; - middle := point .5 along curve ; - elseif anglemethod = 2 : - middle := common rotatedaround(.5[pointa,pointb],180) ; - curve := pointa--middle--pointb ; - elseif anglemethod = 3 : - curve := pointa--middle--pointb ; - elseif anglemethod = 4 : - curve := pointa..controls middle..pointb ; - middle := point .5 along curve ; - fi ; - draw thefreelabel(str, middle, common) ; % withcolor black ; - curve + save pointa, pointb, common, middle, offset ; + pair pointa, pointb, common, middle, offset ; + save curve ; path curve ; + save where ; numeric where ; + if round point 0 of a = round point 0 of b : + common := point 0 of a ; + else : + common := a intersectionpoint b ; + fi ; + pointa := point anglelength on a ; + pointb := point anglelength on b ; + where := turningnumber (common--pointa--pointb--cycle) ; + middle := (reverse(common--pointa) rotatedaround (pointa,-where*90)) + intersection_point + (reverse(common--pointb) rotatedaround (pointb, where*90)) ; + if not intersection_found : + middle := point .5 along + ((reverse(common--pointa) rotatedaround (pointa,-where*90)) -- + ( (common--pointb) rotatedaround (pointb, where*90))) ; + fi ; + if anglemethod = 0 : + curve := pointa{unitvector(middle-pointa)}.. pointb; + middle := point .5 along curve ; + curve := common ; + elseif anglemethod = 1 : + curve := pointa{unitvector(middle-pointa)}.. pointb; + middle := point .5 along curve ; + elseif anglemethod = 2 : + middle := common rotatedaround(.5[pointa,pointb],180) ; + curve := pointa--middle--pointb ; + elseif anglemethod = 3 : + curve := pointa--middle--pointb ; + elseif anglemethod = 4 : + curve := pointa..controls middle..pointb ; + middle := point .5 along curve ; + fi ; + draw thefreelabel(str, middle, common) ; % withcolor black ; + curve enddef ; % Stack -picture currentpicturestack[] ; -numeric currentpicturedepth ; currentpicturedepth := 0 ; +picture mfun_current_picture_stack[] ; +numeric mfun_current_picture_depth ; + +mfun_current_picture_depth := 0 ; def pushcurrentpicture = - currentpicturedepth := currentpicturedepth + 1 ; - currentpicturestack[currentpicturedepth] := currentpicture ; - currentpicture := nullpicture ; + mfun_current_picture_depth := mfun_current_picture_depth + 1 ; + mfun_current_picture_stack[mfun_current_picture_depth] := currentpicture ; + currentpicture := nullpicture ; enddef ; def popcurrentpicture text t = % optional text - if currentpicturedepth > 0 : - addto currentpicturestack[currentpicturedepth] also currentpicture t ; - currentpicture := currentpicturestack[currentpicturedepth] ; - currentpicturedepth := currentpicturedepth - 1 ; - fi ; + if mfun_current_picture_depth > 0 : + addto mfun_current_picture_stack[mfun_current_picture_depth] also currentpicture t ; + currentpicture := mfun_current_picture_stack[mfun_current_picture_depth] ; + mfun_current_picture_stack[mfun_current_picture_depth] := nullpicture ; + mfun_current_picture_depth := mfun_current_picture_depth - 1 ; + fi ; enddef ; %D colorcircle(size, red, green, blue) ; @@ -1603,71 +1647,76 @@ enddef ; % popcurrentpicture ; % enddef ; -vardef colorcircle (expr size, red, green, blue) = - save r, g, b, c, m, y, w ; save radius ; - path r, g, b, c, m, y, w ; numeric radius ; +vardef colorcircle (expr size, red, green, blue) = % might move + save r, g, b, c, m, y, w ; save radius ; + path r, g, b, c, m, y, w ; numeric radius ; - radius := 5cm ; pickup pencircle scaled (radius/25) ; + radius := 5cm ; pickup pencircle scaled (radius/25) ; - transform t ; t := identity rotatedaround(origin,120) ; + transform t ; t := identity rotatedaround(origin,120) ; - r := fullcircle rotated 90 scaled radius - shifted (0,radius/4) rotatedaround(origin,135) ; + r := fullcircle rotated 90 scaled radius shifted (0,radius/4) rotatedaround(origin,135) ; - b := r transformed t ; g := b transformed t ; + b := r transformed t ; g := b transformed t ; - c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ; - y := c transformed t ; m := y transformed t ; + c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ; + y := c transformed t ; m := y transformed t ; - w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ; + w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ; - pushcurrentpicture ; + pushcurrentpicture ; - fill r withcolor red ; - fill g withcolor green ; - fill b withcolor blue ; - fill c withcolor white-red ; - fill m withcolor white-green ; - fill y withcolor white-blue ; - fill w withcolor white ; + fill r withcolor red ; + fill g withcolor green ; + fill b withcolor blue ; + fill c withcolor white - red ; + fill m withcolor white - green ; + fill y withcolor white - blue ; + fill w withcolor white ; - for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ; + for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ; - currentpicture := currentpicture xsized size ; + currentpicture := currentpicture xsized size ; - popcurrentpicture ; + popcurrentpicture ; enddef ; % penpoint (i,2) of somepath -> inner / outer point vardef penpoint expr pnt of p = - save n, d ; numeric n, d ; - (n,d) = if pair pnt : pnt else : (pnt,1) fi ; - (point n of p shifted ((penoffset direction n of p of currentpen) scaled d)) + save n, d ; numeric n, d ; + (n,d) = if pair pnt : pnt else : (pnt,1) fi ; + (point n of p shifted ((penoffset direction n of p of currentpen) scaled d)) enddef ; % nice: currentpicture := inverted currentpicture ; primarydef p uncolored c = - if color p : - c - p - else : - image - (for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : contour else : doublepath fi pathpart i - dashed dashpart i withpen penpart i - else : - also i - fi - withcolor c-(redpart i, greenpart i, bluepart i) ; - endfor ; ) + if color p : + c - p + else : + image ( + for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : + contour + else : + doublepath + fi + pathpart i + dashed dashpart i withpen penpart i + else : + also i + fi + withcolor c-(redpart i, greenpart i, bluepart i) ; + endfor ; + ) fi enddef ; vardef inverted primary p = - (p uncolored white) + p uncolored white enddef ; % primarydef p softened c = @@ -1692,45 +1741,54 @@ enddef ; % enddef ; primarydef p softened c = - begingroup - save cc ; color cc ; cc := tripled(c) ; - if color p : - (redpart cc * redpart p, - greenpart cc * greenpart p, - bluepart cc * bluepart p) - else : - image - (for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : contour else : doublepath fi pathpart i - dashed dashpart i withpen penpart i - else : - also i - fi - withcolor (redpart cc * redpart i, - greenpart cc * greenpart i, - bluepart cc * bluepart i) ; - endfor ;) - fi - endgroup + begingroup + save cc ; color cc ; cc := tripled(c) ; + if color p : + (redpart cc * redpart p,greenpart cc * greenpart p, bluepart cc * bluepart p) + else : + image ( + for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : + contour + else : + doublepath + fi + pathpart i + dashed dashpart i withpen penpart i + else : + also i + fi + withcolor (redpart cc * redpart i, greenpart cc * greenpart i, bluepart cc * bluepart i) ; + endfor ; + ) + fi + endgroup enddef ; vardef grayed primary p = - if color p : - tripled(.30redpart p+.59greenpart p+.11bluepart p) - else : - image - (for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : contour else : doublepath fi pathpart i - dashed dashpart i withpen penpart i - else : - also i - fi - withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; - endfor ; ) + if color p : + tripled(.30redpart p+.59greenpart p+.11bluepart p) + else : + image ( + for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : + contour + else : + doublepath + fi + pathpart i + dashed dashpart i + withpen penpart i + else : + also i + fi + withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; + endfor ; + ) fi enddef ; @@ -1758,10 +1816,10 @@ def condition primary b = if b : "true" else : "false" fi enddef ; % undocumented primarydef p stretched s = - begingroup - save pp ; path pp ; pp := p xyscaled s ; - (pp shifted ((point 0 of p) - (point 0 of pp))) - endgroup + begingroup + save pp ; path pp ; pp := p xyscaled s ; + (pp shifted ((point 0 of p) - (point 0 of pp))) + endgroup enddef ; % primarydef p enlonged len = @@ -1833,40 +1891,40 @@ def yshifted expr dy = shifted(0,dy) enddef ; % def readfile (expr name) = - begingroup ; save ok ; boolean ok ; - if (readfrom (name) <> EOF) : - ok := false ; - elseif (readfrom (name) <> EOF) : - ok := false ; - else : - ok := true ; - fi ; - if not ok : - scantokens("input " & name & " ") ; - fi ; - closefrom (name) ; - endgroup ; + begingroup ; save ok ; boolean ok ; + if (readfrom (name) <> EOF) : + ok := false ; + elseif (readfrom (name) <> EOF) : + ok := false ; + else : + ok := true ; + fi ; + if not ok : + scantokens("input " & name & " ") ; + fi ; + closefrom (name) ; + endgroup ; enddef ; % permits redefinition of end in macro inner end ; -% real fun +% this will be redone (when needed) using scripts and backend handling let normalwithcolor = withcolor ; def remapcolors = - def withcolor primary c = normalwithcolor remappedcolor(c) enddef ; + def withcolor primary c = normalwithcolor remappedcolor(c) enddef ; enddef ; def normalcolors = - let withcolor = normalwithcolor ; + let withcolor = normalwithcolor ; enddef ; def resetcolormap = - color color_map[][][] ; - normalcolors ; + color color_map[][][] ; + normalcolors ; enddef ; resetcolormap ; @@ -1882,15 +1940,15 @@ def g_color primary c = greenpart c enddef ; def b_color primary c = bluepart c enddef ; def remapcolor(expr old, new) = - color_map[r_color old][g_color old][b_color old] := new ; + color_map[redpart old][greenpart old][bluepart old] := new ; enddef ; def remappedcolor(expr c) = - if known color_map[r_color c][g_color c][b_color c] : - color_map[r_color c][g_color c][b_color c] - else : - c - fi + if known color_map[redpart c][greenpart c][bluepart c] : + color_map[redpart c][greenpart c][bluepart c] + else : + c + fi enddef ; % def refill suffix c = do_repath (1) (c) enddef ; @@ -1930,11 +1988,11 @@ enddef ; % Thanks to Jens-Uwe Morawski for pointing out that we need % to treat bounded and clipped components as local pictures. -def recolor suffix p = p := repathed (0,p) enddef ; -def refill suffix p = p := repathed (1,p) enddef ; -def redraw suffix p = p := repathed (2,p) enddef ; -def retext suffix p = p := repathed (3,p) enddef ; -def untext suffix p = p := repathed (4,p) enddef ; +def recolor suffix p = p := repathed (0,p) enddef ; +def refill suffix p = p := repathed (1,p) enddef ; +def redraw suffix p = p := repathed (2,p) enddef ; +def retext suffix p = p := repathed (3,p) enddef ; +def untext suffix p = p := repathed (4,p) enddef ; % primarydef p recolored t = repathed(0,p) t enddef ; % primarydef p refilled t = repathed(1,p) t enddef ; @@ -1997,69 +2055,80 @@ def reprocess suffix p = p := repathed (22,p) enddef ; % no attributes % also 11 and 12 vardef repathed (expr mode, p) text t = - begingroup ; - if mode=0 : save withcolor ; remapcolors ; fi ; - save _p_, _pp_, _ppp_, _f_, _b_, _t_ ; - picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ; - _b_ := boundingbox p ; _p_ := nullpicture ; - for i within p : - _f_ := (redpart i, greenpart i, bluepart i) ; - if bounded i : - _pp_ := repathed(mode,i) t ; - setbounds _pp_ to pathpart i ; - addto _p_ also _pp_ ; - elseif clipped i : - _pp_ := repathed(mode,i) t ; - clip _pp_ to pathpart i ; - addto _p_ also _pp_ ; - elseif stroked i : - if mode=21 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_") - dashed dashpart i withpen penpart i - withcolor _f_ ; ) ; - elseif mode=22 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; - else : - addto _p_ doublepath pathpart i - dashed dashpart i withpen penpart i - withcolor _f_ % (redpart i, greenpart i, bluepart i) - if mode=2 : t fi ; - fi ; - elseif filled i : - if mode=11 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_") - withcolor _f_ ; ) ; - elseif mode=12 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; - else : - addto _p_ contour pathpart i - withcolor _f_ - if (mode=1) and (_f_<>refillbackground) : t fi ; - fi ; - elseif textual i : % textpart i <> "" : - if mode <> 4 : - % transform _t_ ; - % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ; - % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ; - % addto _p_ also - % textpart i infont fontpart i % todo : other font - % transformed _t_ - % withpen penpart i - % withcolor _f_ - % if mode=3 : t fi ; - addto _p_ also i if mode=3 : t fi ; - fi ; - else : - addto _p_ also i ; + begingroup ; + if mode = 0 : + save withcolor ; + remapcolors ; fi ; - endfor ; - setbounds _p_ to _b_ ; - _p_ - endgroup + save _p_, _pp_, _ppp_, _f_, _b_, _t_ ; + picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ; + _b_ := boundingbox p ; + _p_ := nullpicture ; + for i within p : + _f_ := (redpart i, greenpart i, bluepart i) ; + if bounded i : + _pp_ := repathed(mode,i) t ; + setbounds _pp_ to pathpart i ; + addto _p_ also _pp_ ; + elseif clipped i : + _pp_ := repathed(mode,i) t ; + clip _pp_ to pathpart i ; + addto _p_ also _pp_ ; + elseif stroked i : + if mode=21 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_") + dashed dashpart i withpen penpart i + withcolor _f_ ; ) ; + elseif mode=22 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; + else : + addto _p_ doublepath pathpart i + dashed dashpart i withpen penpart i + withcolor _f_ % (redpart i, greenpart i, bluepart i) + if mode = 2 : + t + fi ; + fi ; + elseif filled i : + if mode=11 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_") + withcolor _f_ ; ) ; + elseif mode=12 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; + else : + addto _p_ contour pathpart i + withcolor _f_ + if (mode=1) and (_f_<>refillbackground) : + t + fi ; + fi ; + elseif textual i : % textpart i <> "" : + if mode <> 4 : + % transform _t_ ; + % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ; + % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ; + % addto _p_ also + % textpart i infont fontpart i % todo : other font + % transformed _t_ + % withpen penpart i + % withcolor _f_ + % if mode=3 : t fi ; + addto _p_ also i + if mode=3 : + t + fi ; + fi ; + else : + addto _p_ also i ; + fi ; + endfor ; + setbounds _p_ to _b_ ; + _p_ + endgroup enddef ; % After a question of Denis on how to erase a z variable, Jacko @@ -2087,11 +2156,11 @@ enddef ; % which i decided to simplify to: def clearxy text s = - if false for $ := s : or true endfor : - forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ; - else : - save x, y ; - fi + if false for $ := s : or true endfor : + forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ; + else : + save x, y ; + fi enddef ; % so now we can say: clearxy ; as well as clearxy 1, 2, 3 ; @@ -2103,48 +2172,68 @@ enddef ; % show x0 ; z0 = (30,30) ; primarydef p smoothed d = - (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} .. - p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} .. - p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} .. - p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle) + (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} .. + p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} .. + p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} .. + p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle) enddef ; primarydef p cornered c = - ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) -- - for i=1 upto length(p) : - (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) -- - (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) .. - controls point i of p .. - endfor cycle) + ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) -- + for i=1 upto length(p) : + (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) -- + (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) .. + controls point i of p .. + endfor cycle) enddef ; % cmyk color support vardef cmyk(expr c,m,y,k) = - (1-c-k,1-m-k,1-y-k) + (1-c-k,1-m-k,1-y-k) enddef ; % handy -vardef bbwidth (expr p) = % vardef width_of primary p = - if known p : - if path p or picture p : - xpart (lrcorner p - llcorner p) - else : - 0 - fi +% vardef bbwidth (expr p) = % vardef width_of primary p = +% if known p : +% if path p or picture p : +% xpart (lrcorner p - llcorner p) +% else : +% 0 +% fi +% else : +% 0 +% fi +% enddef ; + +vardef bbwidth primary p = + if unknown p : + 0 + elseif path p or picture p : + xpart (lrcorner p - llcorner p) else : 0 fi enddef ; -vardef bbheight (expr p) = % vardef heigth_of primary p = - if known p : - if path p or picture p : - ypart (urcorner p - lrcorner p) - else : - 0 - fi +% vardef bbheight (expr p) = % vardef heigth_of primary p = +% if known p : +% if path p or picture p : +% ypart (urcorner p - lrcorner p) +% else : +% 0 +% fi +% else : +% 0 +% fi +% enddef ; + +vardef bbheight primary p = + if unknown p : + 0 + elseif path p or picture p : + ypart (urcorner p - lrcorner p) else : 0 fi @@ -2153,122 +2242,87 @@ enddef ; color nocolor ; numeric noline ; % both unknown signals def dowithpath (expr p, lw, lc, bc) = - if known p : - if known bc : - fill p withcolor bc ; - fi ; - if known lw and known lc : - draw p withpen pencircle scaled lw withcolor lc ; - elseif known lw : - draw p withpen pencircle scaled lw ; - elseif known lc : - draw p withcolor lc ; + if known p : + if known bc : + fill p withcolor bc ; + fi ; + if known lw and known lc : + draw p withpen pencircle scaled lw withcolor lc ; + elseif known lw : + draw p withpen pencircle scaled lw ; + elseif known lc : + draw p withcolor lc ; + fi ; fi ; - fi ; enddef ; % result from metafont discussion list (denisr/boguslawj) -def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ; -def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ; +def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ; +def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ; -% not perfect, but useful since it removes redundant points. +let == = = ; -% vardef dostraightened(expr sign, p) = -% if length(p)>2 : % was 1, but straight lines are ok -% save pp ; path pp ; -% pp := point 0 of p ; -% for i=1 upto length(p)-1 : -% if round(point i of p) <> round(point length(pp) of pp) : -% pp := pp -- point i of p ; -% fi ; -% endfor ; -% save n, ok ; numeric n ; boolean ok ; -% n := length(pp) ; ok := false ; -% if n>2 : -% for i=0 upto n : % evt hier ook round -% if unitvector(round(point i of pp - -% point if i=0 : n else : i-1 fi of pp)) <> -% sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - -% point i of pp)) : -% if ok : -- else : ok := true ; fi point i of pp -% fi -% endfor -% if ok and (cycle p) : -- cycle fi -% else : -% pp -% fi -% else : -% p -% fi -% enddef ; +% added -% vardef simplified expr p = -% (reverse dostraightened(+1,dostraightened(+1,reverse p))) -% enddef ; +picture oddly ; % evenly already defined -% vardef unspiked expr p = -% (reverse dostraightened(-1,dostraightened(-1,reverse p))) -% enddef ; +evenly := dashpattern(on 3 off 3) ; +oddly := dashpattern(off 3 on 3) ; + +% not perfect, but useful since it removes redundant points. -% simplified : remove same points as well as redundant points -% unspiked : remove same points as well as areas with zero distance - -vardef dostraightened(expr sign, p) = - save _p_, _q_ ; path _p_, _q_ ; - _p_ := p ; - forever : - _q_ := dodostraightened(sign, _p_) ; - exitif length(_p_) = length(_q_) ; - _p_ := _q_ ; - endfor ; - _q_ -enddef ; - -vardef dodostraightened(expr sign, p) = - if length(p)>2 : % was 1, but straight lines are ok - save pp ; path pp ; - pp := point 0 of p ; - for i=1 upto length(p)-1 : - if round(point i of p) <> round(point length(pp) of pp) : - pp := pp -- point i of p ; - fi ; +vardef mfun_straightened(expr sign, p) = + save _p_, _q_ ; path _p_, _q_ ; + _p_ := p ; + forever : + _q_ := mfun_do_straightened(sign, _p_) ; + exitif length(_p_) = length(_q_) ; + _p_ := _q_ ; endfor ; - save n, ok ; numeric n ; boolean ok ; - n := length(pp) ; ok := false ; - if n>2 : - for i=0 upto n : % evt hier ook round - if unitvector(round(point i of pp - - point if i=0 : n else : i-1 fi of pp)) <> - sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - - point i of pp)) : - if ok : -- else : ok := true ; fi point i of pp + _q_ +enddef ; + +vardef mfun_do_straightened(expr sign, p) = + if length(p)>2 : % was 1, but straight lines are ok + save pp ; path pp ; + pp := point 0 of p ; + for i=1 upto length(p)-1 : + if round(point i of p) <> round(point length(pp) of pp) : + pp := pp -- point i of p ; + fi ; + endfor ; + save n, ok ; numeric n ; boolean ok ; + n := length(pp) ; ok := false ; + if n>2 : + for i=0 upto n : % evt hier ook round + if unitvector(round(point i of pp - point if i=0 : n else : i-1 fi of pp)) <> + sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - point i of pp)) : + if ok : + -- + else : + ok := true ; + fi point i of pp + fi + endfor + if ok and (cycle p) : + -- cycle + fi + else : + pp fi - endfor - if ok and (cycle p) : -- cycle fi else : - pp + p fi - else : - p - fi enddef ; -% vardef simplified expr p = -% dostraightened(+1,p) -% enddef ; - -% vardef unspiked expr p = -% dostraightened(-1,p) -% enddef ; - -vardef simplified expr p = - (reverse dostraightened(+1,dostraightened(+1,reverse p))) -enddef ; +vardef simplified expr p = ( + reverse mfun_straightened(+1,mfun_straightened(+1,reverse p)) +) enddef ; -vardef unspiked expr p = - (reverse dostraightened(-1,dostraightened(-1,reverse p))) -enddef ; +vardef unspiked expr p = ( + reverse mfun_straightened(-1,mfun_straightened(-1,reverse p)) +) enddef ; % path p ; % p := (2cm,1cm) -- (2cm,1cm) -- (2cm,1cm) -- (3cm,1cm) -- @@ -2289,213 +2343,197 @@ enddef ; path originpath ; originpath := origin -- cycle ; vardef unitvector primary z = - if abs z = abs origin : z else : z/abs z fi + if abs z = abs origin : z else : z/abs z fi enddef; % also new -vardef anchored@#(expr p, z) = - p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p - + (1-labxf@#-labyf@#)*llcorner p)) -enddef ; +% vardef anchored@#(expr p, z) = % maybe use the textext variant +% p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) +% enddef ; % epsed(1.2345) vardef epsed (expr e) = - e if e>0 : + eps elseif e<0 : - eps fi + e if e>0 : + eps elseif e<0 : - eps fi enddef ; % handy def withgray primary g = - withcolor (g,g,g) + withcolor (g,g,g) enddef ; % for metafun -if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ; -if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ; -if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ; -if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ; +if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ; +if unknown darkgreen : color darkgreen ; darkgreen := .625(0,1,0) fi ; +if unknown darkblue : color darkblue ; darkblue := .625(0,0,1) fi ; +if unknown darkcyan : color darkcyan ; darkcyan := .625(0,1,1) fi ; +if unknown darkmagenta : color darkmagenta ; darkmagenta := .625(1,0,1) fi ; +if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ; +if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ; +if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ; % an improved plain mp macro vardef center primary p = - if pair p : p else : .5[llcorner p, urcorner p] fi + if pair p : + p + else : + .5[llcorner p, urcorner p] + fi enddef; % new, yet undocumented vardef rangepath (expr p, d, a) = - (if length p>0 : - (d*unitvector(direction 0 of p) rotated a) - shifted point 0 of p - -- p -- - (d*unitvector(direction length(p) of p) rotated a) - shifted point length(p) of p - else : - p - fi) + if length p>0 : + (d*unitvector(direction 0 of p) rotated a) shifted point 0 of p + -- p -- + (d*unitvector(direction length(p) of p) rotated a) shifted point length(p) of p + else : + p + fi enddef ; % under construction -vardef straightpath(expr a, b, method) = - if (method<1) or (method>6) : - (a--b) - elseif method = 1 : - (a -- - if xpart a > xpart b : - if ypart a > ypart b : - (xpart b,ypart a) -- - elseif ypart a < ypart b : - (xpart a,ypart b) -- - fi - elseif xpart a < xpart b : - if ypart a > ypart b : - (xpart a,ypart b) -- - elseif ypart a < ypart b : - (xpart b,ypart a) -- - fi +vardef straightpath (expr a, b, method) = + if (method<1) or (method>6) : + (a--b) + elseif method = 1 : + (a -- + if xpart a > xpart b : + if ypart a > ypart b : + (xpart b,ypart a) -- + elseif ypart a < ypart b : + (xpart a,ypart b) -- + fi + elseif xpart a < xpart b : + if ypart a > ypart b : + (xpart a,ypart b) -- + elseif ypart a < ypart b : + (xpart b,ypart a) -- + fi + fi + b) + elseif method = 3 : + (a -- + if xpart a > xpart b : + (xpart b,ypart a) -- + elseif xpart a < xpart b : + (xpart a,ypart b) -- + fi + b) + elseif method = 5 : + (a -- + if ypart a > ypart b : + (xpart b,ypart a) -- + elseif ypart a < ypart b : + (xpart a,ypart b) -- + fi + b) + else : + (reverse straightpath(b,a,method-1)) fi - b) - elseif method = 3 : - (a -- - if xpart a > xpart b : - (xpart b,ypart a) -- - elseif xpart a < xpart b : - (xpart a,ypart b) -- - fi - b) - elseif method = 5 : - (a -- - if ypart a > ypart b : - (xpart b,ypart a) -- - elseif ypart a < ypart b : - (xpart a,ypart b) -- - fi - b) - else : - (reverse straightpath(b,a,method-1)) - fi enddef ; % handy for myself def addbackground text t = - begingroup ; save p, b ; picture p ; path b ; - b := boundingbox currentpicture ; - p := currentpicture ; currentpicture := nullpicture ; - fill b t ; setbounds currentpicture to b ; addto currentpicture also p ; - endgroup ; + begingroup ; + save p, b ; picture p ; path b ; + b := boundingbox currentpicture ; + p := currentpicture ; currentpicture := nullpicture ; + fill b t ; + setbounds currentpicture to b ; + addto currentpicture also p ; + endgroup ; enddef ; % makes a (line) into an infinite one (handy for calculating % intersection points vardef infinite expr p = - (-infinity*unitvector(direction 0 of p) + (-infinity*unitvector(direction 0 of p) shifted point 0 of p - -- p -- - +infinity*unitvector(direction length(p) of p) - shifted point length(p) of p) + -- p -- + +infinity*unitvector(direction length(p) of p) + shifted point length(p) of p) enddef ; % obscure macros: create var from string and replace - and : -% (needed for process color id's) +% (needed for process color id's) .. will go away -string _clean_ascii_[] ; +string mfun_clean_ascii[] ; def register_dirty_chars(expr str) = for i = 0 upto length(str)-1 : - _clean_ascii_[ASCII substring(i,i+1) of str] := "_" ; + mfun_clean_ascii[ASCII substring(i,i+1) of str] := "_" ; endfor ; enddef ; register_dirty_chars("+-*/:;., ") ; vardef cleanstring (expr s) = - save ss ; string ss, si ; ss = "" ; save i ; - for i=0 upto length(s) : - si := substring(i,i+1) of s ; - ss := ss & if known _clean_ascii_[ASCII si] : _clean_ascii_[ASCII si] else : si fi ; - endfor ; - ss + save ss ; string ss, si ; ss = "" ; save i ; + for i=0 upto length(s) : + si := substring(i,i+1) of s ; + ss := ss & if known mfun_clean_ascii[ASCII si] : mfun_clean_ascii[ASCII si] else : si fi ; + endfor ; + ss enddef ; vardef asciistring (expr s) = - save ss ; string ss, si ; ss = "" ; save i ; - for i=0 upto length(s) : - si := substring(i,i+1) of s ; - if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") : - ss := ss & char(scantokens(si) + ASCII "A") ; - else : - ss := ss & si ; - fi ; - endfor ; - ss -enddef ; - -vardef setunstringed (expr s, v) = - scantokens(cleanstring(s)) := v ; + save ss ; string ss, si ; ss = "" ; save i ; + for i=0 upto length(s) : + si := substring(i,i+1) of s ; + if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") : + ss := ss & char(scantokens(si) + ASCII "A") ; + else : + ss := ss & si ; + fi ; + endfor ; + ss enddef ; vardef setunstringed (expr s, v) = - scantokens(cleanstring(s)) := v ; + scantokens(cleanstring(s)) := v ; enddef ; vardef getunstringed (expr s) = - scantokens(cleanstring(s)) + scantokens(cleanstring(s)) enddef ; vardef unstringed (expr s) = - expandafter known scantokens(cleanstring(s)) -enddef ; - -% new - -% vardef colorpart(expr i) = -% (redpart i, greenpart i,bluepart i) -% enddef ; - -vardef colorpart(expr c) = - if colormodel c = 3 : - graypart c - elseif colormodel c = 5 : - (redpart c,greenpart c,bluepart c) - elseif colormodel c = 7 : - (cyanpart c,magentapart c,yellowpart c,blackpart c) - fi + expandafter known scantokens(cleanstring(s)) enddef ; % for david arnold: % showgrid(-5,10,1cm,-10,10,1cm); -def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY)= - begingroup - save defaultfont, defaultscale, size ; - string defaultfont ; defaultfont := "cmtt10"; % i.e. infofont - numeric defaultscale ; defaultscale := 8pt / fontsize defaultfont; - numeric size ; size := 2pt ; +def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY) = % will move + begingroup + save size ; numeric size ; size := 2pt ; for x=MinX upto MaxX : - for y=MinY upto MaxY : - draw (x*DeltaX, y*DeltaY) - withpen pencircle scaled - if (x mod 5 = 0) and (y mod 5 = 0) : - 1.5size withcolor .50white - else : - size withcolor .75white - fi ; - endfor ; + for y=MinY upto MaxY : + draw (x*DeltaX, y*DeltaY) withpen pencircle scaled + if (x mod 5 = 0) and (y mod 5 = 0) : + 1.5size withcolor .50white + else : + size withcolor .75white + fi ; + endfor ; endfor ; for x=MinX upto MaxX: - label.bot(decimal x, (x*DeltaX,-size)); + label.bot(textext("\infofont " & decimal x), (x*DeltaX,-size)) ; endfor ; for y=MinY upto MaxY: - label.lft(decimal y, (-size,y*DeltaY)) ; + label.lft(textext("\infofont " & decimal y), (-size,y*DeltaY)) ; endfor ; - endgroup + endgroup enddef; % new, handy for: @@ -2525,26 +2563,24 @@ enddef; % % \useMPgraphic{map}{n=3} -vardef phantom (text t) = - picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ; - setbounds currentpicture to boundingbox _p_ ; +vardef phantom (text t) = % to be checked + picture _p_ ; + _p_ := image(t) ; + addto _p_ also currentpicture ; + setbounds currentpicture to boundingbox _p_ ; enddef ; vardef c_phantom (expr b) (text t) = - if b : - picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ; - setbounds currentpicture to boundingbox _p_ ; - else : - t ; - fi ; + if b : + picture _p_ ; + _p_ := image(t) ; + addto _p_ also currentpicture ; + setbounds currentpicture to boundingbox _p_ ; + else : + t ; + fi ; enddef ; -% mark paths (for external progs to split) - -% def somepath(expr p) -% p -% enddef ; - %D Handy: def break = @@ -2553,27 +2589,228 @@ enddef ; %D New too: -primarydef p xstretched w = - (p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi) -enddef ; +primarydef p xstretched w = ( + p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi +) enddef ; -primarydef p ystretched h = - (p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi) -enddef ; +primarydef p ystretched h = ( + p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi +) enddef ; primarydef p snapped s = - hide ( if path p : - forever : - exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ; - p := p scaled (1/2) ; - endfor ; - elseif numeric p : - forever : - exitif p <= s ; - p := p scaled (1/2) ; + hide ( + if path p : + forever : + exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ; + p := p scaled (1/2) ; + endfor ; + elseif numeric p : + forever : + exitif p <= s ; + p := p scaled (1/2) ; + endfor ; + fi ; + ) + p +enddef ; + +% vardef somecolor = (1,1,0,0) enddef ; + +% fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ; +% fill OverlayBox withcolor (ccomponent somecolor,mcomponent somecolor,ycomponent somecolor,bcomponent somecolor) ; + +% This could be standard mplib 2 behaviour: + +vardef rcomponent expr p = if rgbcolor p : redpart p elseif cmykcolor p : 1 - cyanpart p else : p fi enddef ; +vardef gcomponent expr p = if rgbcolor p : greenpart p elseif cmykcolor p : 1 - magentapart p else : p fi enddef ; +vardef bcomponent expr p = if rgbcolor p : bluepart p elseif cmykcolor p : 1 - yellowpart p else : p fi enddef ; +vardef ccomponent expr p = if cmykcolor p : cyanpart p elseif rgbcolor p : 1 - redpart p else : p fi enddef ; +vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor p : 1 - greenpart p else : p fi enddef ; +vardef ycomponent expr p = if cmykcolor p : yellowpart p elseif rgbcolor p : 1 - bluepart p else : p fi enddef ; +vardef bcomponent expr p = if cmykcolor p : blackpart p elseif rgbcolor p : 0 else : p fi enddef ; + +% draw image (...) ... ; % prescripts prepended to first, postscripts appended to last +% draw decorated (...) ... ; % prescripts prepended to each, postscripts appended to each +% draw redecorated (...) ... ; % prescripts assigned to each, postscripts assigned to each +% draw undecorated (...) ... ; % following properties are ignored, existing properties are kept +% +% draw decorated ( +% draw fullcircle scaled 20cm withpen pencircle scaled 20mm withcolor red withtransparency (1,.40) ; +% draw fullcircle scaled 15cm withpen pencircle scaled 15mm withcolor green withtransparency (1,.30) ; +% draw fullcircle scaled 10cm withpen pencircle scaled 10mm withcolor blue withtransparency (1,.20) ; +% ) +% withcolor blue +% withtransparency (1,.125) % selectively applied +% withpen pencircle scaled 10mm +% ; + +% vardef image (text imagedata) = % already defined +% save currentpicture ; +% picture currentpicture ; +% currentpicture := nullpicture ; +% imagedata ; +% currentpicture +% enddef ; + +vardef undecorated (text imagedata) text decoration = + save currentpicture ; + picture currentpicture ; + currentpicture := nullpicture ; + imagedata ; + currentpicture +enddef ; + + +if metapostversion < 1.770 : + + vardef decorated (text imagedata) text decoration = + save mfun_decorated_path, currentpicture ; + picture mfun_decorated_path, currentpicture ; + currentpicture := nullpicture ; + imagedata ; + mfun_decorated_path := currentpicture ; + currentpicture := nullpicture ; + for i within mfun_decorated_path : + addto currentpicture + if stroked i : + doublepath pathpart i + dashed dashpart i + withpen penpart i + withcolor colorpart i + decoration + elseif filled i : + contour pathpart i + withpen penpart i + withcolor colorpart i + decoration + elseif textual i : + also i + withcolor colorpart i + decoration + else : + also i + fi + ; + endfor ; + currentpicture + enddef ; + +else: + + vardef decorated (text imagedata) text decoration = + save mfun_decorated_path, currentpicture ; + picture mfun_decorated_path, currentpicture ; + currentpicture := nullpicture ; + imagedata ; + mfun_decorated_path := currentpicture ; + currentpicture := nullpicture ; + for i within mfun_decorated_path : + addto currentpicture + if stroked i : + doublepath pathpart i + dashed dashpart i + withpen penpart i + withcolor colorpart i + withprescript prescriptpart i + withpostscript postscriptpart i + decoration + elseif filled i : + contour pathpart i + withpen penpart i + withcolor colorpart i + withprescript prescriptpart i + withpostscript postscriptpart i + decoration + elseif textual i : + also i + withcolor colorpart i + withprescript prescriptpart i + withpostscript postscriptpart i + decoration + else : + also i + fi + ; + endfor ; + currentpicture + enddef ; + +fi ; + +vardef redecorated (text imagedata) text decoration = + save mfun_decorated_path, currentpicture ; + picture mfun_decorated_path, currentpicture ; + currentpicture := nullpicture ; + imagedata ; + mfun_decorated_path := currentpicture ; + currentpicture := nullpicture ; + for i within mfun_decorated_path : + addto currentpicture + if stroked i : + doublepath pathpart i + dashed dashpart i + withpen penpart i + decoration + elseif filled i : + contour pathpart i + withpen penpart i + decoration + elseif textual i : + also i + decoration + else : + also i + fi + ; endfor ; - fi ; ) - p + currentpicture enddef ; +% path mfun_bleed_box ; + +% primarydef p bleeded d = +% image ( +% mfun_bleed_box := boundingbox p ; +% if pair d : +% draw p xysized (bbwidth(p)+2*xpart d,bbheight(p)+2*ypart d) shifted -d ; +% else : +% draw p xysized (bbwidth(p)+2d,bbheight(p)+2d) shifted (-d,-d) ; +% fi ; +% setbounds currentpicture to mfun_bleed_box ; +% ) +% enddef ; + +%D New helpers: + +def beginglyph(expr unicode, width, height, depth) = + beginfig(unicode) ; % the number is irrelevant + charcode := unicode ; + charwd := width ; + charht := height ; + chardp := depth ; +enddef ; + +def endglyph = + setbounds currentpicture to (boundingbox unitsquare xscaled charwd yscaled (charht + chardp) shifted (0,-chardp)) ; + if known charscale : + currentpicture := currentpicture scaled charscale ; + fi ; + endfig ; +enddef ; + +%D Dimensions have bever been an issue as traditional MP can't make that large +%D pictures, but with double mode we need a catch: + +newinternal maxdimensions ; maxdimensions := 14000 ; + +def mfun_apply_max_dimensions = % not a generic helper, we want to protect this one + if bbwidth currentpicture > maxdimensions : + currentpicture := currentpicture if bbheight currentpicture > bbwidth currentpicture : ysized else : xsized fi maxdimensions ; + elseif bbheight currentpicture > maxdimensions : + currentpicture := currentpicture ysized maxdimensions ; + fi ; +enddef; + +extra_endfig := extra_endfig & "mfun_apply_max_dimensions ;" ; + let dump = relax ; diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv index 672a051c2..e497e2f72 100644 --- a/metapost/context/base/mp-tool.mpiv +++ b/metapost/context/base/mp-tool.mpiv @@ -57,8 +57,15 @@ mpprocset := 1 ; % % protect ; -string space ; space := char 32 ; -string CRLF ; CRLF := char 10 & char 13 ; +string space ; space := char 32 ; +string percent ; percent := char 37 ; +string crlf ; crlf := char 10 & char 13 ; +string dquote ; dquote := char 34 ; + +let SPACE = space ; +let CRLF = crlf ; +let DQUOTE = dquote ; +let PERCENT = percent ; vardef ddecimal primary p = decimal xpart p & " " & decimal ypart p @@ -90,8 +97,8 @@ newinternal graycolormodel ; graycolormodel := 3 ; newinternal rgbcolormodel ; rgbcolormodel := 5 ; newinternal cmykcolormodel ; cmykcolormodel := 7 ; -let grayscale = numeric ; -let greyscale = numeric ; +let grayscale = graycolor ; +let greyscale = greycolor ; vardef colorpart expr c = if not picture c : @@ -141,6 +148,39 @@ vardef colordecimals primary c = fi enddef ; +vardef colordecimalslist(text t) = + save b ; boolean b ; b := false ; + for s=t : + if b : & " " & fi + colordecimals(s) + hide(b := true ;) + endfor +enddef ; + +% vardef _ctx_color_spec_ primary c = +% if cmykcolor c : +% "c=" & decimal cyanpart c & +% ",m=" & decimal magentapart c & +% ",y=" & decimal yellowpart c & +% ",k=" & decimal blackpart c +% elseif rgbcolor c : +% "r=" & decimal redpart c & +% ",g=" & decimal greenpart c & +% ",b=" & decimal bluepart c +% else : +% "s=" & decimal c +% fi +% enddef ; +% +% vardef _ctx_color_spec_list_(text t) = +% save b ; boolean b ; b := false ; +% for s=t : +% if b : & " " & fi +% _ctx_color_spec_(s) +% hide(b := true ;) +% endfor +% enddef ; + %D We have standardized data file names: def job_name = @@ -152,7 +192,8 @@ def data_mpd_file = enddef ; %D Because \METAPOST\ has a hard coded limit of 4~datafiles, -%D we need some trickery when we have multiple files. +%D we need some trickery when we have multiple files. This will +%D be redone (via \LUA). if unknown collapse_data : boolean collapse_data ; @@ -289,10 +330,14 @@ vardef set_outer_boundingbox text q = % obsolete setbounds q to outerboundingbox q; enddef; -%D Some missing functions can be implemented rather -%D straightforward: +%D Some missing functions can be implemented rather straightforward (thanks to +%D Taco and others): + +% oldpi := 3.14159265358979323846 ; % from <math.h> +pi := 3.14159265358979323846264338327950288419716939937510 ; % 50 digits +radian := 180/pi ; % 2pi*radian = 360 ; -numeric Pi ; Pi := 3.1415926 ; +% let +++ = ++ ; vardef sqr primary x = x*x enddef ; vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; @@ -302,15 +347,6 @@ vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; vardef pow (expr x,p) = x**p enddef ; -vardef asin primary x = x+(x**3)/6+3(x**5)/40 enddef ; -vardef acos primary x = asin(-x) enddef ; -vardef atan primary x = x-(x**3)/3+(x**5)/5-(x**7)/7 enddef ; -vardef tand primary x = sind(x)/cosd(x) enddef ; - -%D Here are Taco Hoekwater's alternatives (but vardef'd and primaried). - -pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ; - vardef tand primary x = sind(x)/cosd(x) enddef ; vardef cotd primary x = cosd(x)/sind(x) enddef ; @@ -321,9 +357,11 @@ vardef cot primary x = cos(x)/sin(x) enddef ; vardef asin primary x = angle((1+-+x,x)) enddef ; vardef acos primary x = angle((x,1+-+x)) enddef ; +vardef atan primary x = angle(1,x) enddef ; vardef invsin primary x = (asin(x))/radian enddef ; vardef invcos primary x = (acos(x))/radian enddef ; +vardef invtan primary x = (atan(x))/radian enddef ; vardef acosh primary x = ln(x+(x+-+1)) enddef ; vardef asinh primary x = ln(x+(x++1)) enddef ; @@ -331,6 +369,11 @@ vardef asinh primary x = ln(x+(x++1)) enddef ; vardef sinh primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ; vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ; +%D Like mod, but useful for anglesl it returns (-.5d,+.5d] and is used +%D in for instance mp-chem. + +primarydef a zmod b = (-((b/2 - a) mod b) + b/2) enddef ; + %D Sometimes this is handy: def undashed = @@ -631,6 +674,15 @@ ultriangle := origin -- (0,+.5) -- (-.5,0) -- cycle ; lltriangle := origin -- (-.5,0) -- (0,-.5) -- cycle ; lrtriangle := origin -- (0,-.5) -- (+.5,0) -- cycle ; +path triangle, uptriangle, downtriangle, lefttriangle, righttriangle ; + +triangle := (1,0) -- (1,0) rotated 120 -- (1,0) rotated -120 -- cycle ; + +uptriangle := triangle rotated 90 ; +downtriangle := triangle rotated -90 ; +lefttriangle := triangle rotated 180 ; +righttriangle := triangle ; + path unitdiamond, fulldiamond ; unitdiamond := (.5,0) -- (1,.5) -- (.5,1) -- (0,.5) -- cycle ; @@ -768,8 +820,8 @@ vardef whitecolor(expr c) = if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi enddef ; -vardef blackcolor(expr c) = - if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi +vardef blackcolor expr c = + if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi enddef ; %D Well, this is the dangerous and naive version: @@ -1223,7 +1275,7 @@ enddef ; extra_endfig := extra_endfig & " naturalizepaths ; " ; -%D Noce tracer: +%D Nice tracer: def drawboundary primary p = draw p dashed evenly withcolor white ; @@ -1318,7 +1370,7 @@ primarydef pct along pat = % also negative enddef ; primarydef len on pat = % no outer ( ) .. somehow fails - (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat + (arctime if len>=0 : len else : (arclength(pat)+len) fi of pat) of pat enddef ; % this cuts of a piece from both ends @@ -1539,9 +1591,13 @@ primarydef p softened c = enddef ; vardef grayed primary p = - if color p : + if rgbcolor p : tripled(.30redpart p+.59greenpart p+.11bluepart p) - else : + elseif cmykcolor p : + tripled(.30*(1-cyanpart i)+.59*(1-magentapart i)+.11*(1-yellowpart i)+blackpart i) + elseif greycolor p : + p + elseif picture p : image ( for i within p : addto currentpicture @@ -1557,12 +1613,24 @@ vardef grayed primary p = else : also i fi - withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; + if unknown colorpart i : + % nothing + elseif rgbcolor colorpart i : + withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; + elseif cmykcolor colorpart i : + withcolor tripled(.30*(1-cyanpart i)+.59*(1-magentapart i)+.11*(1-yellowpart i)+blackpart i) ; + else : + withcolor colorpart i ; + fi endfor ; ) - fi + else : + p + fi enddef ; +let greyed = grayed ; + % yes or no: "text" infont "cmr12" at 24pt ; % let normalinfont = infont ; @@ -2030,7 +2098,7 @@ enddef ; % handy def withgray primary g = - withcolor (g,g,g) + withcolor g enddef ; % for metafun @@ -2253,7 +2321,7 @@ enddef ; %D Handy: def break = - exitif true fi ; + exitif true ; % fi enddef ; %D New too: @@ -2266,23 +2334,31 @@ primarydef p ystretched h = ( p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi ) enddef ; -primarydef p snapped s = - hide ( - if path p : - forever : - exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ; - p := p scaled (1/2) ; - endfor ; - elseif numeric p : - forever : - exitif p <= s ; - p := p scaled (1/2) ; - endfor ; - fi ; - ) - p +%D Newer: + +vardef area expr p = + % we could calculate the boundingbox once + (xpart llcorner boundingbox p,0) -- p -- + (xpart lrcorner boundingbox p,0) -- cycle enddef ; +vardef basiccolors[] = + if @ = 0 : + white + else : + save n ; n := @ mod 7 ; + if n = 1 : red + elseif n = 2 : green + elseif n = 3 : blue + elseif n = 4 : cyan + elseif n = 5 : magenta + elseif n = 6 : yellow + else : black + fi + fi +enddef ; + + % vardef somecolor = (1,1,0,0) enddef ; % fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ; @@ -2329,7 +2405,6 @@ vardef undecorated (text imagedata) text decoration = currentpicture enddef ; - if metapostversion < 1.770 : vardef decorated (text imagedata) text decoration = @@ -2449,25 +2524,76 @@ enddef ; % ) % enddef ; +vardef mfun_snapped(expr p, s) = + if p < 0 : - ( - else : ( fi p div s) * s % the less tokens the better +enddef ; + +vardef mfun_applied(expr p, s)(suffix a) = + if path p : + if pair s : + for i=0 upto length(p)-1 : + (a(xpart point i of p,xpart s),a(ypart point i of p,ypart s)) -- + endfor + if cycle p : + cycle + else : + (a(xpart point length(p) of p,xpart s),a(ypart point length(p) of p,ypart s)) + fi + else : + for i=0 upto length(p)-1 : + (a(xpart point i of p,s),a(ypart point i of p,s)) -- + endfor + if cycle p : + cycle + else : + (a(xpart point length(p) of p,s),a(ypart point length(p) of p,s)) + fi + fi + elseif pair p : + if pair s : + (a(xpart p,xpart s),a(ypart p,ypart s)) + else : + (a(xpart p,s),a(ypart p,s)) + fi + elseif cmykcolor p : + (a(cyanpart p,s),a(magentapart p,s),a(yellowpart p,s),a(blackpart p,s)) + elseif rgbcolor p : + (a(redpart p,s),a(greenpart p,s),a(bluepart p,s)) + elseif graycolor p : + a(p,s) + elseif numeric p : + a(p,s) + else + p + fi +enddef ; + +primarydef p snapped s = + mfun_applied(p,s)(mfun_snapped) % so we can play with variants +enddef ; + %D New helpers: +newinternal charscale ; charscale := 1 ; % persistent so one needs to 'reset' it to 0 or 1 + def beginglyph(expr unicode, width, height, depth) = beginfig(unicode) ; % the number is irrelevant charcode := unicode ; charwd := width ; charht := height ; chardp := depth ; + % charscale := 1 ; % can be set for a whole font, so no reset here enddef ; def endglyph = setbounds currentpicture to (boundingbox unitsquare xscaled charwd yscaled (charht + chardp) shifted (0,-chardp)) ; - if known charscale : + if known charscale : if (charscale > 0) and (charscale <> 1) : currentpicture := currentpicture scaled charscale ; - fi ; + fi ; fi ; endfig ; enddef ; -%D Dimensions have bever been an issue as traditional MP can't make that large +%D Dimensions have never been an issue as traditional MP can't make that large %D pictures, but with double mode we need a catch: newinternal maxdimensions ; maxdimensions := 14000 ; diff --git a/metapost/context/fonts/bidi-symbols.tex b/metapost/context/fonts/bidi-symbols.tex index 800e0e4ea..ba659ccb7 100644 --- a/metapost/context/fonts/bidi-symbols.tex +++ b/metapost/context/fonts/bidi-symbols.tex @@ -1,4 +1,4 @@ -% \nopdfcompression +\nopdfcompression % At the ConTeXt 2013 meeting Taco suggested to add ActualText entries to the % shapes. It took us a bit of experimenting and the current implementation of @@ -30,3 +30,4 @@ \getbuffer \blank \stoptext + |