diff options
Diffstat (limited to 'metapost')
34 files changed, 7260 insertions, 1382 deletions
diff --git a/metapost/context/base/metafun.mpii b/metapost/context/base/metafun.mpii index 65d7b87f8..783b467dc 100644 --- a/metapost/context/base/metafun.mpii +++ b/metapost/context/base/metafun.mpii @@ -28,21 +28,21 @@ %D end even may use a patched version, we prefer to use a %D copy. -input mp-base.mpii ; -input mp-tool.mp ; -input mp-spec.mpii ; -input mp-core.mpii ; -input mp-page.mp ; -input mp-text.mp ; -input mp-txts.mp ; -input mp-shap.mp ; -input mp-butt.mp ; -input mp-char.mpii ; -input mp-step.mpii ; -input mp-grph.mp ; -input mp-figs.mp ; -input mp-grid.mp ; -input mp-func.mp ; +input "mp-base.mpii" ; +input "mp-tool.mpii" ; +input "mp-spec.mpii" ; +input "mp-core.mpii" ; +input "mp-page.mpii" ; +input "mp-text.mpii" ; +input "mp-txts.mpii" ; +input "mp-shap.mpii" ; +input "mp-butt.mpii" ; +input "mp-char.mpii" ; +input "mp-step.mpii" ; +input "mp-grph.mpii" ; +input "mp-figs.mpii" ; +input "mp-grid.mpii" ; +input "mp-func.mpii" ; string metafunversion ; diff --git a/metapost/context/base/metafun.mpiv b/metapost/context/base/metafun.mpiv index b32e301a7..4bc762cf7 100644 --- a/metapost/context/base/metafun.mpiv +++ b/metapost/context/base/metafun.mpiv @@ -16,33 +16,33 @@ %D end even may use a patched version, we prefer to use a %D copy. -input mp-base.mpiv ; -input mp-tool.mp ; -input mp-core.mpiv ; -input mp-page.mp ; -input mp-text.mp ; -input mp-txts.mp ; -input mp-butt.mp ; -input mp-shap.mp ; -% mp-char.mpiv ; % there no need to always load this -% mp-step.mpiv ; % there no need to always load this -input mp-grph.mp ; -input mp-figs.mp ; -input mp-mlib.mpiv ; -input mp-chem.mpiv ; % there no need to always load this (todo) -input mp-grid.mp ; -input mp-func.mp ; - -string metafunversion ; - -metafunversion = "metafun iv" & " " & - decimal year & "-" & - decimal month & "-" & - decimal day & " " & - if ((time div 60) < 10) : "0" & fi - decimal (time div 60) & ":" & - if ((time-(time div 60)*60) < 10) : "0" & fi - decimal (time-(time div 60)*60) ; +input "mp-base.mpiv" ; +input "mp-tool.mpiv" ; +input "mp-mlib.mpiv" ; +input "mp-core.mpiv" ; % todo: namespace and cleanup +input "mp-page.mpiv" ; % todo: namespace and cleanup +input "mp-butt.mpiv" ; % todo: namespace and cleanup +input "mp-shap.mpiv" ; % will be improved +input "mp-grph.mpiv" ; % todo: namespace and cleanup +input "mp-grid.mpiv" ; % todo: namespace and cleanup + +input "mp-figs.mpiv" ; % obsolete, needs checking +input "mp-text.mpiv" ; % will be redone into a module +input "mp-func.mpiv" ; % under construction + +% "mp-char.mpiv" ; % loaded on demand +% "mp-step.mpiv" ; % loaded on demand +% "mp-chem.mpiv" ; % loaded on demand + +string metafunversion ; metafunversion = + "metafun iv" & " " & + decimal year & "-" & + decimal month & "-" & + decimal day & " " & + if ((time div 60) < 10) : "0" & fi + decimal (time div 60) & ":" & + if ((time-(time div 60)*60) < 10) : "0" & fi + decimal (time-(time div 60)*60) ; let normalend = end ; @@ -50,4 +50,6 @@ def end = ; message "" ; message metafunversion ; message "" ; normalend ; enddef ; -dump ; endinput . +dump ; % obsolete in mplib + +endinput diff --git a/metapost/context/base/mp-back.mp b/metapost/context/base/mp-back.mp index f49474cf7..f588adea9 100644 --- a/metapost/context/base/mp-back.mp +++ b/metapost/context/base/mp-back.mp @@ -11,8 +11,7 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_back : endinput ; fi ; +if known context_back : endinput ; fi ; boolean context_back ; context_back := true ; diff --git a/metapost/context/base/mp-base.mpiv b/metapost/context/base/mp-base.mpiv index cd0c79728..5ed6fd981 100644 --- a/metapost/context/base/mp-base.mpiv +++ b/metapost/context/base/mp-base.mpiv @@ -6,6 +6,10 @@ % features of plain METAFONT except those specific to font-making. % There are also a number of macros for labeling figures, etc. +% For practical reasons I have moved some new code here (and might +% remove some code as well). After all, there is no development in +% this format. + string base_name, base_version ; base_name := "plain" ; @@ -15,27 +19,21 @@ message "Preloading the plain mem file, version " & base_version ; delimiters () ; % this makes parentheses behave like parentheses -def upto = - step 1 until -enddef ; - -def downto = - step -1 until -enddef ; +def upto = step 1 until enddef ; +def downto = step -1 until enddef ; def exitunless expr c = exitif not c enddef ; -let relax = \ ; % ignore the word `relax', as in TeX +let relax = \ ; % ignore the word relax, as in TeX let \\ = \ ; % double relaxation is like single -def ]] = % right brackets should be loners - ] ] -enddef ; +def [[ = [ [ enddef ; +def ]] = ] ] enddef ; def -- = - {curl 1}..{curl 1} + {curl 1} .. {curl 1} enddef ; def --- = @@ -58,7 +56,7 @@ enddef ; def ??? = hide ( - interim showstopping : =1 ; + interim showstopping := 1 ; showdependencies ) enddef ; @@ -95,7 +93,7 @@ enddef ; def tracingall = % turns on every form of tracing tracingonline := 1 ; showstopping := 1 ; - loggingall + loggingall ; enddef ; def tracingnone = % turns off every form of tracing @@ -130,19 +128,19 @@ tertiarydef p _on_ d = w := w + d ; pic shifted (0,d) endgroup -enddef; +enddef ; tertiarydef p _off_ d = - begingroup w:=w+d; + begingroup w := w + d ; p shifted (0,d) endgroup -enddef; +enddef ; %% basic constants and mathematical macros % numeric constants -newinternal eps, epsilon,infinity, _ ; +newinternal eps, epsilon, infinity, _ ; eps := .00049 ; % this is a pretty small positive number epsilon := 1/256/256 ; % but this is the smallest @@ -181,16 +179,23 @@ for z=origin,right,up : z transformed identity = z ; endfor -% color constants +% color constants (all in rgb color space) + +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) ; -color black, white, red, green, blue, background; +background := white ; % obsolete -black = (0,0,0) ; -white = (1,1,1) ; -red = (1,0,0) ; -green = (0,1,0) ; -blue = (0,0,1) ; -background = white ; +let graypart = greypart ; +let graycolor = greycolor ; % picture constants @@ -212,7 +217,7 @@ EOF = char 0 ; % end-of-file for readfrom and write..to pen pensquare, penrazor, penspeck ; pensquare = makepen(unitsquare shifted -(.5,.5)) ; -penrazor = makepen((-.5,0)--(.5,0)--cycle) ; +penrazor = makepen((-.5,0) -- (.5,0) -- cycle) ; penspeck = pensquare scaled eps ; % nullary operators @@ -332,7 +337,7 @@ enddef ; vardef directionpoint expr z of p = a_ := directiontime z of p ; - if a_<0 : + if a_ < 0 : errmessage("The direction doesn't occur") ; fi point a_ of p @@ -342,27 +347,27 @@ secondarydef p intersectionpoint q = begingroup save x_, y_ ; (x_,y_) = p intersectiontimes q ; - if x_<0 : + if x_ < 0 : errmessage("The paths don't intersect") ; origin else : .5[point x_ of p, point y_ of q] fi endgroup -enddef; +enddef ; tertiarydef p softjoin q = begingroup c_ := fullcircle scaled 2join_radius shifted point 0 of q ; a_ := ypart(c_ intersectiontimes p) ; b_ := ypart(c_ intersectiontimes q) ; - if a_<0 : + if a_ < 0 : point 0 of p{direction 0 of p} else : subpath(0,a_) of p fi ... - if b_<0 : + if b_ < 0 : {direction infinity of q} point infinity of q else : subpath(b_,infinity) of q @@ -372,14 +377,13 @@ enddef ; newinternal join_radius, a_, b_ ; path c_ ; - path cuttings ; % what got cut off tertiarydef a cutbefore b = % tries to cut as little as possible begingroup save t ; (t, whatever) = a intersectiontimes b ; - if t<0 : + if t < 0 : cuttings := point 0 of a ; a else : @@ -392,7 +396,7 @@ enddef ; tertiarydef a cutafter b = reverse (reverse a cutbefore b) hide(cuttings := reverse cuttings) -enddef; +enddef ; % special operators @@ -421,7 +425,7 @@ vardef min(expr u)(text t) = % t is a list of numerics, pairs, or strings save u_ ; setu_ u ; for uu = t : - if uu<u_ : + if uu < u_ : u_ := uu ; fi endfor @@ -432,7 +436,7 @@ vardef max(expr u)(text t) = % t is a list of numerics, pairs, or strings save u_ ; setu_ u ; for uu = t : - if uu>u_ : + if uu > u_ : u_ := uu ; fi endfor @@ -464,10 +468,10 @@ enddef ; newinternal n_; pair z_[],dz_; def superellipse(expr r,t,l,b,s) = - r{up} ... (s[xpart t,xpart r],s[ypart r,ypart t]){t-r} ... - t{left} ... (s[xpart t,xpart l],s[ypart l,ypart t]){l-t} ... - l{down} ... (s[xpart b,xpart l],s[ypart l,ypart b]){b-l} ... - b{right} ... (s[xpart b,xpart r],s[ypart r,ypart b]){r-b} ... cycle enddef ; + r { up } ... (s[xpart t,xpart r],s[ypart r,ypart t]) { t-r } ... + t { left } ... (s[xpart t,xpart l],s[ypart l,ypart t]) { l-t } ... + l { down } ... (s[xpart b,xpart l],s[ypart l,ypart b]) { b-l } ... + b { right } ... (s[xpart b,xpart r],s[ypart r,ypart b]) { r-b } ... cycle enddef ; vardef interpath(expr a,p,q) = for t=0 upto length p-1 : @@ -529,7 +533,7 @@ pc := 11.95517 ; cc := 12.79213 ; in := 72 ; -vardef magstep primary m = +vardef magstep primary m = % obsolete mexp(46.67432m) enddef ; @@ -582,7 +586,7 @@ def erase text t = withcolor background hide(def _e_ = enddef ;) enddef ; t _e_ -enddef; +enddef ; def _e_ = enddef ; @@ -599,7 +603,7 @@ vardef image(text t) = currentpicture := nullpicture ; t ; currentpicture -enddef; +enddef ; def pickup secondary q = if numeric q : @@ -630,7 +634,7 @@ def pen_pickup_ primary q = pen_top :=ypart penoffset left of currentpen ; pen_bot :=ypart penoffset right of currentpen ; path currentpen_path ; -enddef; +enddef ; newinternal pen_lft, pen_rt, pen_top, pen_bot, pen_count_ ; @@ -642,7 +646,7 @@ vardef savepen = pen_bot_ [pen_count_] = pen_bot ; pen_path_[pen_count_] = currentpen_path ; pen_count_ -enddef; +enddef ; def clearpen = currentpen:=nullpen; pen_lft := pen_rt := pen_top := pen_bot := 0 ; @@ -664,7 +668,7 @@ vardef bot primary y = y + if pair y: (0,pen_bot) else: pen_bot fi enddef ; vardef penpos@#(expr b,d) = (x@#r-x@#l,y@#r-y@#l) = (b,0) rotated d ; x@# = .5(x@#l+x@#r) ; - y@# = .5(y@#l+y@#r) + y@# = .5(y@#l+y@#r) ; % ; added HH enddef ; path path_.l, path_.r ; @@ -688,7 +692,7 @@ vardef arrowhead expr p = e = point length p of p ; q = gobble(p shifted -e cutafter makepath(pencircle scaled 2ahlength)) cuttings ; (q rotated .5ahangle & reverse q rotated -.5ahangle -- cycle) shifted e -enddef; +enddef ; path _apth ; @@ -698,7 +702,7 @@ def drawdblarrow expr p = _apth := p ; _findarr enddef ; def _finarr text t = draw _apth t ; filldraw arrowhead _apth t -enddef; +enddef ; def _findarr text t = draw _apth t ; @@ -713,11 +717,10 @@ newinternal bboxmargin ; bboxmargin := 2bp ; % this can bite you vardef bbox primary p = - llcorner p-( bboxmargin, bboxmargin) - -- lrcorner p+( bboxmargin,-bboxmargin) - -- urcorner p+( bboxmargin, bboxmargin) - -- ulcorner p+(-bboxmargin, bboxmargin) - -- cycle + llcorner p - ( bboxmargin, bboxmargin) -- + lrcorner p + ( bboxmargin,-bboxmargin) -- + urcorner p + ( bboxmargin, bboxmargin) -- + ulcorner p + (-bboxmargin, bboxmargin) -- cycle enddef ; string defaultfont ; newinternal defaultscale, labeloffset ; @@ -734,7 +737,7 @@ vardef thelabel@#(expr s,z) = % Position s near z p = s infont defaultfont scaled defaultscale fi ; p shifted (z + labeloffset*laboff@# - ( labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p) ) -enddef; +enddef ; def label = draw thelabel @@ -747,7 +750,7 @@ dotlabeldiam := 3bp ; vardef dotlabel@#(expr s,z) text t_ = label@#(s,z) t_ ; % label@#(s,z) ; - interim linecap:=rounded ; + interim linecap := rounded ; draw z withpen pencircle scaled dotlabeldiam t_ ; enddef ; @@ -755,6 +758,8 @@ def makelabel = dotlabel enddef ; +% this will be overloaded + pair laboff, laboff.lft, laboff.rt, laboff.top, laboff.bot ; pair laboff.ulft, laboff.llft, laboff.urt, laboff.lrt ; @@ -774,6 +779,8 @@ vardef labels@#(text t) = endfor enddef ; +% til lhere + vardef dotlabels@#(text t) = forsuffixes $=t: dotlabel@#(str$,z$) ; @@ -818,14 +825,14 @@ def beginfig(expr c) = pickup defaultpen ; drawoptions() ; scantokens extra_beginfig ; -enddef; +enddef ; def endfig = ; % added by HH scantokens extra_endfig ; shipit ; endgroup -enddef; +enddef ; %% last-minute items diff --git a/metapost/context/base/mp-butt.mp b/metapost/context/base/mp-butt.mpii index 3ae3dc983..a3599b7c0 100644 --- a/metapost/context/base/mp-butt.mp +++ b/metapost/context/base/mp-butt.mpii @@ -11,22 +11,26 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_butt : endinput ; fi ; +if known context_butt : endinput ; fi ; boolean context_butt ; context_butt := true ; -def some_button (expr button_type, button_size, button_linecolor, button_fillcolor) = +def predefinedbutton (expr button_type, button_size, button_linecolor, button_fillcolor) = + + begingroup ; + + save button_linewidth, p, d, l ; numeric button_linewidth ; button_linewidth := button_size/10 ; drawoptions (withpen pencircle scaled button_linewidth withcolor button_linecolor) ; - path p ; p := unitsquare scaled button_size ; + path p ; p := unitsquare scaled button_size ; numeric d ; d := button_size ; numeric l ; l := button_linewidth ; - fill p withcolor button_fillcolor ; draw p ; + fill p withcolor button_fillcolor ; + draw p ; if button_type = 101 : draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ; @@ -66,6 +70,10 @@ def some_button (expr button_type, button_size, button_linecolor, button_fillcol endfor ; fi ; + endgroup ; + enddef ; +let some_button = predefinedbutton + endinput ; diff --git a/metapost/context/base/mp-butt.mpiv b/metapost/context/base/mp-butt.mpiv new file mode 100644 index 000000000..a3599b7c0 --- /dev/null +++ b/metapost/context/base/mp-butt.mpiv @@ -0,0 +1,79 @@ +%D \module +%D [ file=mp-butt.mp, +%D version=2000.05.31, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=buttons, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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_butt : endinput ; fi ; + +boolean context_butt ; context_butt := true ; + +def predefinedbutton (expr button_type, button_size, button_linecolor, button_fillcolor) = + + begingroup ; + + save button_linewidth, p, d, l ; + + numeric button_linewidth ; button_linewidth := button_size/10 ; + + drawoptions (withpen pencircle scaled button_linewidth withcolor button_linecolor) ; + + path p ; p := unitsquare scaled button_size ; + numeric d ; d := button_size ; + numeric l ; l := button_linewidth ; + + fill p withcolor button_fillcolor ; + draw p ; + + if button_type = 101 : + draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ; + elseif button_type = 102 : + draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ; + elseif button_type = 103 : + for i=2l step 2l until d-2l : + draw (2l,i)--(2l ,i) ; + draw (4l,i)--(d-2l,i) ; + endfor ; + elseif button_type = 104 : + for i=2l step 2l until d-2l : + draw (2l ,i)--(d/2-l,i) ; + draw (d/2+l,i)--(d-2l ,i) ; + endfor ; + elseif button_type = 105 : + fill fullcircle scaled (.2d) shifted (.5d,.7d) ; + fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ; + clip currentpicture to p ; + draw p ; + elseif button_type = 106 : + draw (2l,2l)--(d-2l,d-2l) ; + draw (d-2l,2l)--(2l,d-2l) ; + elseif button_type = 107 : + p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ; + fill p ; draw p ; + draw (.5d,2l) ; + elseif button_type = 108 : + draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ; + elseif button_type = 109 : + draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ; + elseif button_type = 110 : + button_linewidth := button_linewidth/2 ; + draw p enlarged (-2l,-l) ; + for i=2l step l until d-2l : + draw (3l,i)--(d-3l,i) ; + endfor ; + fi ; + + endgroup ; + +enddef ; + +let some_button = predefinedbutton + +endinput ; diff --git a/metapost/context/base/mp-char.mpii b/metapost/context/base/mp-char.mpii new file mode 100644 index 000000000..788099f2c --- /dev/null +++ b/metapost/context/base/mp-char.mpii @@ -0,0 +1,1018 @@ +% to be cleaned up, namespace needed ! ! ! ! ! + +%D \module +%D [ file=mp-char.mp, +%D version=1998.10.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=charts, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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 unknown context_shap : input "mp-shap.mpii" ; fi ; +if known context_flow : endinput ; fi ; + +boolean context_char ; context_char := true ; + +% kan naar elders + +current_position := 0 ; + +def save_text_position (expr p) = % beware: clip shift needed + current_position := current_position + 1 ; + savedata + "\MPposition{" & decimal current_position & "}{" + & decimal xpart p & "}{" + & decimal ypart p & "}%" ; +enddef ; + +%D settings + +grid_width := 60pt ; grid_height := 40pt ; +shape_width := 45pt ; shape_height := 30pt ; + +chart_offset := 2pt ; +color chart_background_color ; chart_background_color := white ; + +%D test mode + +boolean show_mid_points ; show_mid_points := false ; +boolean show_con_points ; show_con_points := false ; +boolean show_all_points ; show_all_points := false ; + +%D shapes + +color shape_line_color, shape_fill_color ; + +shape_line_width := 2pt ; +shape_line_color := .5white ; +shape_fill_color := .9white ; + +shape_node := 0 ; +shape_action := 24 ; +shape_procedure := 5 ; +shape_product := 12 ; +shape_decision := 14 ; +shape_archive := 19 ; +shape_loop := 35 ; +shape_wait := 6 ; +shape_subprocedure := 20 ; shape_sub_procedure := 20 ; +shape_singledocument := 32 ; shape_single_document := 32 ; +shape_multidocument := 33 ; shape_multi_document := 33 ; +shape_right := 66 ; +shape_left := 67 ; +shape_up := 68 ; +shape_down := 69 ; + +% vardef some_shape_path (expr type) == imported from mp-shap + +def show_shapes (expr n) = + + begin_chart(n,8,10) ; + show_con_points := true ; + for i=0 upto 7 : + for j=0 upto 9 : + new_shape(i+1,j+1,i*10+j); + endfor ; + endfor ; + end_chart ; + +enddef ; + +%D connections + +def new_chart = + + color connection_line_color ; + + connection_line_width := shape_line_width ; + connection_line_color := .8white ; + connection_smooth_size := 5pt ; + connection_arrow_size := 4pt ; + connection_dash_size := 3pt ; + + max_x := 6 ; + max_y := 4 ; + + numeric xypoint ; xypoint := 0 ; + + pair xypoints [] ; + + boolean xyfree [][] ; + path xypath [][] ; + numeric xysx [][] ; + numeric xysy [][] ; + color xyfill [][] ; + color xydraw [][] ; + numeric xyline [][] ; + boolean xypeep [][] ; + picture xypicture[][] ; + + numeric cpath ; cpath := 0 ; + path cpaths [] ; + numeric cline [] ; + color ccolor [] ; + boolean carrow [] ; + boolean cdash [] ; + boolean ccross [] ; + + boolean smooth ; smooth := true ; + boolean peepshape ; peepshape := false ; + boolean arrowtip ; arrowtip := true ; + boolean dashline ; dashline := false ; + boolean forcevalid ; forcevalid := false ; + boolean touchshape ; touchshape := false ; + boolean showcrossing ; showcrossing := false ; + + picture dash_pattern ; + + boolean reverse_y ; reverse_y := true ; + +enddef ; + +new_chart ; + +def y_pos (expr y) = + if reverse_y : max_y + 1 - y else : y fi +enddef ; + +def initialize_grid (expr maxx, maxy) = + begingroup ; + save i, j ; + max_x := maxx ; + max_y := maxy ; + dsp_x := 0 ; + dsp_y := 0 ; + for x=1 upto max_x : + for y=1 upto max_y : + xyfree [x][y] := true ; + xyfill [x][y] := shape_fill_color ; + xydraw [x][y] := shape_line_color ; + xyline [x][y] := shape_line_width ; + endfor ; + endfor ; + endgroup ; +enddef ; + +def scaled_to_grid = + xscaled grid_width yscaled grid_height +enddef ; + +def xy_offset (expr x, y) = + (x+.5,y+.5) +enddef ; + +def draw_shape (expr x, yy, p, sx, sy) = + begingroup ; + save y ; + y := y_pos(yy) ; + xypath [x][y] := (p xscaled sx yscaled sy) shifted xy_offset(x,y) ; + xyfree [x][y] := false ; + xysx [x][y] := sx ; + xysy [x][y] := sy ; + xyfill [x][y] := shape_fill_color ; + xydraw [x][y] := shape_line_color ; + xyline [x][y] := shape_line_width ; + xypeep [x][y] := peepshape ; + endgroup ; +enddef ; + +vardef i_point (expr x, y, p, t) = + begingroup ; + save q, ok ; + pair q ; + boolean ok ; + q := xypath[x][y] intersection_point ((p) shifted xy_offset(x,y)) ; + ok := true ; +% if xpart q < -.5 : ok := false ; q := (-.45,ypart q) fi ; +% if xpart q > .5 : ok := false ; q := ( .45,ypart q) fi ; +% if ypart q < -.5 : ok := false ; q := (xpart q,-.45) fi ; +% if ypart q > .5 : ok := false ; q := (xpart q, .45) fi ; + if not ok : + message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ; + fi ; + q + endgroup +enddef ; + +vardef trimmed (expr x, y, z, t) = + if touchshape and t : xyline[x][y]/z else : epsilon fi +enddef ; + +zfactor := 1/3 ; + +vardef xy_bottom (expr x, y, z, t) = + i_point (x, y, ((0,0)--(0,-2)) shifted (zfactor*z*xysx[x][y],0), "bottom") + shifted(0,-trimmed(x,y,grid_height,t)) +enddef ; + +vardef xy_top (expr x, y, z, t) = + i_point (x, y, ((0,0)--(0,2)) shifted (zfactor*z*xysx[x][y],0), "top") + shifted(0,trimmed(x,y,grid_height,t)) +enddef ; + +vardef xy_left (expr x, y, z, t) = + i_point (x, y, ((0,0)--(-2,0)) shifted (0,zfactor*z*xysy[x][y]), "left") + shifted(-trimmed(x,y,grid_width,t),0) +enddef ; + +vardef xy_right (expr x, y, z, t) = + i_point (x, y, ((0,0)--(2,0)) shifted (0,zfactor*z*xysy[x][y]), "right") + shifted(trimmed(x,y,grid_width,t),0) +enddef ; + +def flush_shapes = + for x=1 upto max_x : + for y=1 upto max_y : + flush_shape (x, y) ; + endfor ; + endfor ; +enddef ; + +def flush_pictures = + for x=1 upto max_x : + for y=1 upto max_y : + flush_picture (x, y) ; + endfor ; + endfor ; +enddef ; + + +def draw_connection_point (expr x, y, z) = + pickup pencircle scaled if (z=0): 2 fi xyline[x][y] ; + drawdot xy_bottom(x,y,z,false) scaled_to_grid withcolor (1,0,0) ; + drawdot xy_top (x,y,z,false) scaled_to_grid withcolor (0,1,0) ; + drawdot xy_left (x,y,z,false) scaled_to_grid withcolor (0,0,1) ; + drawdot xy_right (x,y,z,false) scaled_to_grid withcolor (1,1,0) ; +enddef ; + +def flush_shape (expr x, yy) = + begingroup ; + save y ; + y := y_pos(yy) ; + if not xyfree[x][y] : + pickup pencircle scaled xyline[x][y] ; + if xypeep[x][y] : + fill (xypath[x][y] peepholed (unitsquare shifted (x,y))) + scaled_to_grid withpen pencircle scaled 0 + withcolor chart_background_color ; + else : + fill xypath[x][y] scaled_to_grid withcolor xyfill[x][y] ; + fi ; + draw xypath[x][y] scaled_to_grid withcolor xydraw[x][y] ; + if show_con_points or show_all_points : + draw_connection_point (x, y, 0) ; + fi ; + if show_all_points : + for i=-1 upto 1 : + draw_connection_point (x, y, i) ; + endfor ; + fi ; + fi ; + endgroup ; +enddef ; + +vardef points_initialized (expr xfrom, yfrom, xto, yto, n) = + if not xyfree[xfrom][yfrom] and not xyfree[xto][yto] : + xypoint := n ; true + else : + xypoint := 0 ; false + fi +enddef ; + +def collapse_points = + % remove redundant points + n := 1 ; + for i=2 upto xypoint: + if not (xypoints[i]=xypoints[n]) : + n := n + 1 ; + xypoints[n] := xypoints[i] + fi ; + endfor ; + xypoint := n ; + % make straight lines + if xypoints[2]=xypoints[xypoint-1] : + xypoints[3] := xypoints[xypoint] ; + xypoint := 3 ; + fi ; +enddef ; + +vardef smooth_connection (expr a,b) = + sx := connection_smooth_size/grid_width ; + sy := connection_smooth_size/grid_height ; + if ypart a = ypart b : + a shifted (if xpart a >= xpart b : - fi sx,0) +% a shifted (sx*xpart unitvector(b-a),0) + else : + a shifted (0,if ypart a >= ypart b : - fi sy) +% a shifted (0,sy*ypart unitvector(b-a)) + fi +enddef ; + +vardef trim_points = + begingroup + save p, a, b, d, i ; path p ; pair d ; + p := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ; + if touchshape : + a := shape_line_width/grid_width ; + b := shape_line_width/grid_height ; + else : + a := epsilon ; + b := epsilon ; + fi ; + d := direction infinity of p ; + xypoints[xypoint] := xypoints[xypoint] shifted + if xpart d < 0 : (+a,0) ; + elseif xpart d > 0 : (-a,0) ; + elseif ypart d < 0 : (0,+b) ; + elseif ypart d > 0 : (0,-b) ; + else : origin ; + fi ; + d := direction 0 of p ; + xypoints[1] := xypoints[1] shifted + if xpart d < 0 : (-a,0) ; + elseif xpart d > 0 : (+a,0) ; + elseif ypart d < 0 : (0,-b) ; + elseif ypart d > 0 : (0,+b) ; + else : origin ; + fi ; + endgroup +enddef ; + +vardef trim_points = enddef ; + +vardef connection_path = + if reverse_connection : reverse fi (xypoints[1]-- + for i=2 upto xypoint-1 : + if smooth : + smooth_connection(xypoints[i],xypoints[i-1]) .. + controls xypoints[i] and xypoints[i] .. + smooth_connection(xypoints[i],xypoints[i+1]) -- + else : + xypoints[i]-- + fi + endfor + xypoints[xypoint]) +enddef ; + +% vardef connection_path = +% sx := connection_smooth_size/grid_width ; +% sy := connection_smooth_size/grid_height ; +% if reverse_connection : reverse fi +% (for i=1 upto xypoint-1 : xypoints[i] -- endfor xypoints[xypoint]) +% if smooth : cornered max(sx,sy) fi +% enddef ; +% +% primarydef p cornered c = +% if cycle p : +% ((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) +% else : +% ((point 0 of p) -- +% for i=1 upto length(p)-1 : +% (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 +% (point length(p) of p)) +% fi +% enddef ; + +def draw_connection = + if xypoint>0 : + collapse_points ; + trim_points ; + cpath := cpath + 1 ; + cpaths[cpath] := connection_path scaled_to_grid ; + cline[cpath] := connection_line_width ; + ccolor[cpath] := connection_line_color ; + carrow[cpath] := arrowtip ; + cdash[cpath] := dashline ; + ccross[cpath] := showcrossing ; + else : + message("no connection defined") ; + fi ; + reverse_connection := false ; +enddef ; + +def flush_connections = + pair ip ; + boolean crossing ; + ahlength := connection_arrow_size ; + dash_pattern := dashpattern(on connection_dash_size off connection_dash_size ) ; + for i=1 upto cpath : + if ccross[i] : + crossing := false ; + for j=1 upto i : + %if not ((point infinity of cpaths[i] = point infinity of cpaths[j]) or + % (point 0 of cpaths[i] = point 0 of cpaths[j])) : + if not (point infinity of cpaths[i] = point infinity of cpaths[j]) : + ip := cpaths[i] intersection_point cpaths[j] ; + if intersection_found : crossing := true fi ; + fi ; + endfor ; + if crossing : + pickup pencircle scaled 2cline[i] ; + %draw cpaths[i] withcolor chart_background_color ; + path cp ; cp := cpaths[i] ; + cp := cp cutbefore point .05 length cp of cp ; + cp := cp cutafter point .95 length cp of cp ; + draw cp withcolor chart_background_color ; + fi ; + fi ; + pickup pencircle scaled cline[i] ; + if carrow[i] : + if cdash[i] : + drawarrow cpaths[i] withcolor ccolor[i] dashed dash_pattern ; + else : + drawarrow cpaths[i] withcolor ccolor[i] ; + fi ; + else : + if cdash[i] : + draw cpaths[i] withcolor ccolor[i] dashed dash_pattern ; + else : + draw cpaths[i] withcolor ccolor[i] ; + fi ; + fi ; + draw_midpoint (i) ; + endfor ; +enddef ; + +def draw_midpoint (expr n) = + begingroup + save p ; + pair p ; + p := point .5*length(cpaths[n]) of cpaths[n]; + pickup pencircle scaled 2cline[n] ; + save_text_position (p) ; + if show_mid_points : + drawdot p withcolor .7white ; + fi ; + endgroup ; +enddef ; + +def flush_picture(expr x, y) = + if known xypicture[x][y]: + draw xypicture[x][y] shifted xy_offset((x+0.5)*grid_width,(max_y-y+1.5)*grid_height) ; + fi ; +enddef ; + +def chart_draw_picture(expr x, y, p) = + xypicture[x][y] := p ; +enddef ; + +boolean reverse_connection ; reverse_connection := false ; + +vardef up_on_grid (expr n) = + (xpart xypoints[n],(ypart xypoints[n]+1) div 1) +enddef ; + +vardef down_on_grid (expr n) = + (xpart xypoints[n],(ypart xypoints[n]) div 1) +enddef ; + +vardef left_on_grid (expr n) = + ((xpart xypoints[n]) div 1, ypart xypoints[n]) +enddef ; + +vardef right_on_grid (expr n) = + ((xpart xypoints[n]+1) div 1, ypart xypoints[n]) +enddef ; + +vardef x_on_grid (expr n, xfrom, xto, zfrom) = + if (xfrom=xto) and not (zfrom=0) : + if (zfrom=1) : right_on_grid(2) else : left_on_grid(2) fi + elseif xpart xypoints[1] < xpart xypoints[6] : + right_on_grid(n) + else : + left_on_grid(n) + fi +enddef ; + +vardef y_on_grid (expr n, yfrom, yto, zfrom) = + if (yfrom=yto) and not (zfrom=0) : + if (zfrom=1) : up_on_grid(2) else : down_on_grid(2) fi + elseif ypart xypoints[1] < ypart xypoints[6] : + up_on_grid(n) + else : + down_on_grid(n) + fi +enddef ; + +vardef xy_on_grid (expr n, m) = + (xpart xypoints[n], ypart xypoints[m]) +enddef ; + +vardef down_to_grid (expr a,b) = + (xpart xypoints[a], + ypart xypoints[if ypart xypoints[a]<ypart xypoints[b]:a else:b fi]) +enddef ; + +vardef up_to_grid (expr a,b) = + (xpart xypoints[a], + ypart xypoints[if ypart xypoints[a]>ypart xypoints[b]:a else:b fi]) +enddef ; + +vardef left_to_grid (expr a,b) = + (xpart xypoints[if xpart xypoints[a]<xpart xypoints[b]:a else:b fi], + ypart xypoints[a]) +enddef ; + +vardef right_to_grid (expr a,b) = + (xpart xypoints[if xpart xypoints[a]>xpart xypoints[b]:a else:b fi], + ypart xypoints[a]) +enddef ; + +% vardef boundingboxfraction(expr p, f) = +% ((boundingbox p) enlarged (-f*bbwidth(p),-f*bbheight(p))) +% enddef ; + +vardef valid_connection (expr xfrom, yfrom, xto, yto) = + begingroup ; + save ok, vc, pp ; + boolean ok ; + % check for slanted lines + ok := true ; + for i=1 upto xypoint-1 : + if not ((xpart xypoints[i]=xpart xypoints[i+1]) or + (ypart xypoints[i]=ypart xypoints[i+1])) : ok := false ; + fi ; + endfor ; + if not ok : + %message("slanted"); + false + elseif forcevalid : + %message("force"); + true + elseif (xfrom=xto) and (yfrom=yto) : + %message("self"); + false + else : + % check for crossing shapes + pair vc ; + path pp ; + + pair xyfirst, xylast ; + xyfirst := xypoints[1] ; + xylast := xypoints[xypoint] ; + trim_points ; + pp := for i=1 upto xypoint-1 : xypoints[i]-- endfor xypoints[xypoint] ; + xypoints[1] := xyfirst ; + xypoints[xypoint] := xylast ; + + for i=1 upto max_x : + for j=1 upto max_y : % was bug: xfrom,yto + if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) : + if not xyfree[i][j] : + vc := pp intersection_point xypath[i][j] ; + if intersection_found : ok := false fi ; + fi ; + fi ; + endfor ; + endfor ; + %if not ok: message("crossing") ; fi ; + ok + fi + endgroup +enddef ; + +def connect_top_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_bottom(xto,yto,zto,true) ; + xypoints[2] := up_on_grid(1) ; + xypoints[5] := down_on_grid(6) ; + xypoints[3] := up_to_grid(2,5) ; + xypoints[4] := up_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ; + xypoints[4] := xy_on_grid(3,5) ; + fi ; + %%%% begin experiment + xypoints[3] := xypoints[3] shifted (dsp_x,0) ; + xypoints[4] := xypoints[4] shifted (dsp_x,0) ; + if dsp_y>0 : + xypoints[2] := xypoints[2] shifted (0,dsp_y) ; + xypoints[3] := xypoints[3] shifted (0,dsp_y) ; + elseif dsp_y<0 : + xypoints[4] := xypoints[4] shifted (0,dsp_y) ; + xypoints[5] := xypoints[5] shifted (0,dsp_y) ; + fi + %%%% end experiment + draw_connection ; + fi ; +enddef ; + +def connect_left_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_right(xto,yto,zto,true) ; + xypoints[2] := left_on_grid(1) ; + xypoints[5] := right_on_grid(6) ; + xypoints[3] := left_to_grid(2,5) ; + xypoints[4] := left_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ; + xypoints[4] := xy_on_grid(5,3) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_left_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,5) : + xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ; + xypoints[5] := xy_top(xto,yto,zto,true) ; + xypoints[2] := left_on_grid(1) ; + xypoints[4] := up_on_grid(5) ; + xypoints[3] := left_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := xy_on_grid(2,4) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_left_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,5) : + xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ; + xypoints[5] := xy_bottom(xto,yto,zto,true) ; + xypoints[2] := left_on_grid(1) ; + xypoints[4] := down_on_grid(5) ; + xypoints[3] := left_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := xy_on_grid(2,4) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_right_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,5) : + xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ; + xypoints[5] := xy_top(xto,yto,zto,true) ; + xypoints[2] := right_on_grid(1) ; + xypoints[4] := up_on_grid(5) ; + xypoints[3] := right_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := xy_on_grid(2,4) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_right_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,5) : + xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ; + xypoints[5] := xy_bottom(xto,yto,zto,true) ; + xypoints[2] := right_on_grid(1) ; + xypoints[4] := down_on_grid(5) ; + xypoints[3] := right_to_grid(2,5) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := xy_on_grid(2,4) ; + fi ; + %%%% begin experiment + xypoints[2] := xypoints[2] shifted (dsp_x,0) ; + xypoints[3] := xypoints[3] shifted (dsp_x,0) ; + if dsp_y>0 : + xypoints[3] := xypoints[3] shifted (0,-dsp_y) ; + xypoints[4] := xypoints[4] shifted (0,-dsp_y) ; + elseif dsp_y<0 : + xypoints[3] := xypoints[3] shifted (0,dsp_y) ; + xypoints[4] := xypoints[4] shifted (0,dsp_y) ; + fi + %%%% end experiment + draw_connection ; + fi ; +enddef ; + +def connect_left_left (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_left(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_left(xto,yto,zto,true) ; + xypoints[2] := left_on_grid(1) ; + xypoints[5] := left_on_grid(6) ; + xypoints[3] := left_to_grid(2,5) ; + xypoints[4] := left_to_grid(5,2) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ; + xypoints[4] := xy_on_grid(5,3) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_right_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_right(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_right(xto,yto,zto,true) ; + xypoints[2] := right_on_grid(1) ; + xypoints[5] := right_on_grid(6) ; + xypoints[3] := right_to_grid(2,5) ; + xypoints[4] := right_to_grid(5,2) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := y_on_grid(2,yfrom,yto,zfrom) ; + xypoints[4] := xy_on_grid(5,3) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_top_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_top(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_top(xto,yto,zto,true) ; + xypoints[2] := up_on_grid(1) ; + xypoints[5] := up_on_grid(6) ; + xypoints[3] := up_to_grid(2,5) ; + xypoints[4] := up_to_grid(5,2) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ; + xypoints[4] := xy_on_grid(3,5) ; + fi ; + draw_connection ; + fi ; +enddef ; + +def connect_bottom_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := y_pos(yyfrom) ; yto := y_pos(yyto) ; + if points_initialized(xfrom,yfrom,xto,yto,6) : + xypoints[1] := xy_bottom(xfrom,yfrom,zfrom,true) ; + xypoints[6] := xy_bottom(xto,yto,zto,true) ; + xypoints[2] := down_on_grid(1) ; + xypoints[5] := down_on_grid(6) ; + xypoints[3] := down_to_grid(2,5) ; + xypoints[4] := down_to_grid(5,2) ; + if not valid_connection(xfrom,yfrom,xto,yto) : + xypoints[3] := x_on_grid(2,xfrom,xto,zfrom) ; + xypoints[4] := xy_on_grid(3,5) ; + fi ; + %%%% begin experiment + xypoints[3] := xypoints[3] shifted (dsp_x,0) ; + xypoints[4] := xypoints[4] shifted (dsp_x,0) ; + if dsp_y<0 : + xypoints[2] := xypoints[2] shifted (0,-dsp_y) ; + xypoints[3] := xypoints[3] shifted (0,-dsp_y) ; + elseif dsp_y>0 : + xypoints[4] := xypoints[4] shifted (0,dsp_y) ; + xypoints[5] := xypoints[5] shifted (0,dsp_y) ; + fi + %%%% end experiment + draw_connection ; + fi ; +enddef ; + +def connect_bottom_top (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_top_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def connect_right_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_left_right (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def connect_top_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_left_top (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def connect_bottom_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_left_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def connect_top_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_right_top (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def connect_bottom_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + reverse_connection := true ; + connect_right_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def draw_test_shape (expr x, y) = + draw_shape(x,y,fullcircle, .7, .7) ; +enddef ; + +def draw_test_shapes = + for i=1 upto max_x : + for j=1 upto max_y : + draw_test_shape(i,j) ; + endfor ; + endfor ; +enddef; + +def draw_test_area = + pickup pencircle scaled .5shape_line_width ; + draw (unitsquare xscaled max_x yscaled max_y shifted (1,1)) + scaled_to_grid withcolor blue ; +enddef ; + +def show_connection (expr n, m) = + + begin_chart(100+n,6,6) ; + + draw_test_area ; + + smooth := true ; + arrowtip := true ; + dashline := true ; + + draw_test_shape(2,2) ; draw_test_shape(4,5) ; + draw_test_shape(3,3) ; draw_test_shape(5,1) ; + draw_test_shape(2,5) ; draw_test_shape(1,3) ; + draw_test_shape(6,2) ; draw_test_shape(4,6) ; + + if (m=1) : + connect_top_bottom (2,2,0) (4,5,0) ; + connect_top_bottom (3,3,0) (5,1,0) ; + connect_top_bottom (2,5,0) (1,3,0) ; + connect_top_bottom (6,2,0) (4,6,0) ; + elseif (m=2) : + connect_top_top (2,2,0) (4,5,0) ; + connect_top_top (3,3,0) (5,1,0) ; + connect_top_top (2,5,0) (1,3,0) ; + connect_top_top (6,2,0) (4,6,0) ; + elseif (m=3) : + connect_bottom_bottom (2,2,0) (4,5,0) ; + connect_bottom_bottom (3,3,0) (5,1,0) ; + connect_bottom_bottom (2,5,0) (1,3,0) ; + connect_bottom_bottom (6,2,0) (4,6,0) ; + elseif (m=4) : + connect_left_right (2,2,0) (4,5,0) ; + connect_left_right (3,3,0) (5,1,0) ; + connect_left_right (2,5,0) (1,3,0) ; + connect_left_right (6,2,0) (4,6,0) ; + elseif (m=5) : + connect_left_left (2,2,0) (4,5,0) ; + connect_left_left (3,3,0) (5,1,0) ; + connect_left_left (2,5,0) (1,3,0) ; + connect_left_left (6,2,0) (4,6,0) ; + elseif (m=6) : + connect_right_right (2,2,0) (4,5,0) ; + connect_right_right (3,3,0) (5,1,0) ; + connect_right_right (2,5,0) (1,3,0) ; + connect_right_right (6,2,0) (4,6,0) ; + elseif (m=7) : + connect_left_top (2,2,0) (4,5,0) ; + connect_left_top (3,3,0) (5,1,0) ; + connect_left_top (2,5,0) (1,3,0) ; + connect_left_top (6,2,0) (4,6,0) ; + elseif (m=8) : + connect_left_bottom (2,2,0) (4,5,0) ; + connect_left_bottom (3,3,0) (5,1,0) ; + connect_left_bottom (2,5,0) (1,3,0) ; + connect_left_bottom (6,2,0) (4,6,0) ; + elseif (m=9) : + connect_right_top (2,2,0) (4,5,0) ; + connect_right_top (3,3,0) (5,1,0) ; + connect_right_top (2,5,0) (1,3,0) ; + connect_right_top (6,2,0) (4,6,0) ; + else : + connect_right_bottom (2,2,0) (4,5,0) ; + connect_right_bottom (3,3,0) (5,1,0) ; + connect_right_bottom (2,5,0) (1,3,0) ; + connect_right_bottom (6,2,0) (4,6,0) ; + fi ; + + end_chart ; + +enddef ; + +def show_connections = + for f=1 upto 10 : + show_connection(f,f) ; + endfor ; +enddef ; + +%D charts + +def clip_chart (expr minx, miny, maxx, maxy) = + cmin_x := minx ; + cmax_x := maxx ; + cmin_y := miny ; + cmax_y := maxy ; +enddef ; + +def begin_chart (expr n, maxx, maxy) = + new_chart ; + chart_figure := n ; + chart_scale := 1 ; + if chart_figure>0: beginfig(chart_figure) ; fi ; + startsavingdata ; + initialize_grid (maxx, maxy) ; + bboxmargin := 0 ; + cmin_x := 1 ; + cmax_x := maxx ; + cmin_y := 1 ; + cmax_y := maxy ; +enddef ; + +def end_chart = + flush_shapes ; + flush_connections ; + flush_pictures ; + cmin_x := cmin_x ; + cmax_x := cmin_x+cmax_x ; + cmin_y := cmin_y-1 ; + cmax_y := cmin_y+cmax_y ; + if reverse_y : + cmin_y := y_pos(cmin_y) ; + cmax_y := y_pos(cmax_y) ; + fi ; + path p ; + p := (((cmin_x,cmin_y)--(cmax_x,cmin_y)-- + (cmax_x,cmax_y)--(cmin_x,cmax_y)--cycle)) + scaled_to_grid ; + %draw p withcolor red ; + p := p enlarged chart_offset ; + clip currentpicture to p ; + setbounds currentpicture to p ; + savedata + "\MPclippath{" & + decimal xpart llcorner p & "}{" & + decimal ypart llcorner p & "}{" & + decimal xpart urcorner p & "}{" & + decimal ypart urcorner p & "}%" ; + savedata + "\MPareapath{" & + decimal (xpart llcorner p + 2chart_offset) & "}{" & + decimal (ypart llcorner p + 2chart_offset) & "}{" & + decimal (xpart urcorner p - 2chart_offset) & "}{" & + decimal (ypart urcorner p - 2chart_offset) & "}%" ; + currentpicture := currentpicture scaled chart_scale ; + stopsavingdata ; + if chart_figure>0: endfig ; fi ; +enddef ; + +def new_shape (expr x, y, n) = + if known n : + if (x>0) and (x<=max_x) and (y>0) and (y<=max_y) : + sx := shape_width/grid_width ; + sy := shape_height/grid_height ; + draw_shape(x,y,some_shape_path(n), sx, sy) ; + else : + message ("shape outside grid ignored") ; + fi ; + else + message ("shape not known" ) ; + fi ; +enddef ; + +def begin_sub_chart = + begingroup ; + save shape_line_width , connection_line_width ; + save shape_line_color, shape_fill_color, connection_line_color ; + color shape_line_color, shape_fill_color, connection_line_color ; + save smooth, arrowtip, dashline, peepshape ; + boolean smooth, arrowtip, dashline, peepshape ; +enddef ; + +def end_sub_chart = + endgroup ; +enddef ; + +%D done + +endinput ; + +%D testing + +show_shapes(100) ; + +end + +%D more testing + +show_connections ; + +begin_chart (1,4,5) ; + %clip_chart(1,1,1,2) ; + new_shape (1,1,31) ; + new_shape (1,2,3) ; + new_shape (4,4,5) ; + connect_top_left (1,1,0) (4,4,0) ; + connect_bottom_top (1,2,0) (4,4,0) ; + connect_left_right (1,2,0) (1,1,0) ; +end_chart ; + +end diff --git a/metapost/context/base/mp-char.mpiv b/metapost/context/base/mp-char.mpiv new file mode 100644 index 000000000..f2bbb8b68 --- /dev/null +++ b/metapost/context/base/mp-char.mpiv @@ -0,0 +1,1019 @@ +%D \module +%D [ file=mp-char.mp, +%D version=2011.10.1, % 1998.10.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=charts, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D This is ancient code .. but I see no need to rewrite it. + +if unknown context_shap : input "mp-shap.mpiv" ; fi ; +if known context_flow : endinput ; fi ; + +boolean context_flow ; context_flow := true ; + +%D settings + +numeric flow_grid_width ; flow_grid_width := 60pt ; +numeric flow_shape_width ; flow_shape_width := 45pt ; +numeric flow_grid_height ; flow_grid_height := 40pt ; +numeric flow_shape_height ; flow_shape_height := 30pt ; +numeric flow_chart_offset ; flow_chart_offset := 2pt ; +color flow_chart_background_color ; flow_chart_background_color := white ; +boolean flow_show_mid_points ; flow_show_mid_points := false ; +boolean flow_show_con_points ; flow_show_con_points := false ; +boolean flow_show_all_points ; flow_show_all_points := false ; +numeric flow_shape_line_width ; flow_shape_line_width := 2pt ; +color flow_shape_line_color ; flow_shape_line_color := .5white ; +color flow_shape_fill_color ; flow_shape_fill_color := .9white ; +color flow_connection_line_color ; flow_connection_line_color := .2white ; + +numeric flow_connection_line_width ; flow_connection_line_width := flow_shape_line_width ; + +numeric flow_connection_smooth_size ; flow_connection_smooth_size := 5pt ; +numeric flow_connection_arrow_size ; flow_connection_arrow_size := 4pt ; +numeric flow_connection_dash_size ; flow_connection_dash_size := 3pt ; + +numeric flow_max_x ; flow_max_x := 6 ; +numeric flow_max_y ; flow_max_y := 4 ; + +boolean flow_smooth ; flow_smooth := true ; +boolean flow_peepshape ; flow_peepshape := false ; +boolean flow_arrowtip ; flow_arrowtip := true ; +boolean flow_dashline ; flow_dashline := false ; +boolean flow_forcevalid ; flow_forcevalid := false ; +boolean flow_touchshape ; flow_touchshape := false ; +boolean flow_showcrossing ; flow_showcrossing := false ; +boolean flow_reverse_y ; flow_reverse_y := true ; + +picture flow_dash_pattern ; flow_dash_pattern := nullpicture ; + +numeric flow_shape_node ; flow_shape_node := 0 ; +numeric flow_shape_action ; flow_shape_action := 24 ; +numeric flow_shape_procedure ; flow_shape_procedure := 5 ; +numeric flow_shape_product ; flow_shape_product := 12 ; +numeric flow_shape_decision ; flow_shape_decision := 14 ; +numeric flow_shape_archive ; flow_shape_archive := 19 ; +numeric flow_shape_loop ; flow_shape_loop := 35 ; +numeric flow_shape_wait ; flow_shape_wait := 6 ; +numeric flow_shape_subprocedure ; flow_shape_subprocedure := 20 ; +numeric flow_shape_singledocument ; flow_shape_singledocument := 32 ; +numeric flow_shape_multidocument ; flow_shape_multidocument := 33 ; +numeric flow_shape_right ; flow_shape_right := 66 ; +numeric flow_shape_left ; flow_shape_left := 67 ; +numeric flow_shape_up ; flow_shape_up := 68 ; +numeric flow_shape_down ; flow_shape_down := 69 ; + +% vardef some_shape_path (expr type) == imported from mp-shap + +def flow_show_shapes(expr n) = + flow_begin_chart(n,8,10) ; + flow_show_con_points := true ; + for i=0 upto 7 : + for j=0 upto 9 : + flow_new_shape(i+1,j+1,i*10+j); + endfor ; + endfor ; + flow_end_chart ; +enddef ; + +%D connections + +def flow_new_chart = + + flow_grid_width := 60pt ; + flow_shape_width := 45pt ; + flow_grid_height := 40pt ; + flow_shape_height := 30pt ; + flow_chart_offset := 2pt ; + flow_chart_background_color := white ; + flow_show_mid_points := false ; + flow_show_con_points := false ; + flow_show_all_points := false ; + flow_shape_line_width := 2pt ; + flow_shape_line_color := .5white ; + flow_shape_fill_color := .9white ; + flow_connection_line_color := .2white ; + flow_connection_line_width := flow_shape_line_width ; + flow_connection_smooth_size := 5pt ; + flow_connection_arrow_size := 4pt ; + flow_connection_dash_size := 3pt ; + + flow_max_x := 6 ; + flow_max_y := 4 ; + + flow_smooth := true ; + flow_peepshape := false ; + flow_arrowtip := true ; + flow_dashline := false ; + flow_forcevalid := false ; + flow_touchshape := false ; + flow_showcrossing := false ; + flow_reverse_y := true ; + + flow_dash_pattern := nullpicture ; + + numeric flow_xypoint ; flow_xypoint := 0 ; + numeric flow_cpath ; flow_cpath := 0 ; + + pair flow_xypoints [] ; + boolean flow_xyfree [][] ; + path flow_xypath [][] ; + numeric flow_xysx [][] ; + numeric flow_xysy [][] ; + color flow_xyfill [][] ; + color flow_xydraw [][] ; + numeric flow_xyline [][] ; + boolean flow_xypeep [][] ; + picture flow_xytext [][] ; + picture flow_xylabel_l[][] ; + picture flow_xylabel_r[][] ; + picture flow_xylabel_t[][] ; + picture flow_xylabel_b[][] ; + picture flow_xyexit_l [][] ; + picture flow_xyexit_r [][] ; + picture flow_xyexit_t [][] ; + picture flow_xyexit_b [][] ; + path flow_cpaths [] ; + numeric flow_cline [] ; + color flow_ccolor [] ; + boolean flow_carrow [] ; + boolean flow_cdash [] ; + boolean flow_ccross [] ; + + picture flow_tpicture[][] ; + picture flow_bpicture[][] ; + picture flow_lpicture[][] ; + picture flow_rpicture[][] ; + + predefined_shapes[61] := (fullcircle scaled (1.5*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ; + predefined_shapes[62] := (fullcircle scaled (2.0*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ; + +enddef ; + +flow_new_chart ; + +def flow_y_pos(expr y) = + if flow_reverse_y : + flow_max_y + 1 - y + else : + y + fi +enddef ; + +def flow_initialize_grid(expr maxx, maxy) = + flow_max_x := maxx ; + flow_max_y := maxy ; + flow_dsp_x := 0 ; + flow_dsp_y := 0 ; + for x=1 upto flow_max_x : + for y=1 upto flow_max_y : + flow_xyfree[x][y] := true ; + flow_xyfill[x][y] := flow_shape_fill_color ; + flow_xydraw[x][y] := flow_shape_line_color ; + flow_xyline[x][y] := flow_shape_line_width ; + endfor ; + endfor ; +enddef ; + +def flow_scaled_to_grid = + xscaled flow_grid_width yscaled flow_grid_height +enddef ; + +def flow_xy_offset(expr x, y) = + (x+.5,y+.5) +enddef ; + +def flow_draw_shape(expr x, yy, p, sx, sy) = + begingroup ; + save y ; numeric y ; + y := flow_y_pos(yy) ; + flow_xypath [x][y] := (p xscaled sx yscaled sy) shifted flow_xy_offset(x,y) ; + flow_xyfree [x][y] := false ; + flow_xysx [x][y] := sx ; + flow_xysy [x][y] := sy ; + flow_xyfill [x][y] := flow_shape_fill_color ; + flow_xydraw [x][y] := flow_shape_line_color ; + flow_xyline [x][y] := flow_shape_line_width ; + flow_xypeep [x][y] := flow_peepshape ; + endgroup ; +enddef ; + +vardef flow_i_point (expr x, y, p, t) = + begingroup ; + save q, ok ; pair q ; boolean ok ; + q := flow_xypath[x][y] intersection_point ((p) shifted flow_xy_offset(x,y)) ; + ok := true ; + if not ok : + message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ; + fi ; + q + endgroup +enddef ; + +vardef flow_trimmed (expr x, y, z, t) = + if flow_touchshape and t : + flow_xyline[x][y]/z + else : + epsilon + fi +enddef ; + +numeric flow_zfactor ; flow_zfactor := 1/3 ; + +vardef flow_xy_bottom (expr x, y, z, t) = + flow_i_point(x, y, ((0,0)--(0,-2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "bottom") + shifted(0,-flow_trimmed(x,y,flow_grid_height,t)) +enddef ; + +vardef flow_xy_top (expr x, y, z, t) = + flow_i_point (x, y, ((0,0)--(0,2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "top") + shifted(0,flow_trimmed(x,y,flow_grid_height,t)) +enddef ; + +vardef flow_xy_left (expr x, y, z, t) = + flow_i_point (x, y, ((0,0)--(-2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "left") + shifted(-flow_trimmed(x,y,flow_grid_width,t),0) +enddef ; + +vardef flow_xy_right (expr x, y, z, t) = + flow_i_point (x, y, ((0,0)--(2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "right") + shifted(flow_trimmed(x,y,flow_grid_width,t),0) +enddef ; + +def flow_flush_shapes = + for x=1 upto flow_max_x : + for y=1 upto flow_max_y : + flow_flush_shape(x, y) ; + endfor ; + endfor ; +enddef ; + +def flow_flush_pictures = + for x=1 upto flow_max_x : + for y=1 upto flow_max_y : + flow_flush_picture(x, y) ; + endfor ; + endfor ; +enddef ; + +def flow_draw_connection_point(expr x, y, z) = + pickup pencircle scaled if (z=0): 2 fi flow_xyline[x][y] ; + drawdot flow_xy_bottom(x,y,z,false) flow_scaled_to_grid withcolor (1,0,0) ; + drawdot flow_xy_top (x,y,z,false) flow_scaled_to_grid withcolor (0,1,0) ; + drawdot flow_xy_left (x,y,z,false) flow_scaled_to_grid withcolor (0,0,1) ; + drawdot flow_xy_right (x,y,z,false) flow_scaled_to_grid withcolor (1,1,0) ; +enddef ; + +def flow_flush_shape(expr x, yy) = + begingroup ; + save y ; numeric y ; + y := flow_y_pos(yy) ; + if not flow_xyfree[x][y] : + pickup pencircle scaled flow_xyline[x][y] ; + if flow_xypeep[x][y] : + fill (flow_xypath[x][y] peepholed (unitsquare shifted (x,y))) + flow_scaled_to_grid withpen pencircle scaled 0 + withcolor flow_chart_background_color ; + else : + fill flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xyfill[x][y] ; + fi ; + draw flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xydraw[x][y] ; + if flow_show_con_points or flow_show_all_points : + flow_draw_connection_point(x, y, 0) ; + fi ; + if flow_show_all_points : + for i=-1 upto 1 : + flow_draw_connection_point(x, y, i) ; + endfor ; + fi ; + fi ; + endgroup ; +enddef ; + +vardef flow_points_initialized(expr xfrom, yfrom, xto, yto, n) = + if not flow_xyfree[xfrom][yfrom] and not flow_xyfree[xto][yto] : + flow_xypoint := n ; true + else : + flow_xypoint := 0 ; false + fi +enddef ; + +def flow_collapse_points = % this can become a core macro + begingroup ; + % remove redundant points + save n ; numeric n ; + n := 1 ; + for i=2 upto flow_xypoint : + if not (flow_xypoints[i] = flow_xypoints[n]) : + n := n + 1 ; + flow_xypoints[n] := flow_xypoints[i] + fi ; + endfor ; + flow_xypoint := n ; + % make straight lines + if flow_xypoints[2] = flow_xypoints[flow_xypoint-1] : + flow_xypoints[3] := flow_xypoints[flow_xypoint] ; + flow_xypoint := 3 ; + fi ; + endgroup ; +enddef ; + +vardef flow_smooth_connection(expr a,b) = + if ypart a = ypart b : + a shifted ( if xpart a >= xpart b : - fi (flow_connection_smooth_size/flow_grid_width ),0) + else : + a shifted (0,if ypart a >= ypart b : - fi (flow_connection_smooth_size/flow_grid_height) ) + fi +enddef ; + +vardef flow_trim_points = + begingroup + save p, a, b, d, i ; numeric a, b ; path p ; pair d ; + p := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ; + if flow_touchshape : + a := flow_shape_line_width/flow_grid_width ; + b := flow_shape_line_width/flow_grid_height ; + else : + a := epsilon ; + b := epsilon ; + fi ; + d := direction infinity of p ; + flow_xypoints[flow_xypoint] := flow_xypoints[flow_xypoint] shifted + if xpart d < 0 : (+a,0) ; + elseif xpart d > 0 : (-a,0) ; + elseif ypart d < 0 : (0,+b) ; + elseif ypart d > 0 : (0,-b) ; + else : origin ; + fi ; + d := direction 0 of p ; + flow_xypoints[1] := flow_xypoints[1] shifted + if xpart d < 0 : (-a,0) ; + elseif xpart d > 0 : (+a,0) ; + elseif ypart d < 0 : (0,-b) ; + elseif ypart d > 0 : (0,+b) ; + else : origin ; + fi ; + endgroup +enddef ; + +vardef flow_trim_points = enddef ; + +vardef flow_connection_path = + if flow_reverse_connection : reverse fi (flow_xypoints[1] -- + for i=2 upto flow_xypoint-1 : + if flow_smooth : + flow_smooth_connection(flow_xypoints[i],flow_xypoints[i-1]) .. + controls flow_xypoints[i] and flow_xypoints[i] .. + flow_smooth_connection(flow_xypoints[i],flow_xypoints[i+1]) -- + else : + flow_xypoints[i] -- + fi + endfor + flow_xypoints[flow_xypoint]) +enddef ; + +def flow_draw_connection = + if flow_xypoint > 0 : + flow_collapse_points ; + flow_trim_points ; + flow_cpath := flow_cpath + 1 ; + flow_cpaths[flow_cpath] := flow_connection_path flow_scaled_to_grid ; + flow_cline[flow_cpath] := flow_connection_line_width ; + flow_ccolor[flow_cpath] := flow_connection_line_color ; + flow_carrow[flow_cpath] := flow_arrowtip ; + flow_cdash[flow_cpath] := flow_dashline ; + flow_ccross[flow_cpath] := flow_showcrossing ; + else : + message("no connection defined") ; + fi ; + flow_reverse_connection := false ; +enddef ; + +def flow_flush_connections = % protect locals + begingroup ; + save ip, crossing, cp ; numeric ip ; boolean crossing ; path cp ; + ahlength := flow_connection_arrow_size ; + flow_dash_pattern := dashpattern(on flow_connection_dash_size off flow_connection_dash_size) ; + for i=1 upto flow_cpath : + if flow_ccross[i] : + crossing := false ; + for j=1 upto i : + if not (point infinity of flow_cpaths[i] = point infinity of flow_cpaths[j]) : + ip := flow_cpaths[i] intersection_point flow_cpaths[j] ; + if intersection_found : crossing := true fi ; + fi ; + endfor ; + if crossing : + pickup pencircle scaled 2flow_cline[i] ; + cp := flow_cpaths[i] ; + cp := cp cutbefore point .05 length cp of cp ; + cp := cp cutafter point .95 length cp of cp ; + draw cp withcolor flow_chart_background_color ; + fi ; + fi ; + pickup pencircle scaled flow_cline[i] ; + if flow_carrow[i] : + if flow_cdash[i] : + drawarrow flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ; + else : + drawarrow flow_cpaths[i] withcolor flow_ccolor[i] ; + fi ; + else : + if flow_cdash[i] : + draw flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ; + else : + draw flow_cpaths[i] withcolor flow_ccolor[i] ; + fi ; + fi ; + flow_draw_midpoint(i) ; + endfor ; + endgroup ; +enddef ; + +def flow_draw_midpoint (expr n) = + begingroup + save p ; pair p ; + p := point .5*length(flow_cpaths[n]) of flow_cpaths[n]; + pickup pencircle scaled 2flow_cline[n] ; + if flow_show_mid_points : + drawdot p withcolor .7white ; + fi ; + endgroup ; +enddef ; + +def flow_flush_picture(expr x, yy) = + begingroup ; save y ; numeric y ; + y := flow_y_pos(yy) ; + if known flow_xytext[x][y] : + begingroup ; + % flow_xypath[x][y] + save p, offset ; path p ; pair offset ; + offset := flow_xy_offset((x+0.5)*flow_grid_width,(flow_max_y-y+1.5)*flow_grid_height) ; + offset := offset shifted (-flow_xyline[x][y]/4,-flow_xyline[x][y]/4) ; % terrible hack (some compensation) + p := fullsquare + xscaled flow_grid_width + yscaled flow_grid_height + shifted offset ; + if known flow_xytext[x][y]: + draw flow_xytext[x][y] shifted offset ; + fi ; + if known flow_xylabel_t[x][y] : + label.urt(flow_xylabel_t[x][y],0.5[ulcorner p,urcorner p]) ; + fi ; + if known flow_xylabel_b[x][y] : + label.lrt(flow_xylabel_b[x][y],0.5[llcorner p,lrcorner p]) ; + fi ; + if known flow_xylabel_l[x][y] : + label.ulft(flow_xylabel_l[x][y],0.5[ulcorner p,llcorner p]) ; + fi ; + if known flow_xylabel_r[x][y] : + label.urt (flow_xylabel_r[x][y],0.5[urcorner p,lrcorner p]) ; + fi ; + if known flow_xyexit_t[x][y] : + label.top(flow_xyexit_t[x][y],0.5[ulcorner p,urcorner p] shifted (0, flow_grid_height/2)) ; + fi ; + if known flow_xyexit_b[x][y] : + label.bot(flow_xyexit_b[x][y],0.5[llcorner p,lrcorner p] shifted (0,-flow_grid_height/2)) ; + fi ; + if known flow_xyexit_l[x][y] : + label.lft(flow_xyexit_l[x][y],0.5[ulcorner p,llcorner p] shifted (-flow_grid_width/2,0)) ; + fi ; + if known flow_xyexit_r[x][y] : + label.rt (flow_xyexit_r[x][y],0.5[urcorner p,lrcorner p] shifted ( flow_grid_width/2,0)) ; + fi ; + endgroup ; + fi ; + endgroup ; +enddef ; + +def flow_chart_draw_text(expr x, y, p) = + flow_xytext[x][y] := p ; +enddef ; + +def flow_chart_draw_label_t(expr x, y, p) = flow_xylabel_t[x][y] := p ; enddef ; +def flow_chart_draw_label_b(expr x, y, p) = flow_xylabel_b[x][y] := p ; enddef ; +def flow_chart_draw_label_l(expr x, y, p) = flow_xylabel_l[x][y] := p ; enddef ; +def flow_chart_draw_label_r(expr x, y, p) = flow_xylabel_r[x][y] := p ; enddef ; + +def flow_chart_draw_exit_t (expr x, y, p) = flow_xyexit_t [x][y] := p ; enddef ; +def flow_chart_draw_exit_b (expr x, y, p) = flow_xyexit_b [x][y] := p ; enddef ; +def flow_chart_draw_exit_l (expr x, y, p) = flow_xyexit_l [x][y] := p ; enddef ; +def flow_chart_draw_exit_r (expr x, y, p) = flow_xyexit_r [x][y] := p ; enddef ; + +boolean flow_reverse_connection ; flow_reverse_connection := false ; + +vardef flow_up_on_grid (expr n) = + (xpart flow_xypoints[n],(ypart flow_xypoints[n]+1) div 1) +enddef ; + +vardef flow_down_on_grid (expr n) = + (xpart flow_xypoints[n],(ypart flow_xypoints[n]) div 1) +enddef ; + +vardef flow_left_on_grid (expr n) = + ((xpart flow_xypoints[n]) div 1, ypart flow_xypoints[n]) +enddef ; + +vardef flow_right_on_grid (expr n) = + ((xpart flow_xypoints[n]+1) div 1, ypart flow_xypoints[n]) +enddef ; + +vardef flow_x_on_grid (expr n, xfrom, xto, zfrom) = + if (xfrom = xto) and not (zfrom = 0) : + if (zfrom=1) : flow_right_on_grid(2) else : flow_left_on_grid(2) fi + elseif xpart flow_xypoints[1] < xpart flow_xypoints[6] : + flow_right_on_grid(n) + else : + flow_left_on_grid(n) + fi +enddef ; + +vardef flow_y_on_grid (expr n, yfrom, yto, zfrom) = + if (yfrom = yto) and not (zfrom = 0) : + if (zfrom = 1) : flow_up_on_grid(2) else : flow_down_on_grid(2) fi + elseif ypart flow_xypoints[1] < ypart flow_xypoints[6] : + flow_up_on_grid(n) + else : + flow_down_on_grid(n) + fi +enddef ; + +vardef flow_xy_on_grid (expr n, m) = + (xpart flow_xypoints[n], ypart flow_xypoints[m]) +enddef ; + +vardef flow_down_to_grid (expr a,b) = + (xpart flow_xypoints[a], ypart flow_xypoints[if ypart flow_xypoints[a]<ypart flow_xypoints[b] : a else : b fi]) +enddef ; + +vardef flow_up_to_grid (expr a,b) = + (xpart flow_xypoints[a], ypart flow_xypoints[if ypart flow_xypoints[a]>ypart flow_xypoints[b] : a else : b fi]) +enddef ; + +vardef flow_left_to_grid (expr a,b) = + (xpart flow_xypoints[if xpart flow_xypoints[a]<xpart flow_xypoints[b] : a else : b fi], ypart flow_xypoints[a]) +enddef ; + +vardef flow_right_to_grid (expr a,b) = + (xpart flow_xypoints[if xpart flow_xypoints[a]>xpart flow_xypoints[b] : a else : b fi], ypart flow_xypoints[a]) +enddef ; + +vardef flow_valid_connection (expr xfrom, yfrom, xto, yto) = + begingroup ; + save ok, vc, pp ; boolean ok ; pair vc ; path pp ; + save flow_xyfirst, flow_xylast ; pair flow_xyfirst, flow_xylast ; + % check for slanted lines + ok := true ; + for i=1 upto flow_xypoint-1 : + if not ((xpart flow_xypoints[i]=xpart flow_xypoints[i+1]) or (ypart flow_xypoints[i]=ypart flow_xypoints[i+1])) : + ok := false ; + fi ; + endfor ; + if not ok : + % message("slanted"); + false + elseif flow_forcevalid : + % message("force"); + true + elseif (xfrom=xto) and (yfrom=yto) : + % message("self"); + false + else : + % check for crossing shapes + flow_xyfirst := flow_xypoints[1] ; + flow_xylast := flow_xypoints[flow_xypoint] ; + flow_trim_points ; + pp := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ; + flow_xypoints[1] := flow_xyfirst ; + flow_xypoints[flow_xypoint] := flow_xylast ; + for i=1 upto flow_max_x : + for j=1 upto flow_max_y : % was bug: xfrom,yto + if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) : + if not flow_xyfree[i][j] : + vc := pp intersection_point flow_xypath[i][j] ; + if intersection_found : + ok := false + fi ; + fi ; + fi ; + endfor ; + endfor ; + % if not ok: message("crossing") ; fi ; + ok + fi + endgroup +enddef ; + +def flow_connect_top_bottom (expr xfrom, yyfrom, zfrom) (expr xto, yyto, zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ; + flow_xypoints[2] := flow_up_on_grid(1) ; + flow_xypoints[5] := flow_down_on_grid(6) ; + flow_xypoints[3] := flow_up_to_grid(2,5) ; + flow_xypoints[4] := flow_up_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(3,5) ; + fi ; + %%%% begin experiment + flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; + flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ; + if flow_dsp_y>0 : + flow_xypoints[2] := flow_xypoints[2] shifted (0,flow_dsp_y) ; + flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ; + elseif flow_dsp_y<0 : + flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; + flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ; + fi + %%%% end experiment + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_left_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ; + flow_xypoints[2] := flow_left_on_grid(1) ; + flow_xypoints[5] := flow_right_on_grid(6) ; + flow_xypoints[3] := flow_left_to_grid(2,5) ; + flow_xypoints[4] := flow_left_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(5,3) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_left_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,5) : + flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; + flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ; + flow_xypoints[2] := flow_left_on_grid(1) ; + flow_xypoints[4] := flow_up_on_grid(5) ; + flow_xypoints[3] := flow_left_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_xy_on_grid(2,4) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_left_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,5) : + flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; + flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ; + flow_xypoints[2] := flow_left_on_grid(1) ; + flow_xypoints[4] := flow_down_on_grid(5) ; + flow_xypoints[3] := flow_left_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_xy_on_grid(2,4) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_right_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,5) : + flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; + flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ; + flow_xypoints[2] := flow_right_on_grid(1) ; + flow_xypoints[4] := flow_up_on_grid(5) ; + flow_xypoints[3] := flow_right_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_xy_on_grid(2,4) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_right_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,5) : + flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; + flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ; + flow_xypoints[2] := flow_right_on_grid(1) ; + flow_xypoints[4] := flow_down_on_grid(5) ; + flow_xypoints[3] := flow_right_to_grid(2,5) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_xy_on_grid(2,4) ; + fi ; + %%%% begin experiment + flow_xypoints[2] := flow_xypoints[2] shifted (flow_dsp_x,0) ; + flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; + if flow_dsp_y>0 : + flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ; + flow_xypoints[4] := flow_xypoints[4] shifted (0,-flow_dsp_y) ; + elseif flow_dsp_y<0 : + flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ; + flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; + fi + %%%% end experiment + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_left_left (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_left(xto,yto,zto,true) ; + flow_xypoints[2] := flow_left_on_grid(1) ; + flow_xypoints[5] := flow_left_on_grid(6) ; + flow_xypoints[3] := flow_left_to_grid(2,5) ; + flow_xypoints[4] := flow_left_to_grid(5,2) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(5,3) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_right_right (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ; + flow_xypoints[2] := flow_right_on_grid(1) ; + flow_xypoints[5] := flow_right_on_grid(6) ; + flow_xypoints[3] := flow_right_to_grid(2,5) ; + flow_xypoints[4] := flow_right_to_grid(5,2) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(5,3) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_top_top (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_top(xto,yto,zto,true) ; + flow_xypoints[2] := flow_up_on_grid(1) ; + flow_xypoints[5] := flow_up_on_grid(6) ; + flow_xypoints[3] := flow_up_to_grid(2,5) ; + flow_xypoints[4] := flow_up_to_grid(5,2) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(3,5) ; + fi ; + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_bottom_bottom (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = + yfrom := flow_y_pos(yyfrom) ; + yto := flow_y_pos(yyto) ; + if flow_points_initialized(xfrom,yfrom,xto,yto,6) : + flow_xypoints[1] := flow_xy_bottom(xfrom,yfrom,zfrom,true) ; + flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ; + flow_xypoints[2] := flow_down_on_grid(1) ; + flow_xypoints[5] := flow_down_on_grid(6) ; + flow_xypoints[3] := flow_down_to_grid(2,5) ; + flow_xypoints[4] := flow_down_to_grid(5,2) ; + if not flow_valid_connection(xfrom,yfrom,xto,yto) : + flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; + flow_xypoints[4] := flow_xy_on_grid(3,5) ; + fi ; + %%%% begin experiment + flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; + flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ; + if flow_dsp_y<0 : + flow_xypoints[2] := flow_xypoints[2] shifted (0,-flow_dsp_y) ; + flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ; + elseif flow_dsp_y>0 : + flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; + flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ; + fi + %%%% end experiment + flow_draw_connection ; + fi ; +enddef ; + +def flow_connect_bottom_top (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_top_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_connect_right_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_left_right (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_connect_top_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_left_top(xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_connect_bottom_left (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_left_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_connect_top_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_right_top (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_connect_bottom_right (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = + flow_reverse_connection := true ; + flow_connect_right_bottom (xto,yto,zto) (xfrom,yfrom,zfrom) ; +enddef ; + +def flow_draw_test_shape(expr x, y) = + flow_draw_shape(x,y,fullcircle, .7, .7) ; +enddef ; + +def flow_draw_test_shapes = + for i=1 upto flow_max_x : + for j=1 upto flow_max_y : + flow_draw_test_shape(i,j) ; + endfor ; + endfor ; +enddef; + +def flow_draw_test_area = + pickup pencircle scaled .5flow_shape_line_width ; + draw (unitsquare xscaled flow_max_x yscaled flow_max_y shifted (1,1)) flow_scaled_to_grid withcolor blue ; +enddef ; + +def flow_show_connection(expr n, m) = + + flow_begin_chart(100+n,6,6) ; + + flow_draw_test_area ; + + flow_smooth := true ; + flow_arrowtip := true ; + flow_dashline := true ; + + flow_draw_test_shape(2,2) ; flow_draw_test_shape(4,5) ; + flow_draw_test_shape(3,3) ; flow_draw_test_shape(5,1) ; + flow_draw_test_shape(2,5) ; flow_draw_test_shape(1,3) ; + flow_draw_test_shape(6,2) ; flow_draw_test_shape(4,6) ; + + if (m=1) : + flow_connect_top_bottom (2,2,0) (4,5,0) ; + flow_connect_top_bottom (3,3,0) (5,1,0) ; + flow_connect_top_bottom (2,5,0) (1,3,0) ; + flow_connect_top_bottom (6,2,0) (4,6,0) ; + elseif (m=2) : + flow_connect_top_top (2,2,0) (4,5,0) ; + flow_connect_top_top (3,3,0) (5,1,0) ; + flow_connect_top_top (2,5,0) (1,3,0) ; + flow_connect_top_top (6,2,0) (4,6,0) ; + elseif (m=3) : + flow_connect_bottom_bottom (2,2,0) (4,5,0) ; + flow_connect_bottom_bottom (3,3,0) (5,1,0) ; + flow_connect_bottom_bottom (2,5,0) (1,3,0) ; + flow_connect_bottom_bottom (6,2,0) (4,6,0) ; + elseif (m=4) : + flow_connect_left_right (2,2,0) (4,5,0) ; + flow_connect_left_right (3,3,0) (5,1,0) ; + flow_connect_left_right (2,5,0) (1,3,0) ; + flow_connect_left_right (6,2,0) (4,6,0) ; + elseif (m=5) : + flow_connect_left_left (2,2,0) (4,5,0) ; + flow_connect_left_left (3,3,0) (5,1,0) ; + flow_connect_left_left (2,5,0) (1,3,0) ; + flow_connect_left_left (6,2,0) (4,6,0) ; + elseif (m=6) : + flow_connect_right_right (2,2,0) (4,5,0) ; + flow_connect_right_right (3,3,0) (5,1,0) ; + flow_connect_right_right (2,5,0) (1,3,0) ; + flow_connect_right_right (6,2,0) (4,6,0) ; + elseif (m=7) : + flow_connect_left_top (2,2,0) (4,5,0) ; + flow_connect_left_top (3,3,0) (5,1,0) ; + flow_connect_left_top (2,5,0) (1,3,0) ; + flow_connect_left_top (6,2,0) (4,6,0) ; + elseif (m=8) : + flow_connect_left_bottom (2,2,0) (4,5,0) ; + flow_connect_left_bottom (3,3,0) (5,1,0) ; + flow_connect_left_bottom (2,5,0) (1,3,0) ; + flow_connect_left_bottom (6,2,0) (4,6,0) ; + elseif (m=9) : + flow_connect_right_top (2,2,0) (4,5,0) ; + flow_connect_right_top (3,3,0) (5,1,0) ; + flow_connect_right_top (2,5,0) (1,3,0) ; + flow_connect_right_top (6,2,0) (4,6,0) ; + else : + flow_connect_right_bottom (2,2,0) (4,5,0) ; + flow_connect_right_bottom (3,3,0) (5,1,0) ; + flow_connect_right_bottom (2,5,0) (1,3,0) ; + flow_connect_right_bottom (6,2,0) (4,6,0) ; + fi ; + + flow_end_chart ; + +enddef ; + +def flow_show_connections = + for f=1 upto 10 : + flow_show_connection(f,f) ; + endfor ; +enddef ; + +%D charts + +def flow_clip_chart(expr minx, miny, maxx, maxy) = + flow_cmin_x := minx ; + flow_cmax_x := maxx ; + flow_cmin_y := miny ; + flow_cmax_y := maxy ; +enddef ; + +def flow_begin_chart(expr n, maxx, maxy) = + flow_new_chart ; + flow_chart_figure := n ; + flow_chart_scale := 1 ; + if flow_chart_figure>0: + beginfig(flow_chart_figure) ; + fi ; + flow_initialize_grid (maxx, maxy) ; + bboxmargin := 0 ; + flow_cmin_x := 1 ; + flow_cmax_x := maxx ; + flow_cmin_y := 1 ; + flow_cmax_y := maxy ; +enddef ; + +def flow_end_chart = + begingroup ; + save p ; path p ; + flow_flush_shapes ; + flow_flush_connections ; + flow_flush_pictures ; + flow_cmin_x := flow_cmin_x ; + flow_cmax_x := flow_cmin_x+flow_cmax_x ; + flow_cmin_y := flow_cmin_y-1 ; + flow_cmax_y := flow_cmin_y+flow_cmax_y ; + if flow_reverse_y : + flow_cmin_y := flow_y_pos(flow_cmin_y) ; + flow_cmax_y := flow_y_pos(flow_cmax_y) ; + fi ; + p := (((flow_cmin_x,flow_cmin_y)--(flow_cmax_x,flow_cmin_y)-- + (flow_cmax_x,flow_cmax_y)--(flow_cmin_x,flow_cmax_y)--cycle)) + flow_scaled_to_grid ; + %draw p withcolor red ; + p := p enlarged flow_chart_offset ; + clip currentpicture to p ; + setbounds currentpicture to p ; + endgroup ; + currentpicture := currentpicture scaled flow_chart_scale ; + if flow_chart_figure>0: + endfig ; + fi ; +enddef ; + +def flow_new_shape(expr x, y, n) = + if known n : + if (x>0) and (x<=flow_max_x) and (y>0) and (y<=flow_max_y) : + flow_draw_shape(x,y,some_shape_path(n), flow_shape_width/flow_grid_width, flow_shape_height/flow_grid_height) ; + else : + message ("shape outside grid ignored") ; + fi ; + else : + message ("shape not known" ) ; + fi ; +enddef ; + +def flow_begin_sub_chart = + begingroup ; + save flow_shape_line_width, flow_connection_line_width ; + save flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ; + color flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ; + save flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ; + boolean flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ; +enddef ; + +def flow_end_sub_chart = + endgroup ; +enddef ; + diff --git a/metapost/context/base/mp-chem.mpiv b/metapost/context/base/mp-chem.mpiv index c70dafd85..0432a7e88 100644 --- a/metapost/context/base/mp-chem.mpiv +++ b/metapost/context/base/mp-chem.mpiv @@ -15,7 +15,9 @@ % either consistent setting or not -if known chem_reset : endinput ; fi ; +if known context_chem : endinput ; fi ; + +boolean context_chem ; context_chem := true ; numeric chem_width, chem_radical_min, chem_radical_max, chem_text_max, chem_circle_radius, @@ -140,16 +142,15 @@ def chem_stop_structure = setbounds currentpicture to chem_setting_bbox ; enddef ; -def chem_start_component = -enddef ; -def chem_stop_component = -enddef ; +def chem_start_component = enddef ; +def chem_stop_component = enddef ; def chem_pb = % draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor blue ; % draw origin withpen pencircle scaled 2mm withcolor blue ; chem_doing_pb := true ; enddef ; + def chem_pe = % draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ; % draw origin withpen pencircle scaled 1mm withcolor red ; @@ -176,38 +177,49 @@ enddef ; vardef chem_b (expr n, f, t, r, c) = chem_draw (n, chem_b_path[n], f, t, r, c) ; enddef ; + vardef chem_sb (expr n, f, t, r, c) = chem_draw (n, chem_sb_path[n], f, t, r, c) ; enddef ; + vardef chem_s (expr n, f, t, r, c) = chem_draw (n, chem_s_path[n], f, t, r, c) ; enddef ; + vardef chem_ss (expr n, f, t, r, c) = chem_draw (n, chem_ss_path[n], f, t, r, c) ; enddef ; + vardef chem_mid (expr n, r, c) = chem_draw_fixed (n, chem_midt_path[n], r, c) ; chem_draw_fixed (n, chem_midb_path[n], r, c) ; enddef ; + vardef chem_mids (expr n, r, c) = chem_draw_fixed (n, chem_midst_path[n], r, c) ; chem_draw_fixed (n, chem_midsb_path[n], r, c) ; enddef ; + vardef chem_mss (expr n, f, t, r, c) = chem_draw (n, chem_mss_path[n], f, t, r, c) ; enddef ; + vardef chem_pss (expr n, f, t, r, c) = chem_draw (n, chem_pss_path[n], f, t, r, c) ; enddef ; + vardef chem_msb (expr n, f, t, r, c) = chem_draw (n, chem_msb_path[n], f, t, r, c) ; enddef ; + vardef chem_psb (expr n, f, t, r, c) = chem_draw (n, chem_psb_path[n], f, t, r, c) ; enddef ; + vardef chem_eb (expr n, f, t, r, c) = chem_draw (n, chem_eb_path[n], f, t, r, c) ; enddef ; + vardef chem_db (expr n, f, t, r, c) = if n = 1 : chem_draw (n, chem_msb_path [n], f, t, r, c) ; @@ -217,20 +229,25 @@ vardef chem_db (expr n, f, t, r, c) = chem_draw (n, chem_dbr_path [n], f, t, r, c) ; fi ; enddef ; + vardef chem_er (expr n, f, t, r, c) = chem_draw (n, chem_rl_path[n], f, t, r, c) ; chem_draw (n, chem_rr_path[n], f, t, r, c) ; enddef ; + vardef chem_dr (expr n, f, t, r, c) = chem_draw (n, chem_srl_path[n], f, t, r, c) ; chem_draw (n, chem_srr_path[n], f, t, r, c) ; enddef ; + vardef chem_ad (expr n, f, t, r, c) = chem_draw_arrow(n, chem_ad_path[n], f, t, r, c) ; enddef ; + vardef chem_au (expr n, f, t, r, c) = chem_draw_arrow(n, chem_au_path[n], f, t, r, c) enddef ; + vardef chem_r (expr n, f, t, r, c) = if n < 0 : chem_draw_vertical (n, chem_r_path[n], f, t, r, c) ; @@ -238,27 +255,35 @@ vardef chem_r (expr n, f, t, r, c) = chem_draw (n, chem_r_path[n], f, t, r, c) ; fi ; enddef ; + vardef chem_rd (expr n, f, t, r, c) = chem_dashed_normal (n, chem_r_path[n], f, t, r, c) enddef ; + vardef chem_mrd (expr n, f, t, r, c) = chem_dashed_normal (n, chem_mr_path[n], f, t, r, c) enddef ; + vardef chem_prd (expr n, f, t, r, c) = chem_dashed_normal (n, chem_pr_path[n], f, t, r, c) enddef ; + vardef chem_br (expr n, f, t, r, c) = chem_fill (n, chem_br_path[n], f, t, r, c ) enddef ; + vardef chem_rb (expr n, f, t, r, c) = chem_fill (n, chem_rb_path[n], f, t, r, c) enddef ; + vardef chem_mrb (expr n, f, t, r, c) = chem_fill (n, chem_mrb_path[n], f, t, r, c) enddef ; + vardef chem_prb (expr n, f, t, r, c) = chem_fill (n, chem_prb_path[n], f, t, r, c) enddef ; + vardef chem_mr (expr n, f, t, r, c) = if n < 0 : chem_draw_vertical(n, chem_mr_path[n], f, t, r, c) @@ -266,6 +291,7 @@ vardef chem_mr (expr n, f, t, r, c) = chem_draw (n, chem_mr_path[n], f, t, r, c) fi enddef ; + vardef chem_pr (expr n, f, t, r, c) = if n < 0 : chem_draw_vertical(n, chem_pr_path[n], f, t, r, c) @@ -273,75 +299,95 @@ vardef chem_pr (expr n, f, t, r, c) = chem_draw (n, chem_pr_path[n], f, t, r, c) fi enddef ; + vardef chem_sr (expr n, f, t, r, c) = chem_draw (n, chem_sr_path[n], f, t, r, c) enddef ; + vardef chem_msr (expr n, f, t, r, c) = chem_draw (n, chem_msr_path[n], f, t, r, c) enddef ; + vardef chem_psr (expr n, f, t, r, c) = chem_draw (n, chem_psr_path[n], f, t, r, c) enddef ; + vardef chem_c (expr n, f, t, r, c) = chem_draw (n, chem_c_path[n], f, t, r, c) enddef ; + vardef chem_cc (expr n, f, t, r, c) = chem_draw (n, chem_cc_path[n], f, f, r, c) enddef ; + vardef chem_cd (expr n, f, t, r, c) = chem_dashed_connected (n, chem_c_path[n], f, t, r, c) enddef ; + vardef chem_ccd (expr n, f, t, r, c) = chem_dashed_normal (n, chem_cc_path[n], f, f, r, c) enddef ; + vardef chem_rn (expr n, i, t) = chem_rt (n,i,t) ; enddef ; + vardef chem_rtn (expr n, i, t) = chem_rtt(n,i,t) ; enddef ; + vardef chem_rbn (expr n, i, t) = chem_rbt(n,i,t) ; enddef ; + vardef chem_tb (expr n, f, t, r, c) = % one chem_draw (n, chem_msb_path[n], f, t, r, c) ; chem_draw (n, chem_sb_path [n], f, t, r, c) ; chem_draw (n, chem_psb_path[n], f, t, r, c) ; enddef ; + vardef chem_ep (expr n, f, t, r, c) = % one chem_draw (n, chem_e_path[n], f, t, r, c) ; enddef ; + vardef chem_es (expr n, f, t, r, c) = % one chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ; enddef ; + vardef chem_ed (expr n, f, t, r, c) = % one chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ; chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ; enddef ; + vardef chem_et (expr n, f, t, r, c) = % one chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ; chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ; chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ; enddef ; + vardef chem_sd (expr n, f, t, r, c) = % one chem_draw (n, chem_ddt_path[n], f, t, r, c) ; chem_draw (n, chem_ddb_path[n], f, t, r, c) ; enddef ; + vardef chem_rdd (expr n, f, t, r, c) = % one chem_draw (n, chem_ldt_path[n], f, t, r, c) ; chem_draw (n, chem_ldb_path[n], f, t, r, c) ; chem_draw (n, chem_psb_path[n], f, t, r, c) ; enddef ; + vardef chem_ldd (expr n, f, t, r, c) = % one chem_draw (n, chem_msb_path[n], f, t, r, c) ; chem_draw (n, chem_rdt_path[n], f, t, r, c) ; chem_draw (n, chem_rdb_path[n], f, t, r, c) ; enddef ; + vardef chem_hb (expr n, f, t, r, c) = % one chem_draw_dot (n, point 0 of chem_sb_path[n], f, t, r, c) ; chem_draw_dot (n, center chem_sb_path[n], f, t, r, c) ; chem_draw_dot (n, point 1 of chem_sb_path[n], f, t, r, c) ; enddef ; + vardef chem_bb (expr n, f, t, r, c) = % one if n < 0 : chem_fill (n, chem_bb_path[n], 1, 1, r, c) ; @@ -350,14 +396,17 @@ vardef chem_bb (expr n, f, t, r, c) = % one chem_fill (n, chem_bb_path[n], f, t, r, c) ; fi ; enddef ; + vardef chem_oe (expr n, f, t, r, c) = % one chem_draw (n, chem_oe_path[n], f, t, r, c) ; enddef ; + vardef chem_bd (expr n, f, t, r, c) = % one for i=0 upto 5 : chem_draw (n, subpath (2i,2i+1) of chem_bd_path[n], f, t, r, c) ; endfor ; enddef ; + vardef chem_bw (expr n, f, t, r, c) = % one chem_draw (n, chem_bw_path[n], f, t, r, c) ; enddef ; @@ -365,9 +414,11 @@ enddef ; vardef chem_z_zero@#(text t) = chem_text@#(t, chem_do(origin)) ; enddef ; + vardef chem_cz_zero@#(text t) = chem_text@#(t, chem_do(origin)) ; enddef ; + vardef chem_z@#(expr n, p) (text t) = if p = 0 : chem_text@#(t, chem_do(origin)) ; @@ -375,6 +426,7 @@ vardef chem_z@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_cz@#(expr n, p) (text t) = if n = 1 : chem_c_text(t, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ; @@ -382,9 +434,11 @@ vardef chem_cz@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_midz@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_mid_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_rz@#(expr n, p) (text t) = if n < 0 : % quite special @@ -393,9 +447,11 @@ vardef chem_rz@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_crz@#(expr n, p) (text tx) = chem_text(tx, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_mrz@#(expr n, p) (text t) = if n < 0 : % quite special @@ -404,6 +460,7 @@ vardef chem_mrz@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_mr_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_prz@#(expr n, p) (text t) = if n < 0 : % quite special @@ -412,15 +469,19 @@ vardef chem_prz@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_pr_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_rt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_rtt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_rbt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_zt@#(expr n, p) (text t) = if n = 1 : chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ; @@ -428,6 +489,7 @@ vardef chem_zt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_zn@#(expr n, p) (text t) = if n = 1 : chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ; @@ -435,15 +497,19 @@ vardef chem_zn@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ; fi ; enddef ; + vardef chem_zbt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_zbn@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_ztt@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ; enddef ; + vardef chem_ztn@#(expr n, p) (text t) = chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ; enddef ; @@ -481,15 +547,19 @@ enddef ; vardef chem_ang (expr n, d) = ((-1 * (d-1) * chem_angle[n]) + (-chem_rotation+1) * 90 + chem_start[n]) % no ; enddef ; + vardef chem_rot (expr n, d) = chem_rotation := d ; enddef ; + vardef chem_adj (expr n, d) = chem_adjacent := d ; enddef ; + vardef chem_sub (expr n, d) = chem_substituent := d ; enddef ; + vardef chem_dir (expr n, d) = if n = 1 : chem_direction_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+1))) ; @@ -497,6 +567,7 @@ vardef chem_dir (expr n, d) = chem_shift := chem_shift + chem_direction_p ; fi ; enddef ; + vardef chem_mov (expr n, d) = if d = 0 : currentpicture := currentpicture shifted - chem_shift ; @@ -507,6 +578,7 @@ vardef chem_mov (expr n, d) = chem_shift := chem_shift + chem_move_p ; fi ; enddef ; + vardef chem_off (expr n, d) = if (d = 1) or (d = 2) or (d = 8) : % positive currentpicture := currentpicture shifted (-chem_setting_offset,0) ; @@ -554,6 +626,7 @@ vardef chem_draw (expr n, path_fragment, from_point, to_point, linewidth, lineco draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ; endfor ; enddef ; + vardef chem_fill (expr n, path_fragment, from_point, to_point, linewidth, linecolor) = for i:=from_point upto to_point: fill (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled 0 withcolor linecolor ; @@ -565,24 +638,29 @@ vardef chem_dashed_normal (expr n, path_fragment, from_point, to_point, linewidt draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor dashed evenly ; endfor ; enddef ; + vardef chem_dashed_connected (expr n, path_fragment, from_point, to_point, linewidth, linecolor) = draw for i:=from_point upto to_point: (path_fragment rotated chem_ang(n,i)) if i < to_point : -- fi endfor withpen pencircle scaled linewidth withcolor linecolor dashed evenly ; enddef ; + vardef chem_draw_dot (expr n, path_fragment, from_point, to_point, linewidth, linecolor) = for i:=from_point upto to_point: draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled (chem_dot_factor*linewidth) withcolor linecolor ; endfor ; enddef ; + vardef chem_draw_fixed (expr n, path_fragment, linewidth, linecolor) = draw (path_fragment rotated chem_ang(n,1)) withpen pencircle scaled linewidth withcolor linecolor ; enddef ; + vardef chem_draw_arrow (expr n, path_fragment, from_point, to_point, linewidth, linecolor) = for i:=from_point upto to_point: drawarrow (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ; endfor ; enddef ; + vardef chem_draw_vertical (expr n, path_fragment, from_point, to_point, linewidth, linecolor) = % quite special for i:=from_point upto to_point: @@ -603,6 +681,7 @@ vardef chem_save = % chem_rotation := 1 ; currentpicture := nullpicture ; enddef ; + vardef chem_restore = if chem_stack_n > 0 : currentpicture := currentpicture shifted - chem_shift ; diff --git a/metapost/context/base/mp-core.mpii b/metapost/context/base/mp-core.mpii index 2ccdad22c..4d28cfd17 100644 --- a/metapost/context/base/mp-core.mpii +++ b/metapost/context/base/mp-core.mpii @@ -1,6 +1,4 @@ - -if unknown context_tool : input mp-tool ; fi ; -if known context_core : endinput ; fi ; +if known context_core : endinput ; fi ; boolean context_core ; context_core := true ; diff --git a/metapost/context/base/mp-core.mpiv b/metapost/context/base/mp-core.mpiv index 8fc32c420..1297802e9 100644 --- a/metapost/context/base/mp-core.mpiv +++ b/metapost/context/base/mp-core.mpiv @@ -1,5 +1,17 @@ -if unknown context_tool : input mp-tool ; fi ; -if known context_core : endinput ; fi ; +%D \module +%D [ file=mp-core.mp, +%D version=1999.08.01, % anchoring +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=background macros, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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_core : endinput ; fi ; boolean context_core ; context_core := true ; @@ -45,19 +57,14 @@ def freeze_box (expr pos) = enddef ; def initialize_box (expr n,x,y,w,h,d) = - numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ; - enddef ; def initialize_area (expr fn,fx,fy,fw,fh,fd, tn,tx,ty,tw,th,td) = - numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; - do_initialize_area (fpos, tpos) ; - enddef ; def do_initialize_area (expr fpos, tpos) = @@ -125,182 +132,187 @@ enddef ; def do_initialize_par (expr fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) = - pair lref, rref, pref, lhref, rhref ; - - % clip the page area to the left and right skips - - llxy[mpos] := llxy[mpos] shifted (+rl,0) ; - lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ; - urxy[mpos] := urxy[mpos] shifted (-rr,0) ; - ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ; - - % fixate the leftskip, rightskip and hanging indentation - - lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ; - rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ; - - pref := lxy[ppos] ; - - if nxy[tpos] > nxy[fpos] : - if nxy[fpos] = nxy[mpos] : - % first of multiple pages - llxy[tpos] := llxy[mpos] ; - lrxy[tpos] := lrxy[mpos] ; - urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; - ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; - boxgriddirection := down ; - elseif nxy[tpos] = nxy[mpos] : - % last of multiple pages - llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; - lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; - urxy[fpos] := urxy[mpos] ; - ulxy[fpos] := ulxy[mpos] ; - boxgriddirection := up ; + pair lref, rref, pref, lhref, rhref ; + + % clip the page area to the left and right skips + + llxy[mpos] := llxy[mpos] shifted (+rl,0) ; + lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ; + urxy[mpos] := urxy[mpos] shifted (-rr,0) ; + ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ; + + % fixate the leftskip, rightskip and hanging indentation + + lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ; + rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ; + + pref := lxy[ppos] ; + + if nxy[tpos] > nxy[fpos] : + if nxy[fpos] = nxy[mpos] : + % first of multiple pages + llxy[tpos] := llxy[mpos] ; + lrxy[tpos] := lrxy[mpos] ; + urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; + ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; + boxgriddirection := down ; + elseif nxy[tpos] = nxy[mpos] : + % last of multiple pages + llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; + lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; + urxy[fpos] := urxy[mpos] ; + ulxy[fpos] := ulxy[mpos] ; + boxgriddirection := up ; + else : + % middle of multiple pages + llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; + lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; + urxy[fpos] := urxy[mpos] ; + ulxy[fpos] := ulxy[mpos] ; + llxy[tpos] := llxy[mpos] ; + lrxy[tpos] := lrxy[mpos] ; + urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; + ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; + boxgriddirection := up ; + fi ; else : - % middle of multiple pages - llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ; - lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ; - urxy[fpos] := urxy[mpos] ; - ulxy[fpos] := ulxy[mpos] ; - llxy[tpos] := llxy[mpos] ; - lrxy[tpos] := lrxy[mpos] ; - urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ; - ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ; - boxgriddirection := up ; + % just one page + boxgriddirection := up ; fi ; - else : - % just one page - boxgriddirection := up ; - fi ; - path txy, bxy, pxy, mxy ; + path txy, bxy, pxy, mxy ; - txy := originpath ; % top - bxy := originpath ; % bottom - pxy := originpath ; % composed + txy := originpath ; % top + bxy := originpath ; % bottom + pxy := originpath ; % composed - boolean lefthang, righthang, somehang ; + boolean lefthang, righthang, somehang ; - % we only hang on the first of a multiple page background + % we only hang on the first of a multiple page background - if nxy[mpos] > nxy[fpos] : - lefthang := righthang := somehang := false ; - else : - lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ; - fi ; + if nxy[mpos] > nxy[fpos] : + lefthang := righthang := somehang := false ; + else : + lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ; + fi ; - if lefthang : - mxy := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ; - elseif righthang : - mxy := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ; - else : - mxy := originpath ; - fi ; + if lefthang : + mxy := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ; + elseif righthang : + mxy := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ; + else : + mxy := originpath ; + fi ; - if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) : + if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) : - % We have a one-liner. Watch how er use the bottom pos for - % determining the height. + % We have a one-liner. Watch how er use the bottom pos for + % determining the height. - llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ; - ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ; + llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ; + ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ; - else : + else : - % We have a multi-liner. For convenience we now correct the - % begin and end points for indentation. + % We have a multi-liner. For convenience we now correct the + % begin and end points for indentation. - if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) : - llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ; - ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ; - else : - llxy[tpos] := (xpart lref, ypart llxy[tpos]) ; - ulxy[tpos] := (xpart lref, ypart ulxy[tpos]) ; - fi ; + if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) : + llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ; + ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ; + else : + llxy[tpos] := (xpart lref, ypart llxy[tpos]) ; + ulxy[tpos] := (xpart lref, ypart ulxy[tpos]) ; + fi ; - if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) : - lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ; - urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ; - else : - lrxy[fpos] := (xpart rref, ypart lrxy[fpos]) ; - urxy[fpos] := (xpart rref, ypart urxy[fpos]) ; - fi ; + if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) : + lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ; + urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ; + else : + lrxy[fpos] := (xpart rref, ypart lrxy[fpos]) ; + urxy[fpos] := (xpart rref, ypart urxy[fpos]) ; + fi ; - fi ; + fi ; - somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and - (ypart llxy[tpos]<ypart llcorner mxy) ; + somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and + (ypart llxy[tpos]<ypart llcorner mxy) ; - if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) : + if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) : - % A (short) one-liner goes into the top box. + % A (short) one-liner goes into the top box. - txy := llxy[fpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[fpos] -- cycle ; + txy := llxy[fpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[fpos] -- cycle ; - elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) and - (round(xpart lrxy[tpos]) < round(xpart llxy[fpos])) : + elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) and + (round(xpart lrxy[tpos]) < round(xpart llxy[fpos])) : - % We have a sentence that spans two lines but with only end - % of line and begin of line segments. We need to take care of - % indentation. + % We have a sentence that spans two lines but with only end + % of line and begin of line segments. We need to take care of + % indentation. - txy := llxy[fpos] -- lrxy[fpos] -- urxy[fpos] -- ulxy[fpos] -- cycle ; - bxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[tpos] -- cycle ; + txy := llxy[fpos] -- lrxy[fpos] -- urxy[fpos] -- ulxy[fpos] -- cycle ; + bxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[tpos] -- cycle ; - elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) : + elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) : - % We have a sentence that spans two lines but with overlap. + % We have a sentence that spans two lines but with overlap. - pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- lrxy[fpos] -- - urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- ulxy[tpos] -- cycle ; + pxy := + llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- lrxy[fpos] -- + urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- ulxy[tpos] -- cycle ; - elseif lefthang and somehang : + elseif lefthang and somehang : - % We have a sentence that spans more than two lines with - % left hanging indentation. + % We have a sentence that spans more than two lines with + % left hanging indentation. - pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- - (xpart urxy[fpos],ypart urxy[tpos]) -- - urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- - if round(ypart urxy[tpos]) < round(ypart llcorner mxy) : - (xpart lrcorner mxy,ypart llxy[fpos]) -- - lrcorner mxy -- - (xpart llxy[tpos],ypart llcorner mxy) -- - else : - (xpart llxy[tpos],ypart llxy[fpos]) -- - fi - cycle ; + pxy := + llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- + (xpart urxy[fpos],ypart urxy[tpos]) -- + urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- + if round(ypart urxy[tpos]) < round(ypart llcorner mxy) : + (xpart lrcorner mxy,ypart llxy[fpos]) -- + lrcorner mxy -- + (xpart llxy[tpos],ypart llcorner mxy) -- + else : + (xpart llxy[tpos],ypart llxy[fpos]) -- + fi + cycle ; - elseif righthang and somehang : + elseif righthang and somehang : - % We have a sentence that spans more than two lines with - % right hanging indentation. + % We have a sentence that spans more than two lines with + % right hanging indentation. - pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- - if round(ypart urxy[tpos]) < round(ypart llcorner mxy) : - (xpart lrcorner mxy,ypart urxy[tpos]) -- - lrcorner mxy -- llcorner mxy -- - else : - (xpart urxy[fpos],ypart urxy[tpos]) -- - fi - urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- - (xpart llxy[tpos],ypart llxy[fpos]) -- - cycle ; + pxy := + llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- + if round(ypart urxy[tpos]) < round(ypart llcorner mxy) : + (xpart lrcorner mxy,ypart urxy[tpos]) -- + lrcorner mxy -- llcorner mxy -- + else : + (xpart urxy[fpos],ypart urxy[tpos]) -- + fi + urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- + (xpart llxy[tpos],ypart llxy[fpos]) -- + cycle ; - else : + else : - % We have a sentence that spans more than two lines with - % no hanging indentation. + % We have a sentence that spans more than two lines with + % no hanging indentation. - pxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- - (xpart urxy[fpos],ypart urxy[tpos]) -- - urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- - (xpart llxy[tpos],ypart llxy[fpos]) -- cycle ; + pxy := + llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- + (xpart urxy[fpos],ypart urxy[tpos]) -- + urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- + (xpart llxy[tpos],ypart llxy[fpos]) -- + cycle ; - fi ; + fi ; - pxy := simplified pxy ; - pxy := unspiked pxy ; + pxy := simplified pxy ; + pxy := unspiked pxy ; enddef ; @@ -310,10 +322,10 @@ StrutHeight := 0 ; % will move pair last_multi_par_shift ; last_multi_par_shift := origin ; def relocate_multipars (expr xy) = - last_multi_par_shift := xy ; - for i=1 upto nofmultipars : - multipars[i] := multipars[i] shifted last_multi_par_shift ; - endfor ; + last_multi_par_shift := xy ; + for i=1 upto nofmultipars : + multipars[i] := multipars[i] shifted last_multi_par_shift ; + endfor ; enddef ; boolean compensate_multi_par_topskip ; @@ -327,8 +339,7 @@ auto_multi_par_hsize := false ; % true ; enable_multi_par_fallback := true ; vardef multi_par_at_top (expr i) = - (round (ypart ulcorner multipars[i]) = round (ypart ulcorner - (TextAreas[multirefs[i]] shifted last_multi_par_shift))) + (round (ypart ulcorner multipars[i]) = round (ypart ulcorner (TextAreas[multirefs[i]] shifted last_multi_par_shift))) enddef ; numeric nofmultipars ; nofmultipars := 0 ; @@ -345,16 +356,16 @@ boolean check_multi_par_chain ; check_multi_par_chain := true ; % extra page boolean multi_column_first_page_hack; multi_column_first_page_hack := true ; % seems to work ok def simplify_multi_pars = % boundingbox ipv shape als optie - for i := 1 upto nofmultipars : - multipars[i] := boundingbox multipars[i] ; - endfor ; + for i := 1 upto nofmultipars : + multipars[i] := boundingbox multipars[i] ; + endfor ; enddef ; def save_multipar (expr i, l, p) = - nofmultipars := nofmultipars + 1 ; - multirefs[nofmultipars] := i ; - multilocs[nofmultipars] := l ; - multipars[nofmultipars] := unspiked (simplified p) ; + nofmultipars := nofmultipars + 1 ; + multirefs[nofmultipars] := i ; + multilocs[nofmultipars] := l ; + multipars[nofmultipars] := unspiked (simplified p) ; enddef ; def prepare_multi_pars (expr fn,fx,fy,fw,fh,fd, @@ -363,597 +374,576 @@ def prepare_multi_pars (expr fn,fx,fy,fw,fh,fd, pn,px,py,pw,ph,pd, rw,rl,rr,rh,ra,ri) = - if span_multi_column_pars : - begingroup ; - save TextAreas ; path TextAreas[] ; - save NOfTextAreas ; numeric NOfTextAreas ; - for i=1 upto NOfTextColumns : - TextAreas[i] := TextColumns[i] ; - endfor ; - NOfTextAreas := NOfTextColumns ; - fi ; - - last_multi_par_shift := origin ; - - numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; - numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; - numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ; - numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ; - - if local_multi_par_area : - RealPageNumber := fn ; - NOfTextAreas := 1 ; - NOfSavedTextAreas := 0 ; - TextAreas[1] := TextAreas[0] ; - TextColumns[1] := TextColumns[0] ; - nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ; - elseif ignore_multi_par_page : - RealPageNumber := fn ; - nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ; - fi ; - - numeric par_strut_height, par_strut_depth, par_line_height ; - - set_par_line_height (ph, pd) ; - - numeric par_hang_indent, par_hang_after, par_indent, par_left_skip, par_right_skip ; - - par_hang_indent := rh ; - par_hang_after := ra ; - par_indent := ri ; - par_left_skip := rl ; - par_right_skip := rr ; - - pair par_start_pos ; - pair par_stop_pos ; - - par_start_pos := llxy[fpos] - if par_indent <0: shifted (-par_indent, 0) fi - if par_left_skip<0: shifted (-par_left_skip,0) fi ; - par_stop_pos := lrxy[tpos] - if par_right_skip<0: shifted (par_right_skip,0) fi ; % nasty as the endpos can be shifted by rightskip - - if wxy[wpos]>0 : - left_skip := rl + xpart llxy[wpos] - xpart llxy[ppos] ; - right_skip := rw - left_skip - ww ; - else : - left_skip := rl ; - right_skip := rr ; - fi ; - - path multipar, multipars[] ; - numeric multiref, multirefs[] ; - numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end - - numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ; - - % locals .. why can't i move these outside? - -vardef _pmp_set_multipar_ (expr i) = - ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip - if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) ) -enddef ; + if span_multi_column_pars : + begingroup ; + save TextAreas ; path TextAreas[] ; + save NOfTextAreas ; numeric NOfTextAreas ; + for i=1 upto NOfTextColumns : + TextAreas[i] := TextColumns[i] ; + endfor ; + NOfTextAreas := NOfTextColumns ; + fi ; -vardef _pmp_snapped_multi_pos_ (expr p) = - if snap_multi_par_tops : - if abs(ypart p - ypart ulcorner multipar) < par_line_height : - (xpart p,ypart ulcorner multipar) - else : - p - fi - else : - p - fi -enddef ; + last_multi_par_shift := origin ; -vardef _pmp_estimated_par_lines_ (expr h) = - round(h/par_line_height) -enddef ; + numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ; + numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ; + numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ; + numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ; -vardef _pmp_top_multi_par_(expr p) = - (round(_pmp_estimated_par_lines_(bbheight(p)*par_line_height))=round(bbheight(p))) -enddef ; + if local_multi_par_area : + RealPageNumber := fn ; + NOfTextAreas := 1 ; + NOfSavedTextAreas := 0 ; + TextAreas[1] := TextAreas[0] ; + TextColumns[1] := TextColumns[0] ; + nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ; + elseif ignore_multi_par_page : + RealPageNumber := fn ; + nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ; + fi ; -vardef _pmp_multi_par_tsc_(expr p) = - if _pmp_top_multi_par_(p) : TopSkipCorrection else : 0 fi -enddef ; + numeric par_strut_height, par_strut_depth, par_line_height ; -vardef _pmp_estimated_multi_par_height_ (expr n, t) = - if round(par_line_height)=0 : - 0 - else : - save ok, h ; boolean ok ; - numeric h ; h := 0 ; - ok := false ; - if (nxy[fpos]=RealPageNumber-1) : - for i := 1 upto NOfSavedTextAreas : - if (InsideSavedTextArea(i,par_start_pos)) : - ok := true ; - h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - - ypart llcorner SavedTextAreas[i]) ; - elseif ok : - h := h + _pmp_estimated_par_lines_(bbheight(SavedTextAreas[i])) ; - fi ; - endfor ; - fi ; - if ok : - for i := 1 upto n-1 : - h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; - endfor ; - else : - % already: ok := false ; - for i := 1 upto n-1 : - if (InsideTextArea(i,par_start_pos)) : - ok := true ; - h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ; - elseif ok : - h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; - fi ; - endfor ; - fi ; - h - fi -enddef ; + set_par_line_height (ph, pd) ; -vardef _pmp_left_top_hang_ (expr same_area) = + numeric par_hang_indent, par_hang_after, par_indent, par_left_skip, par_right_skip ; - par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; + par_hang_indent := rh ; + par_hang_after := ra ; + par_indent := ri ; + par_left_skip := rl ; + par_right_skip := rr ; - if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang : - pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])); - pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; - if same_area : - _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ; - fi ; - if obey_multi_par_more and (round(par_line_height)>0) : - par_hang_after := min(0,round(par_hang_after + - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; - fi ; - (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) -- - (xpart _ul_ + par_hang_indent, ypart _pa_) -- - (xpart ulcorner multipar, ypart _pa_) - else : - (xpart ulcorner multipar, ypart lrxy[fpos]) - fi -enddef ; + pair par_start_pos ; + pair par_stop_pos ; -vardef _pmp_right_top_hang_ (expr same_area) = + par_start_pos := llxy[fpos] + if par_indent <0: shifted (-par_indent, 0) fi + if par_left_skip<0: shifted (-par_left_skip,0) fi ; - par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; + par_stop_pos := lrxy[tpos] + if par_right_skip<0: shifted (par_right_skip,0) fi ; % nasty as the endpos can be shifted by rightskip - if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang : - pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; - pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; - if same_area : - _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; - fi ; - if obey_multi_par_more and (round(par_line_height)>0) : - par_hang_after := min(0,round(par_hang_after + - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; + if wxy[wpos]>0 : + left_skip := rl + xpart llxy[wpos] - xpart llxy[ppos] ; + right_skip := rw - left_skip - ww ; + else : + left_skip := rl ; + right_skip := rr ; fi ; - (xpart urcorner multipar, ypart _pa_) -- - (xpart _ur_ + par_hang_indent, ypart _pa_) -- - (xpart _ur_ + par_hang_indent, ypart _pmp_snapped_multi_pos_(urxy[fpos])) - else : - (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) - fi -enddef ; -vardef _pmp_x_left_top_hang_ (expr i, t) = - par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ; - if (par_hang_indent>0) and (par_hang_after<0) : - pair _ul_ ; _ul_ := ulcorner multipar ; - pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; - if t : - _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos])); - fi ; - if abs(ypart _pa_-ypart llxy[tpos])<par_line_height : - _pa_ := (xpart _pa_,ypart llxy[tpos]); - fi ; - if abs(ypart _pa_-ypart llcorner multipar)<par_line_height : - _pa_ := (xpart _pa_,ypart llcorner multipar); - fi ; - (xpart _ul_, ypart _pa_) -- - (xpart _ul_ + par_hang_indent, ypart _pa_) -- - (xpart _ul_ + par_hang_indent, ypart _ul_) - else : - ulcorner multipar - fi -enddef ; + path multipar, multipars[] ; + numeric multiref, multirefs[] ; + numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end -vardef _pmp_x_right_top_hang_ (expr i, t) = - par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ; - if (par_hang_indent<0) and (par_hang_after<0) : - pair _ur_ ; _ur_ := urcorner multipar ; - pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; - if t : - _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(urxy[tpos]))) ; - fi ; - (xpart _ur_ + par_hang_indent, ypart _ur_) -- - (xpart _ur_ + par_hang_indent, ypart _pa_) -- - (xpart _ur_, ypart _pa_) - else : - urcorner multipar - fi -enddef ; + numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ; -vardef _pmp_left_bottom_hang_ (expr same_area) = - pair _ll_, _sa_, _pa_ ; - _sa_ := if same_area : llxy[tpos] else : lrcorner multipar fi ; - if (par_hang_indent>0) and (par_hang_after>0) and obey_multi_par_hang : - _ll_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])) ; - _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; - if same_area : - _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; - fi ; - if obey_multi_par_more and (round(par_line_height)>0) : - par_hang_after := max(0,round(par_hang_after - - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; - fi ; - _pa_ -- - (xpart _pa_ + par_hang_indent,ypart _pa_) -- - (xpart _pa_ + par_hang_indent,ypart _sa_) - else : - (xpart llcorner multipar, ypart _sa_) - fi -enddef ; + % locals .. why can't i move these outside? -vardef _pmp_right_bottom_hang_ (expr same_area) = - pair _lr_, _sa_, _pa_ ; - _sa_ := if same_area : _pmp_snapped_multi_pos_(ulxy[tpos]) else : lrcorner multipar fi ; - if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang : - _lr_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; - _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; - if same_area : - _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; - fi ; - if obey_multi_par_more and (round(par_line_height)>0) : - par_hang_after := max(0,round(par_hang_after - - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; - fi ; - (xpart _pa_ + par_hang_indent,ypart _sa_) -- - (xpart _pa_ + par_hang_indent,ypart _pa_) -- - _pa_ - else : - (xpart lrcorner multipar, ypart _sa_) - fi -enddef ; + vardef _pmp_set_multipar_ (expr i) = + ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip + if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) ) + enddef ; -vardef _pmp_x_left_bottom_hang_ (expr i, t) = - pair _ll_, _sa_, _pa_ ; - _sa_ := if t : llxy[tpos] else : llcorner multipar fi ; - if (par_hang_indent>0) and (ra>0) : - par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i,t)) ; - _ll_ := ulcorner multipar ; - _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; - % we need to compensate for topskip enlarged areas - if abs(ypart _pa_ - ypart _sa_) > par_line_height : - (xpart _pa_ + par_hang_indent,ypart _sa_) -- - (xpart _pa_ + par_hang_indent,ypart _pa_) -- - fi - _pa_ - else : - (xpart llcorner multipar, ypart _sa_) - fi -enddef ; + vardef _pmp_snapped_multi_pos_ (expr p) = + if snap_multi_par_tops : + if abs(ypart p - ypart ulcorner multipar) < par_line_height : + (xpart p,ypart ulcorner multipar) + else : + p + fi + else : + p + fi + enddef ; -vardef _pmp_x_right_bottom_hang_ (expr i, t) = - pair _lr_, _sa_, _pa_ ; - _sa_ := if t : _pmp_snapped_multi_pos_(ulxy[tpos]) else : llcorner multipar fi ; - if (par_hang_indent<0) and (ra>0) : - par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i, t)) ; - _lr_ := urcorner multipar ; - _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; - _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; - % we need to compensate for topskip enlarged areas - _pa_ - if abs(ypart _pa_ - ypart _sa_) > par_line_height : - -- (xpart _pa_ + par_hang_indent,ypart _pa_) - -- (xpart _pa_ + par_hang_indent,ypart _sa_) - fi - else : - (xpart lrcorner multipar, ypart _sa_) - fi -enddef ; + vardef _pmp_estimated_par_lines_ (expr h) = + round(h/par_line_height) + enddef ; -% def _pmp_test_multipar_ = -% multipar := boundingbox multipar ; -% enddef ; + vardef _pmp_top_multi_par_(expr p) = + (round(_pmp_estimated_par_lines_(bbheight(p)*par_line_height))=round(bbheight(p))) + enddef ; - % first loop + vardef _pmp_multi_par_tsc_(expr p) = + if _pmp_top_multi_par_(p) : TopSkipCorrection else : 0 fi + enddef ; - ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ; + vardef _pmp_estimated_multi_par_height_ (expr n, t) = + if round(par_line_height)=0 : + 0 + else : + save ok, h ; boolean ok ; + numeric h ; h := 0 ; + ok := false ; + if (nxy[fpos]=RealPageNumber-1) : + for i := 1 upto NOfSavedTextAreas : + if (InsideSavedTextArea(i,par_start_pos)) : + ok := true ; + h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner SavedTextAreas[i]) ; + elseif ok : + h := h + _pmp_estimated_par_lines_(bbheight(SavedTextAreas[i])) ; + fi ; + endfor ; + fi ; + if ok : + for i := 1 upto n-1 : + h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; + endfor ; + else : + % already: ok := false ; + for i := 1 upto n-1 : + if (InsideTextArea(i,par_start_pos)) : + ok := true ; + h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ; + elseif ok : + h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ; + fi ; + endfor ; + fi ; + h + fi + enddef ; - if enable_multi_par_fallback and - (nxy[fpos]=RealPageNumber) and - (nxy[tpos]=RealPageNumber) and not - (InsideSomeTextArea(lxy[fpos]) and - InsideSomeTextArea(rxy[tpos])) : + vardef _pmp_left_top_hang_ (expr same_area) = - % fallback + par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; - % multipar := - % llxy[fpos] -- - % lrxy[tpos] -- - % urxy[tpos] -- - % ulxy[fpos] -- cycle ; - % - % save_multipar (1,1,multipar) ; + if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang : + pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])); + pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; + if same_area : + _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ; + fi ; + if obey_multi_par_more and (round(par_line_height)>0) : + par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; + fi ; + (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) -- + (xpart _ul_ + par_hang_indent, ypart _pa_) -- + (xpart ulcorner multipar, ypart _pa_) + else : + (xpart ulcorner multipar, ypart lrxy[fpos]) + fi + enddef ; - % we need to take the boundingbox because there can be - % more lines and we want a proper rectange + vardef _pmp_right_top_hang_ (expr same_area) = - multipar := - ulxy[fpos] -- - urxy[tpos] -- - lrxy[fpos] -- - llxy[tpos] -- cycle ; + par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ; - save_multipar (1,1,boundingbox(multipar)) ; + if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang : + pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; + pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ; + if same_area : + _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; + fi ; + if obey_multi_par_more and (round(par_line_height)>0) : + par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; + fi ; + (xpart urcorner multipar, ypart _pa_) -- + (xpart _ur_ + par_hang_indent, ypart _pa_) -- + (xpart _ur_ + par_hang_indent, ypart _pmp_snapped_multi_pos_(urxy[fpos])) + else : + (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) + fi + enddef ; - else : + vardef _pmp_x_left_top_hang_ (expr i, t) = + par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ; + if (par_hang_indent>0) and (par_hang_after<0) : + pair _ul_ ; _ul_ := ulcorner multipar ; + pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; + if t : + _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos])); + fi ; + if abs(ypart _pa_-ypart llxy[tpos])<par_line_height : + _pa_ := (xpart _pa_,ypart llxy[tpos]); + fi ; + if abs(ypart _pa_-ypart llcorner multipar)<par_line_height : + _pa_ := (xpart _pa_,ypart llcorner multipar); + fi ; + (xpart _ul_, ypart _pa_) -- + (xpart _ul_ + par_hang_indent, ypart _pa_) -- + (xpart _ul_ + par_hang_indent, ypart _ul_) + else : + ulcorner multipar + fi + enddef ; - % normal + vardef _pmp_x_right_top_hang_ (expr i, t) = + par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ; + if (par_hang_indent<0) and (par_hang_after<0) : + pair _ur_ ; _ur_ := urcorner multipar ; + pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; + if t : + _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(urxy[tpos]))) ; + fi ; + (xpart _ur_ + par_hang_indent, ypart _ur_) -- + (xpart _ur_ + par_hang_indent, ypart _pa_) -- + (xpart _ur_, ypart _pa_) + else : + urcorner multipar + fi + enddef ; - for i=1 upto NOfTextAreas : + vardef _pmp_left_bottom_hang_ (expr same_area) = + pair _ll_, _sa_, _pa_ ; + _sa_ := if same_area : llxy[tpos] else : lrcorner multipar fi ; + if (par_hang_indent>0) and (par_hang_after>0) and obey_multi_par_hang : + _ll_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])) ; + _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; + if same_area : + _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; + fi ; + if obey_multi_par_more and (round(par_line_height)>0) : + par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; + fi ; + _pa_ -- + (xpart _pa_ + par_hang_indent,ypart _pa_) -- + (xpart _pa_ + par_hang_indent,ypart _sa_) + else : + (xpart llcorner multipar, ypart _sa_) + fi + enddef ; - TopSkipCorrection := 0 ; + vardef _pmp_right_bottom_hang_ (expr same_area) = + pair _lr_, _sa_, _pa_ ; + _sa_ := if same_area : _pmp_snapped_multi_pos_(ulxy[tpos]) else : lrcorner multipar fi ; + if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang : + _lr_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ; + _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; + if same_area : + _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ; + fi ; + if obey_multi_par_more and (round(par_line_height)>0) : + par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ; + fi ; + (xpart _pa_ + par_hang_indent,ypart _sa_) -- + (xpart _pa_ + par_hang_indent,ypart _pa_) -- + _pa_ + else : + (xpart lrcorner multipar, ypart _sa_) + fi + enddef ; + + vardef _pmp_x_left_bottom_hang_ (expr i, t) = + pair _ll_, _sa_, _pa_ ; + _sa_ := if t : llxy[tpos] else : llcorner multipar fi ; + if (par_hang_indent>0) and (ra>0) : + par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i,t)) ; + _ll_ := ulcorner multipar ; + _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; + % we need to compensate for topskip enlarged areas + if abs(ypart _pa_ - ypart _sa_) > par_line_height : + (xpart _pa_ + par_hang_indent,ypart _sa_) -- + (xpart _pa_ + par_hang_indent,ypart _pa_) -- + fi + _pa_ + else : + (xpart llcorner multipar, ypart _sa_) + fi + enddef ; + + vardef _pmp_x_right_bottom_hang_ (expr i, t) = + pair _lr_, _sa_, _pa_ ; + _sa_ := if t : _pmp_snapped_multi_pos_(ulxy[tpos]) else : llcorner multipar fi ; + if (par_hang_indent<0) and (ra>0) : + par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i, t)) ; + _lr_ := urcorner multipar ; + _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ; + _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ; + % we need to compensate for topskip enlarged areas + _pa_ + if abs(ypart _pa_ - ypart _sa_) > par_line_height : + -- (xpart _pa_ + par_hang_indent,ypart _pa_) + -- (xpart _pa_ + par_hang_indent,ypart _sa_) + fi + else : + (xpart lrcorner multipar, ypart _sa_) + fi + enddef ; - multipar := _pmp_set_multipar_(i) ; + % def _pmp_test_multipar_ = + % multipar := boundingbox multipar ; + % enddef ; - % watch how we compensate for negative indentation + % first loop - if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) : + ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ; - % first one in chain + if enable_multi_par_fallback and (nxy[fpos]=RealPageNumber) + and (nxy[tpos]=RealPageNumber) and not (InsideSomeTextArea(lxy[fpos]) and InsideSomeTextArea(rxy[tpos])) : - ii := i ; + % fallback -% if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) : - if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : + % multipar := + % llxy[fpos] -- + % lrxy[tpos] -- + % urxy[tpos] -- + % ulxy[fpos] -- cycle ; + % + % save_multipar (1,1,multipar) ; - % in same area + % we need to take the boundingbox because there can be + % more lines and we want a proper rectange - nn := i ; + multipar := + ulxy[fpos] -- + urxy[tpos] -- + lrxy[fpos] -- + llxy[tpos] -- cycle ; - if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) : + save_multipar (1,1,boundingbox(multipar)) ; - TopSkipCorrection := TopSkip - StrutHeight ; + else : + + % normal + + for i=1 upto NOfTextAreas : - if round(ypart ulxy[fpos] + TopSkipCorrection) = - round(ypart ulcorner TextAreas[i]) : - ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ; - urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ; - else : TopSkipCorrection := 0 ; - fi ; - fi ; + multipar := _pmp_set_multipar_(i) ; - if ypart llxy[fpos] = ypart llxy[tpos] : + % watch how we compensate for negative indentation - multipar := - llxy[fpos] -- - lrxy[tpos] -- - %urxy[tpos] -- - _pmp_snapped_multi_pos_(urxy[tpos]) -- - %ulxy[fpos] -- - _pmp_snapped_multi_pos_(ulxy[fpos]) -- - cycle ; + if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) : - save_multipar (i,1,multipar) ; + % first one in chain - elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and - (xpart llxy[tpos] < xpart llxy[fpos]) : + ii := i ; - % two loners + if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : - multipar := if obey_multi_par_hang : + % in same area - _pmp_right_bottom_hang_(true) -- - _pmp_right_top_hang_(true) -- - _pmp_snapped_multi_pos_(urxy[fpos]) -- - lrxy[fpos] -- + nn := i ; - else : + if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) : - llxy[fpos] -- - (xpart urcorner multipar, ypart llxy[fpos]) -- - (xpart urcorner multipar, ypart ulxy[fpos]) -- - _pmp_snapped_multi_pos_(ulxy[fpos]) -- + TopSkipCorrection := TopSkip - StrutHeight ; - fi cycle ; + if round(ypart ulxy[fpos] + TopSkipCorrection) = round(ypart ulcorner TextAreas[i]) : + ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ; + urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ; + else : + TopSkipCorrection := 0 ; + fi ; - save_multipar (i,1,multipar) ; + fi ; - multipar := _pmp_set_multipar_(i) ; + if ypart llxy[fpos] = ypart llxy[tpos] : - multipar := if obey_multi_par_hang : + multipar := + llxy[fpos] -- + lrxy[tpos] -- + _pmp_snapped_multi_pos_(urxy[tpos]) -- + _pmp_snapped_multi_pos_(ulxy[fpos]) -- + cycle ; - _pmp_left_bottom_hang_(true) -- - llxy[tpos] -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - _pmp_left_top_hang_(true) -- + save_multipar (i,1,multipar) ; - else : + elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and (xpart llxy[tpos] < xpart llxy[fpos]) : - (xpart llcorner multipar, ypart llxy[tpos]) -- - llxy[tpos] -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - (xpart llcorner multipar, ypart ulxy[tpos]) -- + % two loners - fi cycle ; + multipar := if obey_multi_par_hang : - save_multipar (i,1,multipar) ; + _pmp_right_bottom_hang_(true) -- + _pmp_right_top_hang_(true) -- + _pmp_snapped_multi_pos_(urxy[fpos]) -- + lrxy[fpos] -- - else : + else : - multipar := if obey_multi_par_hang : + llxy[fpos] -- + (xpart urcorner multipar, ypart llxy[fpos]) -- + (xpart urcorner multipar, ypart ulxy[fpos]) -- + _pmp_snapped_multi_pos_(ulxy[fpos]) -- - _pmp_left_bottom_hang_(true) -- - llxy[tpos] -- - %ulxy[tpos] -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - _pmp_right_bottom_hang_(true) -- - _pmp_right_top_hang_(true) -- - %urxy[fpos] -- - _pmp_snapped_multi_pos_(urxy[fpos]) -- - lrxy[fpos] -- - _pmp_left_top_hang_(true) -- - - else : - - (xpart llcorner multipar, ypart llxy[tpos]) -- - llxy[tpos] -- - %ulxy[tpos] -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - (xpart lrcorner multipar, ypart ulxy[tpos]) -- - (xpart urcorner multipar, ypart urxy[fpos]) -- - %urxy[fpos] -- - _pmp_snapped_multi_pos_(urxy[fpos]) -- - lrxy[fpos] -- - (xpart ulcorner multipar, ypart lrxy[fpos]) -- + fi cycle ; - fi cycle ; + save_multipar (i,1,multipar) ; - save_multipar (i,1,multipar) ; + multipar := _pmp_set_multipar_(i) ; - fi ; + multipar := if obey_multi_par_hang : - else : + _pmp_left_bottom_hang_(true) -- + llxy[tpos] -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + _pmp_left_top_hang_(true) -- - multipar := if obey_multi_par_hang : + else : - _pmp_left_bottom_hang_(false) -- - _pmp_right_bottom_hang_(false) -- - _pmp_right_top_hang_(false) -- - %urxy[fpos] -- - _pmp_snapped_multi_pos_(urxy[fpos]) -- - lrxy[fpos] -- - _pmp_left_top_hang_(false) -- + (xpart llcorner multipar, ypart llxy[tpos]) -- + llxy[tpos] -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + (xpart llcorner multipar, ypart ulxy[tpos]) -- - else : + fi cycle ; - llcorner multipar -- - lrcorner multipar -- - (xpart urcorner multipar, ypart urxy[fpos]) -- - %urxy[fpos] -- - _pmp_snapped_multi_pos_(urxy[fpos]) -- - lrxy[fpos] -- - (xpart ulcorner multipar, ypart lrxy[fpos]) -- + save_multipar (i,1,multipar) ; - fi cycle ; + else : - save_multipar (i,1,multipar) ; + multipar := if obey_multi_par_hang : - fi ; + _pmp_left_bottom_hang_(true) -- + llxy[tpos] -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + _pmp_right_bottom_hang_(true) -- + _pmp_right_top_hang_(true) -- + _pmp_snapped_multi_pos_(urxy[fpos]) -- + lrxy[fpos] -- + _pmp_left_top_hang_(true) -- -% elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,llxy[tpos])) : - elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : + else : - % last one in chain + (xpart llcorner multipar, ypart llxy[tpos]) -- + llxy[tpos] -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + (xpart lrcorner multipar, ypart ulxy[tpos]) -- + (xpart urcorner multipar, ypart urxy[fpos]) -- + _pmp_snapped_multi_pos_(urxy[fpos]) -- + lrxy[fpos] -- + (xpart ulcorner multipar, ypart lrxy[fpos]) -- - nn := i ; + fi cycle ; - if obey_multi_par_hang and obey_multi_par_more : + save_multipar (i,1,multipar) ; - multipar := - _pmp_x_left_top_hang_(i,true) -- - _pmp_x_right_top_hang_(i,true) -- - _pmp_x_right_bottom_hang_(i,true) -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - llxy[tpos] -- - _pmp_x_left_bottom_hang_(i,true) -- - cycle ; + fi ; - else : + else : - multipar := - ulcorner multipar -- - urcorner multipar -- - (xpart lrcorner multipar, ypart urxy[tpos]) -- - _pmp_snapped_multi_pos_(ulxy[tpos]) -- - llxy[tpos] -- - (xpart llcorner multipar, ypart llxy[tpos]) -- - cycle ; + multipar := if obey_multi_par_hang : - fi ; + _pmp_left_bottom_hang_(false) -- + _pmp_right_bottom_hang_(false) -- + _pmp_right_top_hang_(false) -- + _pmp_snapped_multi_pos_(urxy[fpos]) -- + lrxy[fpos] -- + _pmp_left_top_hang_(false) -- - save_multipar (i,3,multipar) ; + else : - elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber) and (NOfTextColumns>1)) : + llcorner multipar -- + lrcorner multipar -- + (xpart urcorner multipar, ypart urxy[fpos]) -- + _pmp_snapped_multi_pos_(urxy[fpos]) -- + lrxy[fpos] -- + (xpart ulcorner multipar, ypart lrxy[fpos]) -- - save_multipar (i,2,multipar) ; + fi cycle ; - else : - % handled later - fi ; + save_multipar (i,1,multipar) ; - endfor ; + fi ; - % second loop + elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) : - if force_multi_par_chain or (ii > 1) : + % last one in chain - for i=ii+1 upto nn-1 : + nn := i ; - % rest of chain / todo : hang + if obey_multi_par_hang and obey_multi_par_more : -% hm, the second+ column in column sets now gets lost in a NOfTextColumns + multipar := + _pmp_x_left_top_hang_(i,true) -- + _pmp_x_right_top_hang_(i,true) -- + _pmp_x_right_bottom_hang_(i,true) -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + llxy[tpos] -- + _pmp_x_left_bottom_hang_(i,true) -- + cycle ; - if (not check_multi_par_chain) or - ((nxy[fpos]<RealPageNumber) and (nxy[tpos]>RealPageNumber)) - : + else : - multipar := _pmp_set_multipar_(i) ; + multipar := + ulcorner multipar -- + urcorner multipar -- + (xpart lrcorner multipar, ypart urxy[tpos]) -- + _pmp_snapped_multi_pos_(ulxy[tpos]) -- + llxy[tpos] -- + (xpart llcorner multipar, ypart llxy[tpos]) -- + cycle ; - if obey_multi_par_hang and obey_multi_par_more : + fi ; - multipar := - _pmp_x_left_top_hang_(i,false) -- - _pmp_x_right_top_hang_(i,false) -- - _pmp_x_right_bottom_hang_(i,false) -- - _pmp_x_left_bottom_hang_(i,false) -- - cycle ; + save_multipar (i,3,multipar) ; - fi ; + elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber) and (NOfTextColumns>1)) : - save_multipar(i,2,multipar) ; + save_multipar (i,2,multipar) ; - fi ; + else : + % handled later + fi ; - endfor ; + endfor ; - fi ; + % second loop - % end of normal/fallback + if force_multi_par_chain or (ii > 1) : -fi ; + for i=ii+1 upto nn-1 : - if span_multi_column_pars : - endgroup ; - fi ; + % rest of chain / todo : hang - % potential safeguard: + % hm, the second+ column in column sets now gets lost in a NOfTextColumns - % for i=1 upto nofmultipars : - % if length p <= 4 : - % multipars[i] := boundingbox(multipars[i]) ; - % fi ; - % end ; + if (not check_multi_par_chain) or ((nxy[fpos]<RealPageNumber) and (nxy[tpos]>RealPageNumber)) : - % quick hack for gb: + multipar := _pmp_set_multipar_(i) ; - one_piece_multi_par := (nofmultipars=1) and (pn=tn) ; + if obey_multi_par_hang and obey_multi_par_more : + + multipar := + _pmp_x_left_top_hang_(i,false) -- + _pmp_x_right_top_hang_(i,false) -- + _pmp_x_right_bottom_hang_(i,false) -- + _pmp_x_left_bottom_hang_(i,false) -- + cycle ; + + fi ; + + save_multipar(i,2,multipar) ; + + fi ; + + endfor ; + + fi ; + + % end of normal/fallback + + fi ; + + if span_multi_column_pars : + endgroup ; + fi ; + + % potential safeguard: + + % for i=1 upto nofmultipars : + % if length p <= 4 : + % multipars[i] := boundingbox(multipars[i]) ; + % fi ; + % end ; + + % quick hack for gb: + + one_piece_multi_par := (nofmultipars=1) and (pn=tn) ; enddef ; @@ -974,380 +964,375 @@ numeric boxgriddistance ; boxgriddistance := .5cm ; numeric boxgridshift ; boxgridshift := 0pt ; def draw_box = - draw pxy boxlineoptions withpen pencircle scaled boxlinewidth ; - draw lxy -- rxy boxlineoptions withpen pencircle scaled boxgridwidth ; + draw pxy boxlineoptions withpen pencircle scaled boxlinewidth ; + draw lxy -- rxy boxlineoptions withpen pencircle scaled boxgridwidth ; enddef ; def draw_par = % 1 2 3 11 12 - do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ; - for i = pxy, txy, bxy : + do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ; + for i = pxy, txy, bxy : if boxgridtype = 1 : - boxgriddirection := origin ; - draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; - elseif boxgridtype = 2 : - boxgriddirection := origin ; - draw baseline_grid (i,boxgriddirection,false) boxgridoptions ; - elseif boxgridtype = 3 : - boxgriddirection := origin ; - draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; - draw baseline_grid (i,boxgriddirection,true ) - shifted (0,ExHeight) boxgridoptions ; - elseif boxgridtype = 4 : - boxgriddirection := origin ; - draw baseline_grid (i,boxgriddirection,true ) - shifted (0,ExHeight/2) boxgridoptions ; - elseif boxgridtype = 11 : - draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; - elseif boxgridtype = 12 : - draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ; - fi ; - endfor ; + boxgriddirection := origin ; + draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; + elseif boxgridtype = 2 : + boxgriddirection := origin ; + draw baseline_grid (i,boxgriddirection,false) boxgridoptions ; + elseif boxgridtype = 3 : + boxgriddirection := origin ; + draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ; + draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight) boxgridoptions ; + elseif boxgridtype = 4 : + boxgriddirection := origin ; + draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight/2) boxgridoptions ; + elseif boxgridtype = 11 : + draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; + elseif boxgridtype = 12 : + draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ; + fi ; + endfor ; enddef ; def do_show_par (expr p, r, c) = - if length(p) > 2 : for i=0 upto length(p) : - draw fullcircle scaled r shifted point i of p - withpen pencircle scaled .5pt withcolor c ; - endfor ; fi ; - draw p withpen pencircle scaled .5pt withcolor c ; + if length(p) > 2 : + for i=0 upto length(p) : + draw fullcircle scaled r shifted point i of p withpen pencircle scaled .5pt withcolor c ; + endfor ; + fi ; + draw p withpen pencircle scaled .5pt withcolor c ; enddef ; def show_par = - if length(mxy) > 2 : - draw mxy dashed evenly - withpen pencircle scaled .5pt withcolor .5white ; - fi ; - do_show_par(txy, 4pt, .5green) ; - do_show_par(bxy, 6pt, .5blue ) ; - do_show_par(pxy, 8pt, .5red ) ; - draw pref withpen pencircle scaled 2pt ; + if length(mxy) > 2 : + draw mxy dashed evenly withpen pencircle scaled .5pt withcolor .5white ; + fi ; + do_show_par(txy, 4pt, .5green) ; + do_show_par(bxy, 6pt, .5blue ) ; + do_show_par(pxy, 8pt, .5red ) ; + draw pref withpen pencircle scaled 2pt ; enddef ; def sort_multi_pars = - if nofmultipars>1 : - begingroup ; save _p_, _n_ ; path _p_ ; numeric _n_ ; - for i := 1 upto nofmultipars : - if multilocs[i] = 3 : - _p_ := multipars[nofmultipars] ; - multipars[nofmultipars] := multipars[i] ; - multipars[i] := _p_ ; - _n_ := multirefs[nofmultipars] ; - multirefs[nofmultipars] := multirefs[i] ; - multirefs[i] := _n_ ; - _n_ := multilocs[nofmultipars] ; - multilocs[nofmultipars] := multilocs[i] ; - multilocs[i] := _n_ ; - fi ; - endfor ; - endgroup ; - fi ; + if nofmultipars>1 : + begingroup ; + save _p_, _n_ ; path _p_ ; numeric _n_ ; + for i := 1 upto nofmultipars : + if multilocs[i] = 3 : + _p_ := multipars[nofmultipars] ; + multipars[nofmultipars] := multipars[i] ; + multipars[i] := _p_ ; + _n_ := multirefs[nofmultipars] ; + multirefs[nofmultipars] := multirefs[i] ; + multirefs[i] := _n_ ; + _n_ := multilocs[nofmultipars] ; + multilocs[nofmultipars] := multilocs[i] ; + multilocs[i] := _n_ ; + fi ; + endfor ; + endgroup ; + fi ; enddef ; - def collapse_multi_pars = - if nofmultipars>1 : - begingroup ; save _nofmultipars_ ; numeric _nofmultipars_ ; - _nofmultipars_ := 1 ; - sort_multi_pars ; % block not in order: 1, 3, 2.... - for i:=1 upto nofmultipars-1 : - if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and - (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) : -multilocs[_nofmultipars_] := multilocs[i+1] ; -multirefs[_nofmultipars_] := multirefs[i+1] ; - multipars[_nofmultipars_] := - ulcorner multipars[_nofmultipars_] -- - urcorner multipars[_nofmultipars_] -- - lrcorner multipars[i+1] -- - llcorner multipars[i+1] -- cycle ; - else : - _nofmultipars_ := _nofmultipars_ + 1 ; - multipars[_nofmultipars_] := multipars[i+1] ; - multilocs[_nofmultipars_] := multilocs[i+1] ; - multirefs[_nofmultipars_] := multirefs[i+1] ; - fi ; - endfor ; - nofmultipars := _nofmultipars_ ; - endgroup ; - fi ; + if nofmultipars>1 : + begingroup ; + save _nofmultipars_ ; numeric _nofmultipars_ ; + _nofmultipars_ := 1 ; + sort_multi_pars ; % block not in order: 1, 3, 2.... + for i:=1 upto nofmultipars-1 : + if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and + (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) : + multilocs[_nofmultipars_] := multilocs[i+1] ; + multirefs[_nofmultipars_] := multirefs[i+1] ; + multipars[_nofmultipars_] := + ulcorner multipars[_nofmultipars_] -- + urcorner multipars[_nofmultipars_] -- + lrcorner multipars[i+1] -- + llcorner multipars[i+1] -- cycle ; + else : + _nofmultipars_ := _nofmultipars_ + 1 ; + multipars[_nofmultipars_] := multipars[i+1] ; + multilocs[_nofmultipars_] := multilocs[i+1] ; + multirefs[_nofmultipars_] := multirefs[i+1] ; + fi ; + endfor ; + nofmultipars := _nofmultipars_ ; + endgroup ; + fi ; enddef ; def draw_multi_pars = - for i=1 upto nofmultipars : - do_draw_par(multipars[i]) ; + for i=1 upto nofmultipars : + do_draw_par(multipars[i]) ; if boxgridtype= 1 : - draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; - elseif boxgridtype= 2 : - draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ; - elseif boxgridtype= 3 : - draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; - draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ; - elseif boxgridtype= 4 : - draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ; - elseif boxgridtype=11 : - draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; - elseif boxgridtype=12 : - draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ; - fi ; - endfor ; + draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; + elseif boxgridtype= 2 : + draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ; + elseif boxgridtype= 3 : + draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ; + draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ; + elseif boxgridtype= 4 : + draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ; + elseif boxgridtype=11 : + draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ; + elseif boxgridtype=12 : + draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ; + fi ; + endfor ; enddef ; def show_multi_pars = - for i=1 upto nofmultipars : - do_show_par(multipars[i], 6pt, .5blue) ; - endfor ; + for i=1 upto nofmultipars : + do_show_par(multipars[i], 6pt, .5blue) ; + endfor ; enddef ; vardef do_draw_par (expr p) = - if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) : - save pp ; path pp ; - if (boxlineradius>0) and (boxlinetype=2) : - pp := p cornered boxlineradius ; - else : - pp := p ; - fi ; - if boxfilltype>0 : - if boxfilloffset>0 : - % temporary hack - begingroup ; interim linejoin := mitered ; - filldraw pp boxfilloptions withpen pencircle scaled (2*boxfilloffset) ; - endgroup ; - else : - fill pp boxfilloptions ; - fi ; - fi ; - if boxlinetype>0 : - draw pp boxlineoptions withpen pencircle scaled boxlinewidth ; + if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) : + save pp ; path pp ; + if (boxlineradius>0) and (boxlinetype=2) : + pp := p cornered boxlineradius ; + else : + pp := p ; + fi ; + if boxfilltype>0 : + if boxfilloffset>0 : + % temporary hack + begingroup ; + interim linejoin := mitered ; + filldraw pp boxfilloptions withpen pencircle scaled (2*boxfilloffset) ; + endgroup ; + else : + fill pp boxfilloptions ; + fi ; + fi ; + if boxlinetype>0 : + draw pp boxlineoptions withpen pencircle scaled boxlinewidth ; + fi ; fi ; - fi ; enddef ; vardef baseline_grid (expr pxy, pdir, at_baseline) = - if (par_line_height>0) and (bbheight(pxy)>1) and (bbwidth(pxy)>1) and (boxgridwidth>0) : - save i, grid, bb ; picture grid ; pair start ; path bb ; - def _do_ (expr start) = - % 1 = normal, 2 = with background (i.e. no shine-through) - if boxdashtype = 2 : - draw start -- start shifted (bbwidth(pxy),0) - withpen pencircle scaled boxgridwidth - boxfilloptions ; - fi ; - draw start -- start shifted (bbwidth(pxy),0) - if boxdashtype > 0 : dashed evenly fi - withpen pencircle scaled boxgridwidth - boxgridoptions ; - enddef ; - grid := image - ( %fails with inlinespace - % - if pdir=up : - for i = if at_baseline : par_strut_depth else : 0 fi - step par_line_height - until max(bbheight(pxy),par_line_height) : - _do_ (llcorner pxy shifted (0,+i)) ; - endfor ; - else : - for i = if at_baseline : par_strut_height else : 0 fi - step par_line_height - until bbheight(pxy) : - _do_ (ulcorner pxy shifted (0,-i)) ; - endfor ; - fi ; - ) ; - clip grid to pxy ; - bb := boundingbox grid ; - grid := grid shifted (0,boxgridshift) ; - setbounds grid to bb ; - grid - else : - nullpicture - fi + if (par_line_height>0) and (bbheight(pxy)>1) and (bbwidth(pxy)>1) and (boxgridwidth>0) : + save i, grid, bb ; picture grid ; pair start ; path bb ; + def _do_ (expr start) = + % 1 = normal, 2 = with background (i.e. no shine-through) + if boxdashtype = 2 : + draw + start -- start shifted (bbwidth(pxy),0) + withpen pencircle scaled boxgridwidth + boxfilloptions ; + fi ; + draw start -- start shifted (bbwidth(pxy),0) + if boxdashtype > 0 : + dashed evenly + fi + withpen pencircle scaled boxgridwidth + boxgridoptions ; + enddef ; + grid := image ( %fails with inlinespace + if pdir=up : + for i = if at_baseline : par_strut_depth else : 0 fi step par_line_height until max(bbheight(pxy),par_line_height) : + _do_ (llcorner pxy shifted (0,+i)) ; + endfor ; + else : + for i = if at_baseline : par_strut_height else : 0 fi step par_line_height until bbheight(pxy) : + _do_ (ulcorner pxy shifted (0,-i)) ; + endfor ; + fi ; + ) ; + clip grid to pxy ; + bb := boundingbox grid ; + grid := grid shifted (0,boxgridshift) ; + setbounds grid to bb ; + grid + else : + nullpicture + fi enddef ; vardef graphic_grid (expr pxy, dx, dy, x, y) = - if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) : - save grid ; picture grid ; - grid := image - ( for i = xpart llcorner pxy step dx until xpart lrcorner pxy : - draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy) - withpen pencircle scaled boxgridwidth ; - endfor ; - for i = ypart llcorner pxy step dy until ypart ulcorner pxy : - draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i) - withpen pencircle scaled boxgridwidth ; - endfor ) shifted (x,y) ; - clip grid to pxy ; - grid - else : - nullpicture - fi + if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) : + save grid ; picture grid ; + grid := image ( + for i = xpart llcorner pxy step dx until xpart lrcorner pxy : + draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy) withpen pencircle scaled boxgridwidth ; + endfor ; + for i = ypart llcorner pxy step dy until ypart ulcorner pxy : + draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i) withpen pencircle scaled boxgridwidth ; + endfor + ) shifted (x,y) ; + clip grid to pxy ; + grid + else : + nullpicture + fi enddef ; def anchor_box (expr n,x,y,w,h,d) = - currentpicture := currentpicture shifted (-x,-y) ; + currentpicture := currentpicture shifted (-x,-y) ; enddef ; let draw_area = draw_box ; let anchor_area = anchor_box ; let anchor_par = anchor_box ; - numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ; pair sync_xy[][] ; color sync_c[][] ; def ResetSyncTasks = - path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ; - NOfSyncPaths := CurrentSyncClass := 0 ; - if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ; - if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ; - if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ; - if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ; - if (SyncLeftOffset = 0) and (SyncWidth = 0) : - SyncWidth := if known TextWidth : TextWidth else : -1cm fi ; - fi ; + path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ; + NOfSyncPaths := CurrentSyncClass := 0 ; + if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ; + if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ; + if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ; + if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ; + if (SyncLeftOffset = 0) and (SyncWidth = 0) : + SyncWidth := if known TextWidth : TextWidth else : -1cm fi ; + fi ; enddef ; ResetSyncTasks ; vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) = - save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ; - o shifted (leftoffset,sync_h[n][i]+topoffset) -- - o shifted (width+leftoffset,sync_h[n][i]+topoffset) -- - o shifted (width+leftoffset,bottomoffset) -- - o shifted (leftoffset,bottomoffset) -- cycle + save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ; + o shifted (leftoffset,sync_h[n][i]+topoffset) -- + o shifted (width+leftoffset,sync_h[n][i]+topoffset) -- + o shifted (width+leftoffset,bottomoffset) -- + o shifted (leftoffset,bottomoffset) -- cycle enddef ; def SetSyncColor(expr n, i, c) = - sync_c[n][i] := c ; + sync_c[n][i] := c ; enddef ; def SetSyncThreshold(expr n, i, th) = - sync_th[n][i] := th ; + sync_th[n][i] := th ; enddef ; vardef TheSyncColor(expr n, i) = - if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi + if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi enddef ; vardef TheSyncThreshold(expr n, i) = - if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi + if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi enddef ; vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) = - ResetSyncTasks ; - if known sync_n[n] : - CurrentSyncClass := n ; - save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ; - for i=1 upto sync_n[n] : - if RealPageNumber > sync_p[n][i] : - l := i ; - elseif RealPageNumber = sync_p[n][i] : - NOfSyncPaths := NOfSyncPaths + 1 ; - if not ok : - if i>1 : - if sync_t[n][i-1] = sync_t[n][i] : - SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := i ; - else : - SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := i-1 ; - NOfSyncPaths := NOfSyncPaths + 1 ; - SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := i ; + ResetSyncTasks ; + if known sync_n[n] : + CurrentSyncClass := n ; + save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ; + for i=1 upto sync_n[n] : + if RealPageNumber > sync_p[n][i] : + l := i ; + elseif RealPageNumber = sync_p[n][i] : + NOfSyncPaths := NOfSyncPaths + 1 ; + if not ok : + if i>1 : + if sync_t[n][i-1] = sync_t[n][i] : + SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := i ; + else : + SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := i-1 ; + NOfSyncPaths := NOfSyncPaths + 1 ; + SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := i ; + fi ; + else : + SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := i ; + fi ; + else : + SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := i ; + fi ; + ok := true ; fi ; - else : - SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := i ; - fi ; - else : - SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := i ; + endfor ; + if (NOfSyncPaths = 0) and (l > 0) : + NOfSyncPaths := 1 ; + SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; + SyncTasks[NOfSyncPaths] := l ; fi ; - ok := true ; - fi ; - endfor ; - if (NOfSyncPaths = 0) and (l > 0) : - NOfSyncPaths := 1 ; - SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ; - SyncTasks[NOfSyncPaths] := l ; - fi ; - if NOfSyncPaths > 0 : - for i = 1 upto NOfSyncPaths-1 : - SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ; - endfor ; - if unknown SyncThresholdMethod : - numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ; - fi ; - if extendtop : - if SyncThresholdMethod = 1 : - if NOfSyncPaths>1 : - d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ; - if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) : - SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ; + if NOfSyncPaths > 0 : + for i = 1 upto NOfSyncPaths-1 : + SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ; + endfor ; + if unknown SyncThresholdMethod : + numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ; fi ; - fi ; - else : - for i = 1 upto NOfSyncPaths : - d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ; - if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) : - SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ; + if extendtop : + if SyncThresholdMethod = 1 : + if NOfSyncPaths>1 : + d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ; + if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) : + SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ; + fi ; + fi ; + else : + for i = 1 upto NOfSyncPaths : + d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ; + if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) : + SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ; + fi ; + endfor ; + fi ; fi ; - endfor ; - fi ; - fi ; - if prestartnext : - if NOfSyncPaths>1 : - if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one - d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ; - if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) : - SyncPaths[NOfSyncPaths+1] := - (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- - (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- - lrcorner SyncPaths[NOfSyncPaths] -- - llcorner SyncPaths[NOfSyncPaths] -- cycle ; - SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ; - NOfSyncPaths := NOfSyncPaths + 1 ; + if prestartnext : + if NOfSyncPaths>1 : + if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one + d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ; + if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) : + SyncPaths[NOfSyncPaths+1] := + (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- + (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) -- + lrcorner SyncPaths[NOfSyncPaths] -- + llcorner SyncPaths[NOfSyncPaths] -- cycle ; + SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ; + NOfSyncPaths := NOfSyncPaths + 1 ; + fi ; + fi ; + fi ; + else : + if NOfSyncPaths>1 : + d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ; + if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) : + NOfSyncPaths := NOfSyncPaths - 1 ; + SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ; + fi ; + fi ; + fi ; + if (NOfSyncPaths>1) and collapse : + save j ; numeric j ; j := 1 ; + for i = 2 upto NOfSyncPaths : + if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] : + SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ; + SyncTasks[j] := SyncTasks[i] ; + else : + j := j + 1 ; + SyncPaths[j] := SyncPaths[i] ; + SyncTasks[j] := SyncTasks[i] ; + fi ; + endfor ; + NOfSyncPaths := j ; fi ; - fi ; - fi ; - else : - if NOfSyncPaths>1 : - d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ; - if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) : - NOfSyncPaths := NOfSyncPaths - 1 ; - SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ; - fi ; fi ; - fi ; - if (NOfSyncPaths>1) and collapse : - save j ; numeric j ; j := 1 ; - for i = 2 upto NOfSyncPaths : - if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] : - SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ; - SyncTasks[j] := SyncTasks[i] ; - else : - j := j + 1 ; - SyncPaths[j] := SyncPaths[i] ; - SyncTasks[j] := SyncTasks[i] ; - fi ; - endfor ; - NOfSyncPaths := j ; - fi ; fi ; - fi ; enddef ; def SyncTask(expr n) = - if known SyncTasks[n] : SyncTasks[n] else : 0 fi + if known SyncTasks[n] : SyncTasks[n] else : 0 fi enddef ; def FlushSyncTasks = - for i = 1 upto NOfSyncPaths : - ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ; - endfor ; + for i = 1 upto NOfSyncPaths : + ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ; + endfor ; enddef ; def ProcessSyncTask(expr p, c) = - fill p withcolor c ; + fill p withcolor c ; enddef ; endinput ; diff --git a/metapost/context/base/mp-figs.mp b/metapost/context/base/mp-figs.mpii index da5fa0d16..c90dc3971 100644 --- a/metapost/context/base/mp-figs.mp +++ b/metapost/context/base/mp-figs.mpii @@ -1,5 +1,5 @@ %D \module -%D [ file=mp-tool.mp, +%D [ file=mp-figs.mp, %D version=2003.01.15, %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=figures, @@ -11,37 +11,36 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_figs : endinput ; fi ; +if known context_figs : endinput ; fi ; boolean context_figs ; context_figs := true ; % todo: check defined def registerfigure(expr name,width,height) = - begingroup ; - save s ; string s ; s := cleanstring(name) ; - scantokens( s & "_width := " & decimal(width)) ; - scantokens( s & "_height := " & decimal(height)) ; - endgroup ; + begingroup ; + save s ; string s ; s := cleanstring(name) ; + scantokens( s & "_width := " & decimal(width )) ; + scantokens( s & "_height := " & decimal(height)) ; + endgroup ; enddef ; vardef figuresize(expr name) = - save s ; string s ; s := cleanstring(name) ; - save p ; pair p ; - scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ; - p + save s, p ; string s ; pair p ; + s := cleanstring(name) ; + scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ; + p enddef ; vardef figurewidth(expr name) = - xpart figuresize(name) + xpart figuresize(name) enddef ; vardef figureheight(expr name) = - ypart figuresize(name) + ypart figuresize(name) enddef ; -def figuredimensions = figuresize enddef ; % for old times sake +let figuredimensions = figuresize ; % for old times sake def naturalfigure(expr name) = externalfigure name xyscaled(figuresize(name)) diff --git a/metapost/context/base/mp-figs.mpiv b/metapost/context/base/mp-figs.mpiv new file mode 100644 index 000000000..c90dc3971 --- /dev/null +++ b/metapost/context/base/mp-figs.mpiv @@ -0,0 +1,49 @@ +%D \module +%D [ file=mp-figs.mp, +%D version=2003.01.15, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=figures, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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_figs : endinput ; fi ; + +boolean context_figs ; context_figs := true ; + +% todo: check defined + +def registerfigure(expr name,width,height) = + begingroup ; + save s ; string s ; s := cleanstring(name) ; + scantokens( s & "_width := " & decimal(width )) ; + scantokens( s & "_height := " & decimal(height)) ; + endgroup ; +enddef ; + +vardef figuresize(expr name) = + save s, p ; string s ; pair p ; + s := cleanstring(name) ; + scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ; + p +enddef ; + +vardef figurewidth(expr name) = + xpart figuresize(name) +enddef ; + +vardef figureheight(expr name) = + ypart figuresize(name) +enddef ; + +let figuredimensions = figuresize ; % for old times sake + +def naturalfigure(expr name) = + externalfigure name xyscaled(figuresize(name)) +enddef ; + +endinput diff --git a/metapost/context/base/mp-fobg.mp b/metapost/context/base/mp-fobg.mp index 712efe751..f8b709572 100644 --- a/metapost/context/base/mp-fobg.mp +++ b/metapost/context/base/mp-fobg.mp @@ -11,8 +11,7 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_fobg : endinput ; fi ; +if known context_fobg : endinput ; fi ; boolean context_fobg ; context_fobg := true ; diff --git a/metapost/context/base/mp-func.mp b/metapost/context/base/mp-func.mp deleted file mode 100644 index d8646ef3b..000000000 --- a/metapost/context/base/mp-func.mp +++ /dev/null @@ -1,59 +0,0 @@ -%D \module -%D [ file=mp-func.mp, -%D version=2001.12.29, -%D title=\CONTEXT\ \METAPOST\ graphics, -%D subtitle=function hacks, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] -%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. - -%D Under construction. - -if unknown context_tool : input mp-tool ; fi ; -if known context_func : endinput ; fi ; - -boolean context_func ; context_func := true ; - -string pathconnectors[] ; - -pathconnectors[0] := "," ; -pathconnectors[1] := "--" ; -pathconnectors[2] := ".." ; -pathconnectors[3] := "..." ; - -vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ; - for xx := b step s until e : - hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi - (scantokens(u),scantokens(t)) - endfor -enddef ; - -def punkedfunction = function (1) enddef ; -def curvedfunction = function (2) enddef ; -def tightfunction = function (3) enddef ; - -vardef constructedpath (expr f) (text t) = - save ok ; boolean ok ; ok := false ; - for i=t : - if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i - endfor -enddef ; - -def punkedpath = constructedpath (1) enddef ; -def curvedpath = constructedpath (2) enddef ; -def tightpath = constructedpath (3) enddef ; - -vardef constructedpairs (expr f) (text p) = - save i ; i := -1 ; - forever : exitif unknown p[incr(i)] ; - if i>0 : scantokens(pathconnectors[f]) fi p[i] - endfor -enddef ; - -def punkedpairs = constructedpairs (1) enddef ; -def curvedpairs = constructedpairs (2) enddef ; -def tightpairs = constructedpairs (3) enddef ; diff --git a/metapost/context/base/mp-func.mpii b/metapost/context/base/mp-func.mpii new file mode 100644 index 000000000..407d534e8 --- /dev/null +++ b/metapost/context/base/mp-func.mpii @@ -0,0 +1,58 @@ +%D \module +%D [ file=mp-func.mp, +%D version=2001.12.29, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=function hacks, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D Under construction. + +if known context_func : endinput ; fi ; + +boolean context_func ; context_func := true ; + +string pathconnectors[] ; + +pathconnectors[0] := "," ; +pathconnectors[1] := "--" ; +pathconnectors[2] := ".." ; +pathconnectors[3] := "..." ; + +vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ; + for xx := b step s until e : + hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi + (scantokens(u),scantokens(t)) + endfor +enddef ; + +def punkedfunction = function (1) enddef ; +def curvedfunction = function (2) enddef ; +def tightfunction = function (3) enddef ; + +vardef constructedpath (expr f) (text t) = + save ok ; boolean ok ; ok := false ; + for i=t : + if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i + endfor +enddef ; + +def punkedpath = constructedpath (1) enddef ; +def curvedpath = constructedpath (2) enddef ; +def tightpath = constructedpath (3) enddef ; + +vardef constructedpairs (expr f) (text p) = + save i ; i := -1 ; + forever : exitif unknown p[incr(i)] ; + if i>0 : scantokens(pathconnectors[f]) fi p[i] + endfor +enddef ; + +def punkedpairs = constructedpairs (1) enddef ; +def curvedpairs = constructedpairs (2) enddef ; +def tightpairs = constructedpairs (3) enddef ; diff --git a/metapost/context/base/mp-func.mpiv b/metapost/context/base/mp-func.mpiv new file mode 100644 index 000000000..6ce7ee82a --- /dev/null +++ b/metapost/context/base/mp-func.mpiv @@ -0,0 +1,70 @@ +%D \module +%D [ file=mp-func.mp, +%D version=2001.12.29, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=function hacks, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D Under construction. + +if known context_func : endinput ; fi ; + +boolean context_func ; context_func := true ; + +string mfun_pathconnectors[] ; + +mfun_pathconnectors[0] := "," ; +mfun_pathconnectors[1] := "--" ; +mfun_pathconnectors[2] := ".." ; +mfun_pathconnectors[3] := "..." ; + +vardef mfun_draw_function (expr f) (expr u, t, b, e, s) = save x ; numeric x ; + for xx := b step s until e : + hide (x := xx ;) + if xx > b : + scantokens(mfun_pathconnectors[f]) + fi + (scantokens(u),scantokens(t)) + endfor +enddef ; + +def punkedfunction = mfun_function (1) enddef ; +def curvedfunction = mfun_function (2) enddef ; +def tightfunction = mfun_function (3) enddef ; + +vardef mfun_constructedpath (expr f) (text t) = + save ok ; boolean ok ; ok := false ; + for i=t : + if ok : + scantokens(mfun_pathconnectors[f]) + else : + ok := true ; + fi + i + endfor +enddef ; + +def punkedpath = mfun_constructedpath (1) enddef ; +def curvedpath = mfun_constructedpath (2) enddef ; +def tightpath = mfun_constructedpath (3) enddef ; + +vardef mfun_constructedpairs (expr f) (text p) = + save i ; i := -1 ; + forever : + exitif unknown p[incr(i)] ; + if i>0 : + scantokens(mfun_pathconnectors[f]) + fi + p[i] + endfor +enddef ; + +def punkedpairs = mfun_constructedpairs (1) enddef ; +def curvedpairs = mfun_constructedpairs (2) enddef ; +def tightpairs = mfun_constructedpairs (3) enddef ; diff --git a/metapost/context/base/mp-grid.mp b/metapost/context/base/mp-grid.mpii index c87df821c..bfc8dfed6 100644 --- a/metapost/context/base/mp-grid.mp +++ b/metapost/context/base/mp-grid.mpii @@ -13,8 +13,7 @@ %D Under construction. -if unknown context_tool : input mp-tool ; fi ; -if known context_grid : endinput ; fi ; +if known context_grid : endinput ; fi ; boolean context_grid ; context_grid := true ; diff --git a/metapost/context/base/mp-grid.mpiv b/metapost/context/base/mp-grid.mpiv new file mode 100644 index 000000000..ee8f2489d --- /dev/null +++ b/metapost/context/base/mp-grid.mpiv @@ -0,0 +1,170 @@ +%D \module +%D [ file=mp-grid.mp, +%D version=2000.07.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=grid support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D Under construction. + +if known context_grid : endinput ; fi ; + +boolean context_grid ; context_grid := true ; + +string fmt_separator ; fmt_separator := "@" ; +numeric fmt_precision ; fmt_precision := 3 ; +boolean fmt_initialize ; fmt_initialize := false ; +boolean fmt_zerocheck ; fmt_zerocheck := true ; + +if unknown fmt_loaded : input mp-form ; fi ; + +boolean fmt_pictures ; fmt_pictures := true ; + +def do_format = if fmt_pictures : format else : formatstr fi enddef ; +def do_mformat = if fmt_pictures : Mformat else : Mformatstr fi enddef ; + +numeric grid_eps ; grid_eps = eps ; + +def hlingrid (expr Min, Max, Step, Length, Width) text t = + image ( + for i=Min step Step until Max+grid_eps : + draw (origin--(Width,0)) shifted (0,i*(Length/Max)) t ; + endfor ; + ) ; +enddef ; + +def vlingrid (expr Min, Max, Step, Length, Height) text t = + image ( + for i=Min step Step until Max+grid_eps : + draw (origin--(0,Height)) shifted (i*(Length/Max),0) t ; + endfor ; + ) ; +enddef ; + +def hloggrid (expr Min, Max, Step, Length, Width) text t = + image ( + for i=max(Min,1) step Step until min(Max,10)+grid_eps : + draw (origin--(Width,0)) shifted (0,Length*log(i)) t ; + endfor ; + ) ; +enddef ; + +def vloggrid (expr Min, Max, Step, Length, Height) text t = + image ( + for i=max(Min,1) step Step until min(Max,10)+grid_eps : + draw (origin--(0,Height)) shifted (Length*log(i),0) t ; + endfor ; + ) ; +enddef ; + +vardef hlintext@#(expr Min, Max, Step, Length, Format) text t = + image ( + do_initialize_numbers ; + for i=Min step Step until Max+grid_eps : + draw textext@#(do_format(Format,i)) shifted (0,i*(Length/Max)) t ; + endfor ; + ) +enddef ; + +vardef vlintext@#(expr Min, Max, Step, Length, Format) text t = + image ( + do_initialize_numbers ; + for i=Min step Step until Max+grid_eps : + draw textext@#(do_format(Format,i)) shifted (i*(Length/Max),0) t ; + endfor ; + ) +enddef ; + +vardef hlogtext@#(expr Min, Max, Step, Length, Format) text t = + image ( + do_initialize_numbers ; + for i=max(Min,1) step Step until min(Max,10)+grid_eps : + draw textext@#(do_format(Format,i)) shifted (0,Length*log(i)) t ; + endfor ; + ) +enddef ; + +vardef vlogtext@#(expr Min, Max, Step, Length, Format) text t = + image ( + do_initialize_numbers ; + for i=max(Min,1) step Step until min(Max,10)+grid_eps : + draw textext@#(do_format(Format,i)) shifted (Length*log(i),0) t ; + endfor ; + ) +enddef ; + +vardef hlinlabel@#(expr Min, Max, Step, Length) text t = + image ( + for i=Min step Step until Max+grid_eps : + draw thelabel@#(decimal i,(0,i*(Length/Max))) t ; + endfor ; + ) +enddef ; + +vardef vlinlabel@#(expr Min, Max, Step, Length) text t = + image ( + for i=Min step Step until Max+grid_eps : + draw thelabel@#(decimal i,(i*(Length/Max),0)) t ; + endfor ; + ) +enddef ; + +boolean numbers_initialized ; numbers_initialized := false ; + +def do_initialize_numbers = + if not numbers_initialized : + init_numbers ( + textext.raw("$-$") , + textext.raw("$1$") , + textext.raw("${\times}10$") , + textext.raw("${}^-$") , + textext.raw("${}^2$") + ) ; + if unknown _trial_run_ : + numbers_initialized := true ; + else : + % no reset, otherwise textexts get out of sync + % slows down graphics a bit but not much + fi ; + fi ; +enddef ; + +def initialize_numbers = + numbers_initialized := false ; + do_initialize_numbers ; +enddef ; + +vardef linlog(expr xy) = ( xpart xy, log(ypart xy)) enddef ; +vardef loglin(expr xy) = (log(xpart xy), ypart xy) enddef ; +vardef loglog(expr xy) = (log(xpart xy), log(ypart xy)) enddef ; +vardef linlin(expr xy) = ( (xpart xy), (ypart xy)) enddef ; + +vardef loglinpath primary p = processpath (p) (loglin) enddef ; +vardef linlogpath primary p = processpath (p) (linlog) enddef ; +vardef loglogpath primary p = processpath (p) (loglog) enddef ; +vardef linlinpath primary p = processpath (p) (linlin) enddef ; + +vardef processpath (expr p) (text pp) = + if path p : + for i=0 upto length(p)-1 : + pp(point i of p) .. controls + pp(postcontrol i of p) and + pp(precontrol (i+1) of p) .. + endfor + if cycle p : + cycle + else : + pp(point length(p) of p) + fi + elseif pair p : + pp(p) + else : + p + fi +enddef ; diff --git a/metapost/context/base/mp-grph.mp b/metapost/context/base/mp-grph.mpii index 48776a09f..18183304c 100644 --- a/metapost/context/base/mp-grph.mp +++ b/metapost/context/base/mp-grph.mpii @@ -13,8 +13,7 @@ %D Under construction. -if unknown context_tool : input mp-tool ; fi ; -if known context_grph : endinput ; fi ; +if known context_grph : endinput ; fi ; boolean context_grph ; context_grph := true ; diff --git a/metapost/context/base/mp-grph.mpiv b/metapost/context/base/mp-grph.mpiv new file mode 100644 index 000000000..7291103ec --- /dev/null +++ b/metapost/context/base/mp-grph.mpiv @@ -0,0 +1,259 @@ +%D \module +%D [ file=mp-grph.mp, +%D version=2000.12.14, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=graphic text support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D Under construction. + +if known context_grph : endinput ; fi ; + +boolean context_grph ; context_grph := true ; + +picture _currentpicture_ ; + +numeric _fig_nesting_ ; _fig_nesting_ := 0 ; + +def beginfig (expr c) = + _fig_nesting_ := _fig_nesting_ + 1 ; + if _fig_nesting_ = 1 : + begingroup + charcode := c ; + resetfig ; + scantokens extra_beginfig ; + fi ; +enddef ; + +def endfig = + ; % safeguard + if _fig_nesting_ = 1 : + scantokens extra_endfig; + shipit ; + endgroup ; + fi ; + _fig_nesting_ := _fig_nesting_ - 1 ; +enddef; + +def resetfig = + clearxy ; + clearit ; + clearpen ; + pickup defaultpen ; + interim linecap := linecap ; + interim linejoin := linejoin ; + interim miterlimit := miterlimit ; + save _background_ ; color _background_ ; _background_ := background ; + save background ; color background ; background := _background_ ; + drawoptions () ; +enddef ; + +def protectgraphicmacros = + save showtext ; + save beginfig ; let beginfig = begingraphictextfig ; + save endfig ; let endfig = endgraphictextfig ; + save end ; let end = relax ; + interim prologues := prologues ; + resetfig ; % resets currentpicture +enddef ; + +numeric currentgraphictext ; currentgraphictext := 0 ; + +def data_mpo_file = job_name & "-mpgraph.mpo" enddef ; +def data_mpy_file = job_name & "-mpgraph.mpy" enddef ; + +def begingraphictextfig (expr n) = + foundpicture := n ; + scratchpicture := nullpicture ; +enddef ; + +def endgraphictextfig = + if foundpicture = currentgraphictext : + expandafter endinput + else : + scratchpicture := nullpicture ; + fi ; +enddef ; + +def loadfigure primary filename = + doloadfigure (filename) +enddef ; + +def doloadfigure (expr filename) text figureattributes = + begingroup ; + save figurenumber, figurepicture, number, fixedplace ; + numeric figurenumber ; figurenumber := 0 ; + boolean figureshift ; figureshift := true ; + picture figurepicture ; figurepicture := currentpicture ; + def number primary n = hide(figurenumber := n) enddef ; + def fixedplace = hide(figureshift := false) enddef ; + protectgraphicmacros ; + % defaults + interim linecap := rounded ; + interim linejoin := rounded ; + interim miterlimit := 10 ; + % + currentpicture := nullpicture ; + draw fullcircle figureattributes ; % expand number + currentpicture := nullpicture ; + def beginfig (expr n) = + currentpicture := nullpicture ; + if (figurenumber=n) or (figurenumber=0) : + let endfig = endinput ; + fi ; + enddef ; + let endfig = relax ; + readfile(filename) ; + if figureshift : + currentpicture := currentpicture shifted -llcorner currentpicture ; + fi ; + addto figurepicture also currentpicture figureattributes ; + currentpicture := figurepicture ; + endgroup ; +enddef ; + +def graphictext primary t = + if mfun_trial_run : + let mfun_graphic_text = mfun_no_graphic_text ; + else : + let mfun_graphic_text = mfun_do_graphic_text ; + fi + mfun_graphic_text(t) +enddef ; + +def mfun_do_graphic_text (expr t) = + % withprescript "gt_stage=final" + begingroup ; + save figurepicture ; picture figurepicture ; + figurepicture := currentpicture ; currentpicture := nullpicture ; + currentgraphictext := currentgraphictext + 1 ; + mfun_finish_graphic_text % picks up directives +enddef ; + +def mfun_no_graphic_text (expr t) text rest = + draw unitsquare withprescript "gt_stage=trial" withpostscript t +enddef ; + +def mfun_finish_graphic_text text x_op_x = + protectgraphicmacros ; % resets currentpicture + interim linecap := butt ; % normally rounded + interim linejoin := mitered ; % normally rounded + interim miterlimit := 10 ; % todo + let normalwithshade = withshade ; + save foundpicture, scratchpicture, str ; + save fill, draw, withshade, reversefill, outlinefill ; + save withfillcolor, withdrawcolor ; % quite important + numeric foundpicture ; picture scratchpicture ; string str ; + def draw expr p = + % the first, naive implementation was: + % addto scratchpicture doublepath p withpen currentpen ; + % but it is better to turn lines into fills + addto scratchpicture contour boundingbox + image (addto currentpicture doublepath p withpen currentpen) ; + enddef ; + def fill expr p = + addto scratchpicture contour p withpen currentpen ; + enddef ; + def f_op_f = enddef ; boolean f_color ; f_color := false ; + def d_op_d = enddef ; boolean d_color ; d_color := false ; + def s_op_s = enddef ; boolean s_color ; s_color := false ; + boolean reverse_fill ; reverse_fill := false ; + boolean outline_fill ; outline_fill := false ; + def reversefill = + hide(reverse_fill := true ) + enddef ; + def outlinefill = + hide(outline_fill := true ) + enddef ; + def withshade primary c = + hide(def s_op_s = normalwithshade c enddef ; s_color := true ) + enddef ; + def withfillcolor primary c = + hide(def f_op_f = withcolor c enddef ; f_color := true ) + enddef ; + def withdrawcolor primary c = + hide(def d_op_d = withcolor c enddef ; d_color := true ) + enddef ; + scratchpicture := nullpicture ; + addto scratchpicture doublepath origin x_op_x ; % pre-roll + for i within scratchpicture : % Below here is a dirty tricky test! + if (urcorner dashpart i) = origin : + outline_fill := false ; + fi ; + endfor ; + scratchpicture := nullpicture ; + readfile(data_mpy_file) ; + scratchpicture := (scratchpicture shifted -llcorner scratchpicture) scaled (1/10) ; + if not d_color and not f_color : + d_color := true ; + fi + if s_color : + d_color := false ; + f_color := false ; + fi ; + currentpicture := figurepicture ; + if d_color and not reverse_fill : + for i within scratchpicture : + if f_color and outline_fill : + addto currentpicture doublepath pathpart i _op_ x_op_x f_op_f dashed nullpicture ; + fi ; + if filled i : + addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ; + fi ; + endfor ; + fi ; + if f_color : + for i within scratchpicture : + if filled i : + addto currentpicture contour pathpart i _op_ x_op_x f_op_f withpen pencircle scaled 0 ; + fi ; + endfor ; + fi ; + if d_color and reverse_fill : + for i within scratchpicture : + if filled i : + addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ; + fi ; + endfor ; + fi ; + if s_color : + for i within scratchpicture : + if filled i : + addto currentpicture contour pathpart i _op_ x_op_x s_op_s ; + fi ; + endfor ; + else : + for i within scratchpicture : + if stroked i : + addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ; + fi ; + endfor ; + fi ; + endgroup ; +enddef ; + +endinput + +% example + +beginfig (1) ; + graphictext + "\vbox{\hsize10cm \input tufte }" + scaled 8 + withdrawcolor blue + withfillcolor red + withpen pencircle scaled 2pt ; +endfig ; + +beginfig(1) ; + loadfigure "gracht.mp" rotated 20 ; + loadfigure "koe.mp" number 1 scaled 2 ; +endfig ; + +end diff --git a/metapost/context/base/mp-mlib.mpiv b/metapost/context/base/mp-mlib.mpiv index c7240e127..fe27bee47 100644 --- a/metapost/context/base/mp-mlib.mpiv +++ b/metapost/context/base/mp-mlib.mpiv @@ -89,28 +89,30 @@ def withtransparency(expr alternative, transparency) = withprescript "tr_transparency=" & decimal transparency enddef ; -def cmyk(expr c, m, y, k) = +def cmyk(expr c, m, y, k) = % provided for downward compability (c,m,y,k) enddef ; -% Texts +% Texts (todo: better strut ratio, now .7 hardcoded, should be passed) -numeric _tt_w_[], _tt_h_[], _tt_d_[] ; -numeric _tt_n_ ; _tt_n_ := 0 ; -picture _tt_p_ ; _tt_p_ := nullpicture ; -boolean _trial_run_ ; _trial_run_ := false ; +newinternal textextoffset ; textextoffset := 0 ; -def resettextexts = - _tt_n_ := 0 ; - _tt_p_ := nullpicture ; +numeric mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space) +numeric mfun_tt_n ; mfun_tt_n := 0 ; +picture mfun_tt_p ; mfun_tt_p := nullpicture ; +boolean mfun_trial_run ; mfun_trial_run := false ; + +def mfun_reset_tex_texts = + mfun_tt_n := 0 ; + mfun_tt_p := nullpicture ; enddef ; -def flushtextexts = - addto currentpicture also _tt_p_ +def mfun_flush_tex_texts = + addto currentpicture also mfun_tt_p enddef ; -extra_endfig := "flushtextexts;" & extra_endfig; -extra_beginfig := extra_beginfig & "resettextexts;"; +extra_endfig := "mfun_flush_tex_texts;" & extra_endfig; +extra_beginfig := extra_beginfig & "mfun_reset_tex_texts;"; % We collect and flush them all, as we can also have temporary textexts % that gets never really flushed but are used for calculations. So, we @@ -120,29 +122,29 @@ extra_beginfig := extra_beginfig & "resettextexts;"; vardef rawtextext(expr str) = if str = "" : nullpicture - elseif _trial_run_ : - _tt_n_ := _tt_n_ + 1 ; - addto _tt_p_ doublepath unitsquare - withprescript "tx_number=" & decimal _tt_n_ + elseif mfun_trial_run : + mfun_tt_n := mfun_tt_n + 1 ; + 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 _tt_n_ + withprescript "tx_number=" & decimal mfun_tt_n withprescript "tx_stage=trial" withpostscript str ) else : - _tt_n_ := _tt_n_ + 1 ; - if known _tt_d_[_tt_n_] : + mfun_tt_n := mfun_tt_n + 1 ; + if known mfun_tt_d[mfun_tt_n] : image ( addto currentpicture doublepath unitsquare - xscaled _tt_w_[_tt_n_] - yscaled (_tt_h_[_tt_n_] + _tt_d_[_tt_n_]) - withprescript "tx_number=" & decimal _tt_n_ + 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 ; - ) shifted (0,-_tt_d_[_tt_n_]) + ) shifted (0,-mfun_tt_d[mfun_tt_n]) else : image ( addto currentpicture doublepath unitsquare ; @@ -153,119 +155,116 @@ enddef ; % More text -pair laboff.d, laboff.dlft, laboff.drt ; % new positional suffixes -pair laboff.origin, laboff.raw ; % graph mess - -laboff.d := laboff ; labxf.d := labxf ; labyf.d := labyf ; -laboff.dlft := laboff.lft ; labxf.dlft := labxf.lft ; labyf.dlft := labyf.lft ; -laboff.drt := laboff.rt ; labxf.drt := labxf.rt ; labyf.drt := labyf.rt ; - -labtype := 0 ; labtype.lft := 1 ; labtype.rt := 2 ; -labtype.bot := 3 ; labtype.top := 4 ; labtype.ulft := 5 ; -labtype.urt := 6 ; labtype.llft := 7 ; labtype.lrt := 8 ; -labtype.d := 10 ; labtype.dlft := 11 ; labtype.drt := 12 ; -labtype.origin := 0 ; labtype.raw := 0 ; - -% laboff.origin = (infinity,infinity) ; labxf.origin := 0 ; labyf.origin := 0 ; -% laboff.raw = (infinity,infinity) ; labxf.raw := 0 ; labyf.raw := 0 ; - -% todo: thelabel.origin("xxxx",origin) (overflows) - -laboff.origin = (0,0) ; labxf.origin := 0 ; labyf.origin := 0 ; -laboff.raw = (0,0) ; labxf.raw := 0 ; labyf.raw := 0 ; - -pair laboff.l ; laboff.l = laboff.lft ; -pair laboff.r ; laboff.r = laboff.rt ; -pair laboff.b ; laboff.b = laboff.bot ; -pair laboff.t ; laboff.t = laboff.top ; -pair laboff.l_t ; laboff.l_t = laboff.ulft ; -pair laboff.r_t ; laboff.r_t = laboff.urt ; -pair laboff.l_b ; laboff.l_b = laboff.llft ; -pair laboff.r_b ; laboff.r_b = laboff.lrt ; -pair laboff.t_l ; laboff.t_l = laboff.ulft ; -pair laboff.t_r ; laboff.t_r = laboff.urt ; -pair laboff.b_l ; laboff.b_l = laboff.llft ; -pair laboff.b_r ; laboff.b_r = laboff.lrt ; - -numeric labxf.l ; labxf.l = labxf.lft ; -numeric labxf.r ; labxf.r = labxf.rt ; -numeric labxf.b ; labxf.b = labxf.bot ; -numeric labxf.t ; labxf.t = labxf.top ; -numeric labxf.l_t ; labxf.l_t = labxf.ulft ; -numeric labxf.r_t ; labxf.r_t = labxf.urt ; -numeric labxf.l_b ; labxf.l_b = labxf.llft ; -numeric labxf.r_b ; labxf.r_b = labxf.lrt ; -numeric labxf.t_l ; labxf.t_l = labxf.ulft ; -numeric labxf.t_r ; labxf.t_r = labxf.urt ; -numeric labxf.b_l ; labxf.b_l = labxf.llft ; -numeric labxf.b_r ; labxf.b_r = labxf.lrt ; - -numeric labyf.l ; labyf.l = labyf.lft ; -numeric labyf.r ; labyf.r = labyf.rt ; -numeric labyf.b ; labyf.b = labyf.bot ; -numeric labyf.t ; labyf.t = labyf.top ; -numeric labyf.l_t ; labyf.l_t = labyf.ulft ; -numeric labyf.r_t ; labyf.r_t = labyf.urt ; -numeric labyf.l_b ; labyf.l_b = labyf.llft ; -numeric labyf.r_b ; labyf.r_b = labyf.lrt ; -numeric labyf.t_l ; labyf.t_l = labyf.ulft ; -numeric labyf.t_r ; labyf.t_r = labyf.urt ; -numeric labyf.b_l ; labyf.b_l = labyf.llft ; -numeric labyf.b_r ; labyf.b_r = labyf.lrt ; - -numeric labtype.l ; labtype.l = labtype.lft ; -numeric labtype.r ; labtype.r = labtype.rt ; -numeric labtype.b ; labtype.b = labtype.bot ; -numeric labtype.t ; labtype.t = labtype.top ; -numeric labtype.l_t ; labtype.l_t = labtype.ulft ; -numeric labtype.r_t ; labtype.r_t = labtype.urt ; -numeric labtype.l_b ; labtype.l_b = labtype.llft ; -numeric labtype.r_b ; labtype.r_b = labtype.lrt ; -numeric labtype.t_l ; labtype.t_l = labtype.ulft ; -numeric labtype.t_r ; labtype.t_r = labtype.urt ; -numeric labtype.b_l ; labtype.b_l = labtype.llft ; -numeric labtype.b_r ; labtype.b_r = labtype.lrt ; - -vardef thetextext@#(expr p,z) = % adapted copy of thelabel@ +defaultfont := "Mono" ; % was cmr10, could be lmmono10-regular, but is fed into context anyway + +pair mfun_laboff ; mfun_laboff := (0,0) ; +pair mfun_laboff.lft ; mfun_laboff.lft := (-1,0) ; +pair mfun_laboff.rt ; mfun_laboff.rt := (1,0) ; +pair mfun_laboff.bot ; mfun_laboff.bot := (0,-1) ; +pair mfun_laboff.top ; mfun_laboff.top := (0,1) ; +pair mfun_laboff.ulft ; mfun_laboff.ulft := (-.7,.7) ; +pair mfun_laboff.urt ; mfun_laboff.urt := (.7,.7) ; +pair mfun_laboff.llft ; mfun_laboff.llft := -(.7,.7) ; +pair mfun_laboff.lrt ; mfun_laboff.lrt := (.7,-.7) ; + +pair mfun_laboff.d ; mfun_laboff.d := mfun_laboff ; +pair mfun_laboff.dlft ; mfun_laboff.dlft := mfun_laboff.lft ; +pair mfun_laboff.drt ; mfun_laboff.drt := mfun_laboff.rt ; +pair mfun_laboff.origin ; mfun_laboff.origin := origin ; +pair mfun_laboff.raw ; mfun_laboff.raw := origin ; + +pair mfun_laboff.l ; mfun_laboff.l := mfun_laboff.lft ; +pair mfun_laboff.r ; mfun_laboff.r := mfun_laboff.rt ; +pair mfun_laboff.b ; mfun_laboff.b := mfun_laboff.bot ; +pair mfun_laboff.t ; mfun_laboff.t := mfun_laboff.top ; +pair mfun_laboff.l_t ; mfun_laboff.l_t := mfun_laboff.ulft ; +pair mfun_laboff.r_t ; mfun_laboff.r_t := mfun_laboff.urt ; +pair mfun_laboff.l_b ; mfun_laboff.l_b := mfun_laboff.llft ; +pair mfun_laboff.r_b ; mfun_laboff.r_b := mfun_laboff.lrt ; +pair mfun_laboff.t_l ; mfun_laboff.t_l := mfun_laboff.ulft ; +pair mfun_laboff.t_r ; mfun_laboff.t_r := mfun_laboff.urt ; +pair mfun_laboff.b_l ; mfun_laboff.b_l := mfun_laboff.llft ; +pair mfun_laboff.b_r ; mfun_laboff.b_r := mfun_laboff.lrt ; + +mfun_labxf := 0.5 ; +mfun_labxf.lft := mfun_labxf.l := 1 ; +mfun_labxf.rt := mfun_labxf.r := 0 ; +mfun_labxf.bot := mfun_labxf.b := 0.5 ; +mfun_labxf.top := mfun_labxf.t := 0.5 ; +mfun_labxf.ulft := mfun_labxf.l_t := mfun_labxf.t_l := 1 ; +mfun_labxf.urt := mfun_labxf.r_t := mfun_labxf.t_r := 0 ; +mfun_labxf.llft := mfun_labxf.l_b := mfun_labxf.b_l := 1 ; +mfun_labxf.lrt := mfun_labxf.r_b := mfun_labxf.b_r := 0 ; + +mfun_labxf.d := mfun_labxf ; +mfun_labxf.dlft := mfun_labxf.lft ; +mfun_labxf.drt := mfun_labxf.rt ; +mfun_labxf.origin := 0 ; +mfun_labxf.raw := 0 ; + +mfun_labyf := 0.5 ; +mfun_labyf.lft := mfun_labyf.l := 0.5 ; +mfun_labyf.rt := mfun_labyf.r := 0.5 ; +mfun_labyf.bot := mfun_labyf.b := 1 ; +mfun_labyf.top := mfun_labyf.t := 0 ; +mfun_labyf.ulft := mfun_labyf.l_t := mfun_labyf.t_l := 0 ; +mfun_labyf.urt := mfun_labyf.r_t := mfun_labyf.t_r := 0 ; +mfun_labyf.llft := mfun_labyf.l_b := mfun_labyf.b_l := 1 ; +mfun_labyf.lrt := mfun_labyf.r_b := mfun_labyf.b_r := 1 ; + +mfun_labyf.d := mfun_labyf ; +mfun_labyf.dlft := mfun_labyf.lft ; +mfun_labyf.drt := mfun_labyf.rt ; +mfun_labyf.origin := 0 ; +mfun_labyf.raw := 0 ; + +mfun_labtype := 0 ; +mfun_labtype.lft := mfun_labtype.l := 1 ; +mfun_labtype.rt := mfun_labtype.r := 2 ; +mfun_labtype.bot := mfun_labtype.b := 3 ; +mfun_labtype.top := mfun_labtype.t := 4 ; +mfun_labtype.ulft := mfun_labtype.l_t := mfun_labtype.t_l := 5 ; +mfun_labtype.urt := mfun_labtype.r_t := mfun_labtype.t_r := 6 ; +mfun_labtype.llft := mfun_labtype.l_b := mfun_labtype.b_l := 7 ; +mfun_labtype.lrt := mfun_labtype.r_b := mfun_labtype.b_r := 8 ; +mfun_labtype.d := 10 ; +mfun_labtype.dlft := 11 ; +mfun_labtype.drt := 12 ; +mfun_labtype.origin := 0 ; +mfun_labtype.raw := 0 ; + +vardef thetextext@#(expr p,z) = + % interim labeloffset := textextoffset ; if string p : thetextext@#(rawtextext(p),z) else : p - if (labtype@# >= 10) : shifted (0,ypart center p) fi - shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) + if (mfun_labtype@# >= 10) : + shifted (0,ypart center p) + fi + shifted (z + textextoffset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p)) fi enddef ; -vardef textext@#(expr txt) = - interim labeloffset := textextoffset ; - if string txt : - thetextext@#(rawtextext(txt),origin) - else : - thetextext@#(txt,origin) - fi +vardef textext@#(expr p) = + thetextext@#(p,origin) enddef ; -% \starttext -% \startMPpage -% numeric value ; value = 123 ; -% label.lft(decimal value,origin) ; -% draw "oeps" infont defaultfont ; -% \stopMPpage -% \stoptext - -vardef thelabel@#(expr s, z) = - save p ; picture p ; - if picture s : - p = s ; +vardef thelabel@#(expr p,z) = + if string p : + thelabel@#(rawtextext("\definedfont[" & defaultfont & "]" & p) scaled defaultscale,z) else : - p = textext("\definedfont[" & defaultfont & "]" & s) scaled defaultscale ; - fi ; - p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) + p shifted (z + labeloffset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p)) + fi enddef; +def label = % takes two arguments, contrary to textext that takes one + draw thelabel +enddef ; + let normalinfont = infont ; -primarydef str infont name = % very naughty ! +primarydef str infont name = % nasty hack if name = "" : textext(str) else : @@ -346,72 +345,73 @@ def withlinearshade (expr a, b, ca, cb) = withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset) enddef ; -string _defined_cs_pre_[] ; numeric _defined_cs_ ; _defined_cs_:= 0 ; -string prescript_separator ; prescript_separator := char(13) ; +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) = - _defined_cs_ := _defined_cs_ + 1 ; - _defined_cs_pre_ [_defined_cs_] := "sh_type=circular" - & prescript_separator & "sh_domain=0 1" - & prescript_separator & "sh_factor=" & decimal shadefactor - & prescript_separator & "sh_color_a=" & colordecimals ca - & prescript_separator & "sh_color_b=" & colordecimals cb - & prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset) - & prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset) - & prescript_separator & "sh_radius_a=" & decimal ra - & prescript_separator & "sh_radius_b=" & decimal rb + 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 ; - _defined_cs_ + mfun_defined_cs enddef ; vardef define_linear_shade (expr a, b, ca, cb) = - _defined_cs_ := _defined_cs_ + 1 ; - _defined_cs_pre_ [_defined_cs_] := "sh_type=linear" - & prescript_separator & "sh_domain=0 1" - & prescript_separator & "sh_factor=" & decimal shadefactor - & prescript_separator & "sh_color_a=" & colordecimals ca - & prescript_separator & "sh_color_b=" & colordecimals cb - & prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset) - & prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset) + 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) ; - _defined_cs_ + mfun_defined_cs enddef ; primarydef p withshade sc = - p withprescript _defined_cs_pre_[sc] + p withprescript mfun_defined_cs_pre[sc] enddef ; vardef define_sampled_linear_shade(expr a,b,n)(text t) = - _defined_cs_ := _defined_cs_ + 1 ; - _defined_cs_pre_ [_defined_cs_] := "ssh_type=linear" - & prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) - & prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) - & prescript_separator & "ssh_nofcolors=" & decimal n - & prescript_separator & "ssh_domain=" & domstr - & prescript_separator & "ssh_extend=" & extstr - & prescript_separator & "ssh_colors=" & colstr - & prescript_separator & "ssh_bounds=" & bndstr - & prescript_separator & "ssh_ranges=" & ranstr + 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 ; - _defined_cs_ + mfun_defined_cs enddef ; vardef define_sampled_circular_shade(expr a,b,ra,rb,n)(text t) = - _defined_cs_ := _defined_cs_ + 1 ; - _defined_cs_pre_ [_defined_cs_] := "ssh_type=circular" - & prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset) - & prescript_separator & "ssh_radius_a=" & decimal ra - & prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset) - & prescript_separator & "ssh_radius_b=" & decimal rb - & prescript_separator & "ssh_nofcolors=" & decimal n - & prescript_separator & "ssh_domain=" & domstr - & prescript_separator & "ssh_extend=" & extstr - & prescript_separator & "ssh_colors=" & colstr - & prescript_separator & "ssh_bounds=" & bndstr - & prescript_separator & "ssh_ranges=" & ranstr + 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 ; - _defined_cs_ + mfun_defined_cs enddef ; % vardef predefined_linear_shade (expr p, n, ca, cb) = @@ -474,45 +474,12 @@ primarydef a shadedinto b = withprescript "sh_color_b=" & colordecimals b enddef ; -% END OF NEW - -% Graphic text (we will move code here) - -def graphictext primary t = - if _trial_run_ : - let dographictextindeed = nographictext ; - else : - let dographictextindeed = dographictext ; - fi - dographictextindeed(t) -enddef ; - -def dographictext (expr t) = - % withprescript "gt_stage=final" - begingroup ; - save figurepicture ; picture figurepicture ; - figurepicture := currentpicture ; currentpicture := nullpicture ; - currentgraphictext := currentgraphictext + 1 ; - dofinishgraphictext -enddef ; - -def nographictext (expr t) text rest = - draw unitsquare withprescript "gt_stage=trial" withpostscript t -enddef ; - -% def savegraphictext (expr str) = -% enddef ; - -% def erasegraphictextfile = -% enddef ; - % Layers def onlayer primary name = withprescript "la_name=" & name enddef ; - % Figures % def externalfigure primary filename = @@ -562,10 +529,10 @@ enddef ; extra_beginfig := extra_beginfig & "currentgraphictext := 0 ; " ; extra_endfig := extra_endfig & "finishsavingdata ; " ; -extra_endfig := extra_endfig & "resettextexts ; " ; +extra_endfig := extra_endfig & "mfun_reset_tex_texts ; " ; -boolean cmykcolors ; cmykcolors := true ; -boolean spotcolors ; spotcolors := true ; +boolean cmykcolors ; cmykcolors := true ; % are these still used? +boolean spotcolors ; spotcolors := true ; % are these still used? % Bonus @@ -594,7 +561,7 @@ enddef ; def withproperties expr p = if colormodel p = 3 : - withcolor graypart p + withcolor greypart p elseif colormodel p = 5 : withcolor (redpart p,greenpart p,bluepart p) elseif colormodel p = 7 : diff --git a/metapost/context/base/mp-page.mp b/metapost/context/base/mp-page.mpii index 0c2f41f03..52afacd74 100644 --- a/metapost/context/base/mp-page.mp +++ b/metapost/context/base/mp-page.mpii @@ -14,8 +14,7 @@ %D This module is rather preliminary and subjected to %D changes. -if unknown context_tool : input mp-tool ; fi ; -if known context_page : endinput ; fi ; +if known context_page : endinput ; fi ; boolean context_page ; context_page := true ; diff --git a/metapost/context/base/mp-page.mpiv b/metapost/context/base/mp-page.mpiv new file mode 100644 index 000000000..e9e0be5b0 --- /dev/null +++ b/metapost/context/base/mp-page.mpiv @@ -0,0 +1,666 @@ +%D \module +%D [ file=mp-page.mp, +%D version=1999.03.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=page enhancements, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is rather preliminary and subjected to +%D changes. + +if known context_page : endinput ; fi ; + +boolean context_page ; context_page := true ; + +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 ; + +def SaveTextAreas = + path SavedTextAreas [] ; + path SavedTextColumns[] ; + numeric NOfSavedTextAreas ; + numeric NOfSavedTextColumns ; + for i=1 upto NOfTextAreas : + SavedTextAreas[i] := TextAreas[i] ; + endfor ; + for i=1 upto NOfTextColumns : + SavedTextColumns[i] := TextColumns[i] ; + endfor ; + NOfSavedTextAreas := NOfTextAreas ; + NOfSavedTextColumns := NOfTextColumns ; +enddef ; + +def ResetTextAreas = + path TextAreas[], TextColumns[] ; + numeric NOfTextAreas ; NOfTextAreas := 0 ; + numeric NOfTextColumns ; NOfTextColumns := 0 ; + numeric nofmultipars ; nofmultipars := 0 ; + TextAreas[0] := TextColumns[0] := origin -- cycle ; +enddef ; + +ResetTextAreas ; SaveTextAreas ; ; + +def RegisterTextArea (expr x, y, w, h, d) = + begingroup ; + save p ; path p ; + p := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; + if NOfTextAreas>0 : + % if needed, concatenate areas + if (round(llcorner TextAreas[NOfTextAreas]) = round(ulcorner p)) and + (round(lrcorner TextAreas[NOfTextAreas]) = round(urcorner p)) : + p := + ulcorner TextAreas[NOfTextAreas] -- + urcorner TextAreas[NOfTextAreas] -- + lrcorner p -- + llcorner p -- cycle ; + else : + NOfTextAreas := NOfTextAreas + 1 ; + fi ; + else : + NOfTextAreas := NOfTextAreas + 1 ; + fi ; + TextAreas[NOfTextAreas] := p ; + if NOfTextColumns>0 : + if (round(xpart llcorner TextColumns[NOfTextColumns]) = round(xpart ulcorner p)) and + (round(xpart lrcorner TextColumns[NOfTextColumns]) = round(xpart urcorner p)) : + p := + ulcorner TextColumns[NOfTextColumns] -- + urcorner TextColumns[NOfTextColumns] -- + lrcorner p -- + llcorner p -- cycle ; + else : + NOfTextColumns := NOfTextColumns + 1 ; + fi ; + else : + NOfTextColumns := NOfTextColumns + 1 ; + fi ; + TextColumns[NOfTextColumns] := p ; + endgroup ; +enddef ; + +%D We store a local area in slot zero. + +def RegisterLocalTextArea (expr x, y, w, h, d) = + TextAreas[0] := TextColumns[0] := unitsquare xyscaled(w,h+d) shifted (x,y-d) ; +enddef ; + +def ResetLocalTextArea = + TextAreas[0] := TextColumns[0] := origin -- cycle ; +enddef ; + +ResetLocalTextArea ; + +vardef InsideTextArea (expr _i_, _xy_) = + (round(xpart _xy_) >= round(xpart llcorner TextAreas[_i_])) and + (round(xpart _xy_) <= round(xpart lrcorner TextAreas[_i_])) and + (round(ypart _xy_) >= round(ypart llcorner TextAreas[_i_])) and + (round(ypart _xy_) <= round(ypart urcorner TextAreas[_i_])) +enddef ; + +vardef InsideSavedTextArea (expr _i_, _xy_) = + (round(xpart _xy_) >= round(xpart llcorner SavedTextAreas[_i_])) and + (round(xpart _xy_) <= round(xpart lrcorner SavedTextAreas[_i_])) and + (round(ypart _xy_) >= round(ypart llcorner SavedTextAreas[_i_])) and + (round(ypart _xy_) <= round(ypart urcorner SavedTextAreas[_i_])) +enddef ; + +vardef InsideSomeTextArea (expr _xy_) = + save ok ; boolean ok ; ok := false ; + for i := 1 upto NOfTextAreas : + if InsideTextArea(i,_xy_) : + ok := true ; % we can move the exit here + fi ; + exitif ok ; + endfor ; + ok +enddef ; + +vardef InsideSomeSavedTextArea (expr _xy_) = + save ok ; boolean ok ; ok := false ; + for i := 1 upto NOfSavedTextAreas : + if InsideSavedTextArea(i,_xy_) : + ok := true ; + fi ; + exitif ok ; + endfor ; + ok +enddef ; + +vardef TextAreaX (expr x) = + numeric _TextAreaX_ ; _TextAreaX_ := 0 ; + for i := 1 upto NOfTextAreas : + if (round(x) >= round(xpart llcorner TextAreas[i])) and + (round(x) <= round(xpart lrcorner TextAreas[i])) : + _TextAreaX_ := xpart llcorner TextAreas[i] ; + fi ; + endfor ; + _TextAreaX_ +enddef ; + +vardef TextAreaY (expr y) = + numeric _TextAreaY_ ; _TextAreaY_ := 0 ; + for i := 1 upto NOfTextAreas : + if (round(y) >= round(ypart llcorner TextAreas[NOfTextAreas])) and + (round(y) <= round(ypart ulcorner TextAreas[NOfTextAreas])) : + _TextAreaY_ := ypart llcorner TextAreas[NOfTextAreas] ; + fi ; + endfor ; + _TextAreaY_ +enddef ; + +vardef TextAreaXY (expr x, y) = + pair _TextAreaXY_ ; _TextAreaXY_ := origin ; + for i := 1 upto NOfTextAreas : + if (round(x) >= round(xpart llcorner TextAreas[i])) and + (round(x) <= round(xpart lrcorner TextAreas[i])) and + (round(y) >= round(ypart llcorner TextAreas[i])) and + (round(y) <= round(ypart ulcorner TextAreas[i])) : + _TextAreaXY_ := llconer TextAreas[i] ; + fi ; + endfor ; + _TextAreaXY_ +enddef ; + +vardef TextAreaW (expr x) = + numeric _TextAreaW_ ; _TextAreaW_ := 0 ; + for i := 1 upto NOfTextAreas : + if (round(x) >= round(xpart llcorner TextAreas[i])) and + (round(x) <= round(xpart lrcorner TextAreas[i])) : + _TextAreaW_ := bbwidth(TextAreas[i]) ; + fi ; + endfor ; + _TextAreaW_ +enddef ; + +vardef TextAreaH (expr y) = + numeric _TextAreaH_ ; _TextAreaH_ := 0 ; + for i := 1 upto NOfTextAreas : + if (round(y) >= round(ypart llcorner TextAreas[i])) and + (round(y) <= round(ypart ulcorner TextAreas[i])) : + _TextAreaH_ := bbheight(TextAreas[i]) ; + fi ; + endfor ; + _TextAreaH_ +enddef ; + +vardef TextAreaWH (expr x, y) = + pair _TextAreaWH_ ; _TextAreaWH_ := origin ; + for i := 1 upto NOfTextAreas : + if (round(x) >= round(xpart llcorner TextAreas[i])) and + (round(x) <= round(xpart lrcorner TextAreas[i])) and + (round(y) >= round(ypart llcorner TextAreas[i])) and + (round(y) <= round(ypart ulcorner TextAreas[i])) : + _TextAreaWH_ := (bbwidth(TextAreas[i]),bbheight(TextAreas[i])) ; + fi ; + endfor ; + _TextAreaWH_ +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 ; + +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 [][] ; path Page ; +numeric HorPos ; numeric Hstep [] ; numeric Hsize [] ; +numeric VerPos ; numeric Vstep [] ; numeric Vsize [] ; + +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 ; + +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[] ; + + Vsize[Top] = TopHeight ; + Vsize[TopSeparator] = TopDistance ; + Vsize[Header] = HeaderHeight ; + Vsize[HeaderSeparator] = HeaderDistance ; + Vsize[Text] = TextHeight ; + Vsize[FooterSeparator] = FooterDistance ; + Vsize[Footer] = FooterHeight ; + Vsize[BottomSeparator] = BottomDistance ; + Vsize[Bottom] = BottomHeight ; + + Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ; + Vstep[TopSeparator] = PaperHeight-TopSpace ; + Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ; + Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ; + Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ; + Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ; + Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ; + Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ; + Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ; + + Hsize[LeftEdge] = LeftEdgeWidth ; + Hsize[LeftEdgeSeparator] = LeftEdgeDistance ; + Hsize[LeftMargin] = LeftMarginWidth ; + Hsize[LeftMarginSeparator] = LeftMarginDistance ; + Hsize[Text] = MakeupWidth ; + Hsize[RightMarginSeparator] = RightMarginDistance ; + Hsize[RightMargin] = RightMarginWidth ; + Hsize[RightEdgeSeparator] = RightEdgeDistance ; + Hsize[RightEdge] = RightEdgeWidth ; + + Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ; + Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ; + Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ; + Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ; + Hstep[Text] = BackSpace ; + Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ; + Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ; + Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ; + Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ; + + for VerPos=Top step 10 until Bottom: + for HorPos=LeftEdge step 1 until RightEdge: + Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ; + Area[VerPos][HorPos] := Area[HorPos][VerPos] ; + Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ; + Location[VerPos][HorPos] := Location[HorPos][VerPos] ; + Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ; + Field[VerPos][HorPos] := Field[HorPos][VerPos] ; + endfor ; + endfor ; + + Page := unitsquare xscaled PaperWidth yscaled PaperHeight ; + +enddef ; + +def BoundPageAreas = + + % pickup pencircle scaled 0pt ; + + bboxmargin := 0 ; setbounds currentpicture to Page ; + +enddef ; + +def StartPage = + + if PageStateAvailable : + LoadPageState ; + SwapPageState ; + fi ; + + SetPageAreas ; + BoundPageAreas ; + +enddef ; + +def StopPage = + + BoundPageAreas ; + +enddef ; + +def OverlayBox = + (unitsquare xyscaled (OverlayWidth,OverlayHeight)) +enddef ; + +% handy + +def innerenlarged = + hide(LoadPageState) + if OnRightPage : leftenlarged else : rightenlarged fi +enddef ; + +def outerenlarged = + hide(LoadPageState) + if OnRightPage : rightenlarged else : leftenlarged fi +enddef ; + +% obsolete + +def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ; +def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ; +def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ; +def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ; + +def Enlarged (expr p, d) = + (llEnlarged (p,d) -- + lrEnlarged (p,d) -- + urEnlarged (p,d) -- + ulEnlarged (p,d) -- cycle) +enddef ; + +% New: + +def position_anchor_bar(expr p_b_self, p_e_self, y_b_self, y_e_self, h_b_self, d_e_self, + distance, linewidth, linecolor) = + StartPage ; + path p ; p := + if p_b_self=p_e_self : + (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) -- + (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ; + elseif RealPageNumber=p_b_self : + (xpart ulcorner Field[Text][Text],y_b_self+h_b_self) -- + (llcorner Field[Text][Text]) ; + elseif RealPageNumber=p_e_self : + (ulcorner Field[Text][Text]) -- + (xpart llcorner Field[Text][Text],y_e_self-d_e_self) ; + else : + (ulcorner Field[Text][Text]) -- + (llcorner Field[Text][Text]) ; + fi ; + p := p shifted (-llcorner Field[Text][Text]-(distance,0)) ; + interim linecap := butt ; + draw p + withpen pencircle scaled linewidth + withcolor linecolor ; + StopPage ; +enddef ; + +% Crop stuff + +vardef crop_marks_lines (expr box, length, offset, nx, ny) = + save p ; picture p ; save w, h, x, y ; numeric w, h, x, y ; + p := image ( + x := if nx = 0 : 1 else : nx - 1 fi ; + y := if ny = 0 : 1 else : ny - 1 fi ; + w := bbwidth (box) / x ; + h := bbheight(box) / y ; + for i=0 upto y : + draw ((llcorner box) -- (llcorner box) shifted (-length,0)) shifted (-offset,i*h) ; + draw ((lrcorner box) -- (lrcorner box) shifted ( length,0)) shifted ( offset,i*h) ; + endfor ; + for i=0 upto x : + draw ((llcorner box) -- (llcorner box) shifted (0,-length)) shifted (i*w,-offset) ; + draw ((ulcorner box) -- (ulcorner box) shifted (0, length)) shifted (i*w, offset) ; + endfor ; + ) ; + setbounds p to box ; + p +enddef ; + +vardef crop_marks_cmyk = + save p ; picture p ; p := image ( + fill ulcircle scaled 12.5 withcolor (1,0,0,0) ; + fill urcircle scaled 12.5 withcolor (0,1,0,0) ; + fill lrcircle scaled 12.5 withcolor (0,0,1,0) ; + fill llcircle scaled 12.5 withcolor (0,0,0,1) ; + draw (-10,0) -- (10,0) ; + draw (0,-10) -- (0,10) ; + draw fullcircle scaled 12.5 ; + ) ; + setbounds p to fullsquare scaled 20 ; + p +enddef ; + +vardef crop_marks_gray = + save p ; picture p ; p := image ( + fill ulcircle scaled 12.5 withcolor (0.00) ; + fill urcircle scaled 12.5 withcolor (0.25) ; + fill lrcircle scaled 12.5 withcolor (0.50) ; + fill llcircle scaled 12.5 withcolor (0.75) ; + draw (-10,0) -- (10,0) ; + draw (0,-10) -- (0,10) ; + draw (-6,0) -- (6,0) withcolor white ; + draw (0,-6) -- (0,6) withcolor white ; + draw fullcircle scaled 12.5 ; + ) ; + setbounds p to fullsquare scaled 20 ; + p +enddef ; + +vardef crop_marks_cmykrgb = + save p ; picture p ; p := image ( + fill ulcircle scaled 15 withcolor (1,0,0) ; + fill urcircle scaled 15 withcolor (0,1,0) ; + fill lrcircle scaled 15 withcolor (0,0,1) ; + fill llcircle scaled 15 withcolor (.5,.5,.5) ; + fill ulcircle scaled 10 withcolor (1,0,0,0) ; + fill urcircle scaled 10 withcolor (0,1,0,0) ; + fill lrcircle scaled 10 withcolor (0,0,1,0) ; + fill llcircle scaled 10 withcolor (0,0,0,1) ; + draw (-10,0) -- (10,0) ; + draw (0,-10) -- (0,10) ; + draw fullcircle scaled 10 ; + draw fullcircle scaled 15 ; + ) ; + setbounds p to fullsquare scaled 20 ; + p +enddef ; + +vardef crop_color(expr c, h, w, dx, dy, ts) = + image ( + save p ; path p ; + for i=1 upto 6 : + p := fullsquare + xscaled w + yscaled h + shifted (dx,dy-i*h) ; + fill p + withcolor (crop_colors[i]*c) ; + draw textext("\format{'@0.2f'," & decimal crop_colors[i] & "}") + scaled ts + shifted center p withcolor white ; + endfor ; + ) +enddef ; + +vardef crop_gray(expr c, h, w, dx, dy, ts) = + image ( + save p ; path p ; + for i=.05 step .05 until 1 : + p := fullsquare + xscaled w + yscaled h + shifted (20*(i-1)*w+dx,dy) ; + fill p + withcolor (i*c) ; + draw textext("\format{'@0.2f'," & decimal i & "}") + scaled ts + shifted center p withcolor white ; + endfor ; + ) +enddef ; + +% draw crop_marks_cmyk shifted llcorner more ; +% draw crop_marks_cmyk shifted lrcorner more ; +% draw crop_marks_cmyk shifted ulcorner more ; +% draw crop_marks_cmyk shifted urcorner more ; + +def page_marks_add_color(expr width, height, length, offset) = % todo: namespace + + path page ; page := fullsquare xscaled width yscaled height ; + path more ; more := page enlarged (offset+length/2,offset+length/2) ; + + numeric crop_colors[] ; + crop_colors[1] := 1 ; + crop_colors[2] := 0.95 ; + crop_colors[3] := 0.75 ; + crop_colors[4] := 0.50 ; + crop_colors[5] := 0.25 ; + crop_colors[6] := 0.05 ; + + numeric h ; h := height / 20 ; + numeric w ; w := width / 20 ; + numeric d ; d := offset + length/2 ; + + draw crop_color((1,0,0,0),h,length,xpart ulcorner page - d, 10h,length/20) ; + draw crop_color((0,1,0,0),h,length,xpart ulcorner page - d,3.5h,length/20) ; + draw crop_color((0,0,1,0),h,length,xpart ulcorner page - d, -3h,length/20) ; + + draw crop_color((0,1,1,0),h,length,xpart urcorner page + d, 10h,length/20) ; + draw crop_color((1,0,1,0),h,length,xpart urcorner page + d,3.5h,length/20) ; + draw crop_color((1,1,0,0),h,length,xpart urcorner page + d, -3h,length/20) ; + + draw crop_gray((0,0,0,1),length, w,-xpart llcorner page,-ypart llcorner page + d ,w/20) ; + draw crop_gray((1,0,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d + 1length/3,w/20) ; + draw crop_gray((0,1,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 0length/3,w/20) ; + draw crop_gray((0,0,1,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 1length/3,w/20) ; + + setbounds currentpicture to page ; + +enddef ; + +def page_marks_add_marking(expr width, height, length, offset) = % todo: namespace + + path page ; page := fullsquare xscaled width yscaled height ; + path more ; more := page enlarged (offset+length/2,offset+length/2) ; + + draw crop_marks_gray shifted center(topboundary more) shifted (0, offset+length); + draw crop_marks_cmyk shifted center(bottomboundary more) shifted (0,-offset-length); + + setbounds currentpicture to page ; + +enddef ; + +def page_marks_add_lines(expr width, height, length, offset, nx, ny) = % todo: namespace + + path page ; page := fullsquare xscaled width yscaled height ; + path more ; more := page enlarged (offset+length/2,offset+length/2) ; + + draw crop_marks_lines(page,length,offset,nx,ny) ; + + setbounds currentpicture to page ; + +enddef ; + +def page_marks_add_number(expr width, height, length, offset, n) = % todo: namespace + + path page ; page := fullsquare xscaled width yscaled height ; + path more ; more := page enlarged (offset+length/2,offset+length/2) ; + + for s=llcorner more, lrcorner more, ulcorner more, urcorner more : + draw textext(decimal n) shifted s ; + endfor ; + + setbounds currentpicture to page ; + +enddef ; + +endinput ; diff --git a/metapost/context/base/mp-shap.mp b/metapost/context/base/mp-shap.mpii index 785231278..a551c4419 100644 --- a/metapost/context/base/mp-shap.mp +++ b/metapost/context/base/mp-shap.mpii @@ -11,8 +11,7 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_shap : endinput ; fi ; +if known context_shap : endinput ; fi ; boolean context_shap ; context_shap := true ; @@ -145,7 +144,7 @@ def some_shape (expr shape_type, shape_width, shape_height, shape_linewidth, sha endgroup ; enddef ; -vardef drawshape (expr t, p, lw, lc, fc) = +vardef drawpredefinedshape (expr t, p, lw, lc, fc) = save pp ; if t>1 : % normal shape path pp ; @@ -163,7 +162,7 @@ vardef drawshape (expr t, p, lw, lc, fc) = fi ; enddef ; -vardef drawline (expr t, p, lw, lc) = +vardef drawpredefinedline (expr t, p, lw, lc) = if (t>0) and (length(p)>1) : saveoptions ; drawoptions(withpen pencircle scaled lw withcolor lc) ; @@ -203,4 +202,7 @@ vardef drawline (expr t, p, lw, lc) = fi ; enddef ; +let drawshape = drawpredefinedshape ; +let drawline = drawpredefinedline ; + endinput ; diff --git a/metapost/context/base/mp-shap.mpiv b/metapost/context/base/mp-shap.mpiv new file mode 100644 index 000000000..a551c4419 --- /dev/null +++ b/metapost/context/base/mp-shap.mpiv @@ -0,0 +1,208 @@ +%D \module +%D [ file=mp-shap.mp, +%D version=2000.05.31, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=shapes, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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_shap : endinput ; fi ; + +boolean context_shap ; context_shap := true ; + +path predefined_shapes[] ; + +begingroup ; + +save xradius, yradius, xxradius, yyradius ; +save ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ; + +numeric xradius, yradius, xxradius, yyradius ; +pair ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ; + +xradius := .15 ; +yradius := .15 ; +xxradius := .10 ; +yyradius := .10 ; + +ll := llcorner (unitsquare shifted (-.5,-.5)) ; +lr := lrcorner (unitsquare shifted (-.5,-.5)) ; +ur := urcorner (unitsquare shifted (-.5,-.5)) ; +ul := ulcorner (unitsquare shifted (-.5,-.5)) ; + +llx := ll shifted (xradius,0) ; +lly := ll shifted (0,yradius) ; + +lrx := lr shifted (-xradius,0) ; +lry := lr shifted (0,yradius) ; + +urx := ur shifted (-xradius,0) ; +ury := ur shifted (0,-yradius) ; + +ulx := ul shifted (xradius,0) ; +uly := ul shifted (0,-yradius) ; + +llxx := ll shifted (xxradius,0) ; +llyy := ll shifted (0,yyradius) ; + +lrxx := lr shifted (-xxradius,0) ; +lryy := lr shifted (0,yyradius) ; + +urxx := ur shifted (-xxradius,0) ; +uryy := ur shifted (0,-yyradius) ; + +ulxx := ul shifted (xxradius,0) ; +ulyy := ul shifted (0,-yyradius) ; + +lc := ll shifted (0,.5) ; +rc := lr shifted (0,.5) ; +tc := ul shifted (.5,0) ; +bc := ll shifted (.5,0) ; + +predefined_shapes[ 0] := (origin--cycle) ; +predefined_shapes[ 5] := (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ; +predefined_shapes[ 6] := (ll--lrx{right}...rc...{left}urx--ul--cycle) ; +predefined_shapes[ 7] := (ll--lrx{right}...rc...{left}urx--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[ 8] := (lr--ury{up}...tc...{down}uly--ll--cycle) ; +predefined_shapes[ 9] := (lr--ury{up}...tc...{down}uly--ll--cycle) rotatedaround(origin,180) ; +predefined_shapes[10] := (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ; +predefined_shapes[11] := (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ; +predefined_shapes[12] := (ll--lrx--ur--ulx--cycle) ; +predefined_shapes[13] := (llx--lr--urx--ul--cycle) ; +predefined_shapes[14] := (lly--bc--lry--ury--tc--uly--cycle) ; +predefined_shapes[15] := (llx--lrx--rc--urx--ulx--lc--cycle) ; +predefined_shapes[16] := (ll--lrx--rc--urx--ul--cycle) ; +predefined_shapes[17] := (ll--lrx--rc--urx--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[18] := (lr--ury--tc--uly--ll--cycle) ; +predefined_shapes[19] := (lr--ury--tc--uly--ll--cycle) rotatedaround(origin,180) ; +predefined_shapes[20] := (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--lr--ur--urxx--lrxx--cycle) ; +predefined_shapes[21] := (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--ll--lr--lryy--llyy--cycle) ; +predefined_shapes[22] := (ll--lrx--lry--ur--ulx--uly--cycle) ; +predefined_shapes[23] := (llx--lr--ury--urx--ul--lly--cycle) ; +predefined_shapes[24] := (ll--lr--ur--ul--cycle) ; +predefined_shapes[25] := (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ; +predefined_shapes[26] := (ll--lrx--lry--ur--ul--cycle) ; +predefined_shapes[27] := (ll--lr--ury--urx--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[28] := (ll--lr--ury--urx--ul--cycle) ; +predefined_shapes[29] := (ll--lrx--lry--ur--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[30] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) rotated 45; +predefined_shapes[31] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) ; +predefined_shapes[32] := (ll{right}...{right}lry--ur--ul--ll--cycle) ; +predefined_shapes[33] := (ll{right}...{right}lry--ur--ul--ll--cycle--ul--ulx--ulx shifted(0,yyradius)--ur shifted(yyradius,yyradius)--lry shifted(yyradius,yyradius)--lry shifted(0,yyradius)--ur--ul--cycle ) ; +predefined_shapes[34] := (uly..tc..ury & ury..tc shifted (0,-2yradius)..uly & uly--lly & lly..bc..lry & lry--ury & ury..tc shifted (0,-2yradius)..uly & cycle ) ; +predefined_shapes[35] := (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ; +predefined_shapes[36] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) ; +predefined_shapes[37] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) rotatedaround(origin,180) ; +predefined_shapes[38] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) ; +predefined_shapes[39] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) rotatedaround(origin,180) ; +predefined_shapes[40] := (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ; +predefined_shapes[41] := (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ; +predefined_shapes[42] := (ll--lr--origin shifted (+epsilon,0)--ur--ul--origin shifted (-epsilon,0)--cycle) ; +predefined_shapes[43] := (ll--ul--origin shifted (0,+epsilon)--ur--lr--origin shifted (0,-epsilon)--cycle) ; +predefined_shapes[45] := (bc--rc--tc--lc--cycle) ; +predefined_shapes[46] := (ll--ul--rc--cycle) ; +predefined_shapes[47] := (ll--ul--rc--cycle) rotatedaround(origin,180) ; +predefined_shapes[48] := (ul--ur--bc--cycle) rotatedaround(origin,180) ; +predefined_shapes[49] := (ul--ur--bc--cycle) ; +predefined_shapes[56] := (ll--lry--ury--ul--cycle) ; +predefined_shapes[57] := (ll--lry--ury--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[58] := (ll--ulx--urx--lr--cycle) ; +predefined_shapes[59] := (ll--ulx--urx--lr--cycle) rotatedaround(origin,180); +predefined_shapes[66] := (rc--origin shifted ( epsilon,0) --cycle & rc--origin--cycle ) ; +predefined_shapes[67] := (lc--origin shifted (-epsilon,0) --cycle & lc--origin--cycle ) ; +predefined_shapes[68] := (tc--origin shifted (0, epsilon) --cycle & tc--origin--cycle ) ; +predefined_shapes[69] := (bc--origin shifted (0,-epsilon) --cycle & bc--origin--cycle ) ; +predefined_shapes[75] := (lly--lry--ury--uly--cycle) rotatedaround(origin,180) ; +predefined_shapes[76] := (ll--lr--ur--uly--cycle) rotatedaround(origin,180) ; +predefined_shapes[77] := (ll--lr--ury--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[78] := (lly--lr--ur--ul--cycle) rotatedaround(origin,180) ; +predefined_shapes[79] := (ll--lry--ur--ul--cycle) rotatedaround(origin,180) ; + +numeric predefined_shapes_xradius ; predefined_shapes_xradius := xradius ; +numeric predefined_shapes_yradius ; predefined_shapes_yradius := yradius ; +numeric predefined_shapes_xxradius ; predefined_shapes_xxradius := xxradius ; +numeric predefined_shapes_yyradius ; predefined_shapes_yyradius := yyradius ; + +endgroup ; + +vardef some_shape_path (expr type) = + if known predefined_shapes[type] : predefined_shapes[type] else : predefined_shapes[0] fi +enddef ; + +def some_shape (expr shape_type, shape_width, shape_height, shape_linewidth, shape_linecolor, shape_fillcolor) = + begingroup ; + save p ; path p ; + p := some_shape_path (shape_type) xscaled shape_width yscaled shape_height ; + pickup pencircle scaled shape_linewidth ; + fill p withcolor shape_fillcolor ; + draw p withcolor shape_linecolor ; + endgroup ; +enddef ; + +vardef drawpredefinedshape (expr t, p, lw, lc, fc) = + save pp ; + if t>1 : % normal shape + path pp ; + pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ; + fill pp withcolor fc ; + draw pp withpen pencircle scaled lw withcolor lc ; + elseif t=1 : % background only + path pp ; + pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ; + fill pp withcolor fc ; + else : % dimensions only + picture pp ; pp := nullpicture ; + setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ; + draw pp ; + fi ; +enddef ; + +vardef drawpredefinedline (expr t, p, lw, lc) = + if (t>0) and (length(p)>1) : + saveoptions ; + drawoptions(withpen pencircle scaled lw withcolor lc) ; + draw p ; + if t = 1 : + draw arrowheadonpath(p,1) ; + elseif t = 2 : + draw arrowheadonpath(reverse p,1) ; + elseif t = 3 : + for $ = p,reverse p : + draw arrowheadonpath($,1) ; + endfor ; + elseif t = 11 : + draw arrowheadonpath(p,1/2) ; + elseif t = 12 : + draw arrowheadonpath(reverse p,1/2) ; + elseif t = 13 : + for $=p,reverse p : + draw arrowheadonpath($,1) ; + endfor ; + for $=p,reverse p : + draw arrowheadonpath($,3/4) ; + endfor ; + elseif t = 21 : + for $=1/5,1/2,4/5 : + draw arrowheadonpath(p,$) ; + endfor ; + elseif t = 22 : + for $=1/5,1/2,4/5 : + draw arrowheadonpath(reverse p,$) ; + endfor ; + elseif t = 23 : + for $=p,reverse p : + draw arrowheadonpath($,1/4) ; + endfor ; + fi ; + fi ; +enddef ; + +let drawshape = drawpredefinedshape ; +let drawline = drawpredefinedline ; + +endinput ; diff --git a/metapost/context/base/mp-spec.mpii b/metapost/context/base/mp-spec.mpii index 123e75faa..25e435edb 100644 --- a/metapost/context/base/mp-spec.mpii +++ b/metapost/context/base/mp-spec.mpii @@ -47,9 +47,8 @@ %D for instance shading. More information can be found in %D type {supp-mpe.tex}. -if known mplib : endinput ; fi ; -if unknown context_tool : input mp-tool ; fi ; -if known context_spec : endinput ; fi ; +if known mplib : endinput ; fi ; +if known context_spec : endinput ; fi ; boolean context_spec ; context_spec := true ; diff --git a/metapost/context/base/mp-step.mpii b/metapost/context/base/mp-step.mpii index d602f7014..ad6f7bde0 100644 --- a/metapost/context/base/mp-step.mpii +++ b/metapost/context/base/mp-step.mpii @@ -11,8 +11,7 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_step : endinput ; fi ; +if known context_step : endinput ; fi ; boolean context_step ; context_step := true ; @@ -39,7 +38,7 @@ enddef ; def analyze_step_chart = numeric n[], l[][], r[][] ; pair p[] ; - n[t] := n[b] := 0 ; numeric tb ; + n[t] := n[b] := 0 ; numeric tb ; for i=1 upto nofcells : for nn = t, b : if bbwidth(cells[nn][i])>0 : n[nn] := n[nn] + 1 ; fi ; l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ; @@ -80,15 +79,15 @@ vardef get_step_chart_top_line (expr i, j) = p[3] := p[3] shifted (0,+line_v_offset) ; (p[1] {up} ... p[2] ... {down} p[3]) else : - origin - fi + origin + fi else : - origin - fi + origin + fi else : - origin - fi -enddef ; + origin + fi +enddef ; vardef get_step_chart_bot_line (expr i, j) = if bbwidth(cells[b][i])>0 : @@ -108,31 +107,31 @@ vardef get_step_chart_bot_line (expr i, j) = p[3] := p[3] shifted (0,-line_v_offset) ; (p[1] {down} ... p[2] ... {up} p[3]) else : - origin - fi + origin + fi else : - origin - fi + origin + fi else : - origin - fi + origin + fi enddef ; def end_step_chart = - for i=1 upto nofcells : for nn = t, b : - if bbwidth(cells[nn][i]) >0 : draw cells[nn][i] ; fi ; + for i=1 upto nofcells : for nn = t, b : + if bbwidth(cells[nn][i]) >0 : draw cells[nn][i] ; fi ; endfor ; endfor ; - for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b : + for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b : if known lines[nn][i][j] : if bbwidth(lines[nn][i][j])>0 : draw lines[nn][i][j] ; fi ; - fi ; + fi ; endfor ; endfor ; endfor ; for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b : if bbwidth(texts[nn][i][j])>0 : draw texts[nn][i][j] ; fi ; endfor ; endfor ; endfor ; enddef ; -%D Step tables. +%D Step tables. def begin_step_table = initialize_step_variables ; @@ -141,13 +140,13 @@ def begin_step_table = enddef ; def end_step_table = - for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 : - draw cells[i] ; + for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 : + draw cells[i] ; fi ; fi ; endfor ; - for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 : - draw lines[i] ; + for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 : + draw lines[i] ; fi ; fi ; endfor ; - for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 : + for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 : draw texts[i] ; fi ; fi ; endfor ; enddef ; diff --git a/metapost/context/base/mp-step.mpiv b/metapost/context/base/mp-step.mpiv index dbbc38231..21a20ce71 100644 --- a/metapost/context/base/mp-step.mpiv +++ b/metapost/context/base/mp-step.mpiv @@ -11,8 +11,9 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_cell : endinput ; fi ; +% step prefixes .. no save needed + +if known context_cell : endinput ; fi ; boolean context_cell ; context_cell := true ; diff --git a/metapost/context/base/mp-text.mp b/metapost/context/base/mp-text.mpii index 60e16c09b..67dff15f9 100644 --- a/metapost/context/base/mp-text.mp +++ b/metapost/context/base/mp-text.mpii @@ -13,8 +13,7 @@ %D Under construction. -if unknown context_tool : input mp-tool ; fi ; -if known context_text : endinput ; fi ; +if known context_text : endinput ; fi ; boolean context_text ; context_text := true ; diff --git a/metapost/context/base/mp-text.mpiv b/metapost/context/base/mp-text.mpiv new file mode 100644 index 000000000..c7bafeb8a --- /dev/null +++ b/metapost/context/base/mp-text.mpiv @@ -0,0 +1,163 @@ +%D \module +%D [ file=mp-text.mp, +%D version=2000.07.10, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=text support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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. + +%D This one is only used in metafun so it will become a module. + +if known context_text : endinput ; fi ; + +boolean context_text ; context_text := true ; + +def build_parshape (expr p, offset_or_path, dx, dy, baselineskip, strutheight, strutdepth, topskip) = + + if unknown trace_parshape : + boolean trace_parshape ; trace_parshape := false ; + fi ; + + begingroup ; + + save + q, l, r, line, tt, bb, + n, hsize, vsize, vvsize, voffset, hoffset, width, indent, + ll, lll, rr, rrr, cp, cq, t, b ; + + path + q, l, r, line, tt, bb ; + numeric + n, hsize, vsize, vvsize, voffset, hoffset, width[], indent[] ; + pair + ll, lll, rr, rrr, cp, cq, t, b ; + + n := 0 ; + cp := center p ; + + if path offset_or_path : + q := offset_or_path ; + cq := center q ; + voffset := dy ; + hoffset := dx ; + else : + q := p ; + cq := center q ; + hoffset := offset_or_path + dx ; + voffset := offset_or_path + dy ; + fi ; + + hsize := xpart lrcorner q - xpart llcorner q ; + vsize := ypart urcorner q - ypart lrcorner q ; + + q := p shifted - cp ; + + startsavingdata ; + + savedata "\global\parvoffset " & decimal voffset&"bp " ; + savedata "\global\parhoffset " & decimal hoffset&"bp " ; + savedata "\global\parwidth " & decimal hsize&"bp " ; + savedata "\global\parheight " & decimal vsize&"bp " ; + + if not path offset_or_path : + q := q xscaled ((hsize-2hoffset)/hsize) yscaled ((vsize-2voffset)/vsize) ; + fi ; + + hsize := xpart lrcorner q - xpart llcorner q ; + vsize := ypart urcorner q - ypart lrcorner q ; + + t := (ulcorner q -- urcorner q) intersection_point q ; + b := (llcorner q -- lrcorner q) intersection_point q ; + + if xpart directionpoint t of q < 0 : + q := reverse q ; + fi ; + + l := q cutbefore t ; + l := l if xpart point 0 of q < 0 : & q fi cutafter b ; + + r := q cutbefore b ; + r := r if xpart point 0 of q > 0 : & q fi cutafter t ; + + % tt := (ulcorner q -- urcorner q) shifted (0,-topskip) ; + % bb := (llcorner q -- lrcorner q) shifted (0,strutdepth) ; + + % l := l cutbefore (l intersection_point tt) ; + % l := l cutafter (l intersection_point bb) ; + % r := r cutbefore (r intersection_point bb) ; + % r := r cutafter (r intersection_point tt) ; + + if trace_parshape : + drawarrow p withpen pencircle scaled 2pt withcolor red ; + drawarrow l shifted cp withpen pencircle scaled 1pt withcolor green ; + drawarrow r shifted cp withpen pencircle scaled 1pt withcolor blue ; + fi ; + + vardef found_point (expr lin, pat, sig) = + pair a, b ; + a := pat intersection_point (lin shifted (0,strutheight)) ; + if intersection_found : + a := a shifted (0,-strutheight) ; + else : + a := pat intersection_point lin ; + fi ; + b := pat intersection_point (lin shifted (0,-strutdepth)) ; + if intersection_found : + if sig : + if xpart b > xpart a : a := b shifted (0,strutdepth) fi ; + else : + if xpart b < xpart a : a := b shifted (0,strutdepth) fi ; + fi ; + fi ; + a + enddef ; + + if (strutheight+strutdepth<baselineskip) : + vvsize := vsize ; + else : + vvsize := (vsize div baselineskip) * baselineskip ; + fi ; + + for i=topskip step baselineskip until vvsize : + + line := (ulcorner q -- urcorner q) shifted (0,-i-eps) ; + + ll := found_point(line,l,true ) ; + rr := found_point(line,r,false) ; + + if trace_parshape : + fill (ll--rr--rr shifted (0,strutheight)--ll shifted (0,strutheight)--cycle) shifted cp withcolor .5white ; + fill (ll--rr--rr shifted (0,-strutdepth)--ll shifted (0,-strutdepth)--cycle) shifted cp withcolor .7white ; + draw ll shifted cp withpen pencircle scaled 2pt ; + draw rr shifted cp withpen pencircle scaled 2pt ; + draw (ll--rr) shifted cp withpen pencircle scaled .5pt ; + fi ; + + n := n + 1 ; + indent[n] := abs(xpart ll - xpart llcorner q) ; + width[n] := abs(xpart rr - xpart ll) ; + + if (i=strutheight) and (width[n]<baselineskip) : + n := n - 1 ; + savedata "\global\chardef\parfirst=1 " ; + fi ; + + endfor ; + + savedata "\global\parlines " & decimal n ; + savedata "\global\partoks{ " ; + for i=1 upto n: + savedata decimal indent[i]&"bp " & decimal width[i]&"bp " ; + endfor ; + savedata "}" ; + + stopsavingdata ; + + endgroup ; + +enddef ; diff --git a/metapost/context/base/mp-tool.mp b/metapost/context/base/mp-tool.mpii index 1a758a963..7b46c4725 100644 --- a/metapost/context/base/mp-tool.mp +++ b/metapost/context/base/mp-tool.mpii @@ -85,10 +85,6 @@ mpprocset := 1 ; % % protect ; -%D A semicolor to be used in specials: ? ? ? - -string semicolor ; semicolor := char 59 ; - %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. @@ -96,8 +92,6 @@ string semicolor ; semicolor := char 59 ; % When somehow the first one gets no HiRes, then make sure % that the format matches the mem sizes in the config file. -% eerste " " er uit - string space ; space = char 32 ; vardef ddecimal primary p = diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv new file mode 100644 index 000000000..04d987c8d --- /dev/null +++ b/metapost/context/base/mp-tool.mpiv @@ -0,0 +1,2145 @@ +%D \module +%D [ file=mp-tool.mp, +%D version=1998.02.15, +%D title=\CONTEXT\ \METAPOST\ graphics, +%D subtitle=auxiliary macros, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%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_tool : endinput ; fi ; + +boolean context_tool ; context_tool := true ; + +let @## = @# ; + +%D New, version number testing: +%D +%D \starttyping +%D fill fullcircle scaled 2cm withcolor if mpversiongt("0.6") : red else : green fi ; +%D fill fullcircle scaled 1cm withcolor if mpversionlt(0.6) : blue else : white fi ; +%D \stoptyping + +if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ; + +% vardef mpversiongt(expr s) = +% scantokens (mpversion & " > " & if numeric s : decimal s else : s fi) +% enddef ; +% vardef mpversionlt(expr s) = +% scantokens (mpversion & " < " & if numeric s : decimal s else : s fi) +% enddef ; +% vardef mpversioneq(expr s) = +% scantokens (mpversion & " = " & if numeric s : decimal s else : s fi) +% enddef ; + +%D More interesting: +%D +%D \starttyping +%D fill fullcircle scaled 4cm withcolor if mpversiongt("0.6") : red else : green fi ; +%D fill fullcircle scaled 2cm withcolor if mpversionlt(0.6) : blue else : white fi ; +%D fill fullcircle scaled 1cm withcolor if mpversioncmp(0.6,">=") : yellow else : black fi ; +%D \stoptyping + +% no longer needed as we load runtime + +vardef mpversioncmp(expr s, c) = + scantokens (mpversion & c & if numeric s : decimal s else : s fi) +enddef ; + +vardef mpversionlt (expr s) = mpversioncmp(s, "<") enddef ; +vardef mpversioneq (expr s) = mpversioncmp(s, "=") enddef ; +vardef mpversiongt (expr s) = mpversioncmp(s, ">") enddef ; + +%D We always want \EPS\ conforming output, so we say: + +prologues := 1 ; +warningcheck := 0 ; +mpprocset := 1 ; + +%D Namespace handling: + +% let exclamationmark = ! ; +% let questionmark = ? ; +% +% def unprotect = +% let ! = relax ; +% let ? = relax ; +% enddef ; +% +% def protect = +% let ! = exclamationmark ; +% let ? = questionmark ; +% enddef ; +% +% unprotect ; +% +% mp!some!module = 10 ; show mp!some!module ; show somemodule ; +% +% protect ; + +string space ; space := char 32 ; +string CRLF ; CRLF := char 10 & char 13 ; + +vardef ddecimal primary p = + decimal xpart p & " " & decimal ypart p +enddef ; + +%D Colors: + +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_ ; + forsuffixes i=v : + _p_ := image(draw origin withcolor c ;) ; % intercept pre and postscripts + if (colormodel _p_ = cmykcolormodel) : + cmykcolor i ; + elseif (colormodel _p_ = rgbcolormodel) : + rgbcolor i ; + else : + greycolor i ; + fi ; + endfor ; +enddef ; + +%D Also handy (when we flush colors): + +vardef dddecimal primary 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 +enddef ; + +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 ; + +%D We have standardized data file names: + +def job_name = + jobname +enddef ; + +def data_mpd_file = + job_name & "-mp.mpd" +enddef ; + +%D Because \METAPOST\ has a hard coded limit of 4~datafiles, +%D we need some trickery when we have multiple files. + +if unknown collapse_data : + boolean collapse_data ; + collapse_data := false ; +fi ; + +boolean savingdata ; savingdata := false ; +boolean savingdatadone ; savingdatadone := false ; + +def savedata expr txt = + 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 ; +enddef ; + +def stopsavingdata = + if collapse_data : + write "}%" to data_mpd_file ; + fi ; + savingdata := false ; +enddef ; + +def finishsavingdata = + if savingdatadone : + write EOF to data_mpd_file ; + savingdatadone := false ; + fi ; +enddef ; + +%D Instead of a keystroke eating save and allocation +%D sequence, you can use the \citeer {new} alternatives to +%D save and allocate in one command. + +def newcolor text v = forsuffixes i=v : save i ; color i ; endfor ; enddef ; +def newnumeric text v = forsuffixes i=v : save i ; numeric i ; endfor ; enddef ; +def newboolean text v = forsuffixes i=v : save i ; boolean i ; endfor ; enddef ; +def newtransform text v = forsuffixes i=v : save i ; transform i ; endfor ; enddef ; +def newpath text v = forsuffixes i=v : save i ; path i ; endfor ; enddef ; +def newpicture text v = forsuffixes i=v : save i ; picture i ; endfor ; enddef ; +def newstring text v = forsuffixes i=v : save i ; string i ; endfor ; enddef ; +def newpair text v = forsuffixes i=v : save i ; pair i ; endfor ; enddef ; + +%D Sometimes we don't want parts of the graphics add to the +%D bounding box. One way of doing this is to save the bounding +%D box, draw the graphics that may not count, and restore the +%D bounding box. +%D +%D \starttypen +%D push_boundingbox currentpicture; +%D pop_boundingbox currentpicture; +%D \stoptypen +%D +%D The bounding box can be called with: +%D +%D \starttypen +%D boundingbox currentpicture +%D inner_boundingbox currentpicture +%D outer_boundingbox currentpicture +%D \stoptypen +%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 set_outer_boundingbox currentpicture; +%D \stoptypen +%D +%D Its counterpart is: +%D +%D \starttypen +%D set_inner_boundingbox p +%D \stoptypen + +path mfun_boundingbox_stack ; +numeric mfun_boundingbox_stack_depth ; + +mfun_boundingbox_stack_depth := 0 ; + +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 +enddef; + +vardef innerboundingbox primary p = + top rt llcorner p -- + top lft lrcorner p -- + bot lft urcorner p -- + bot rt ulcorner p -- cycle +enddef; + +vardef outerboundingbox primary p = + bot lft llcorner p -- + bot rt lrcorner p -- + top rt urcorner p -- + top lft ulcorner p -- cycle +enddef; + +def inner_boundingbox = innerboundingbox enddef ; +def outer_boundingbox = outerboundingbox enddef ; + +vardef set_inner_boundingbox text q = % obsolete + setbounds q to innerboundingbox q; +enddef; + +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 ; + +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 ; + +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 ; + +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 invsin primary x = (asin(x))/radian enddef ; +vardef invcos primary x = (acos(x))/radian 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 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 +%D first macro divides the sides into n equal parts. The +%D first argument specifies the way the lines are drawn, while +%D the second argument identifier the way the shape is to be +%D drawn. +%D +%D \starttypen +%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 +%D The a (or angle) alternative supports arbitrary angles and +%D is therefore more versatile. +%D +%D \starttypen +%D stripe_path_a +%D (withpen pencircle scaled 2 withcolor red) +%D (draw) +%D fullcircle xscaled 100 yscaled 40 withcolor blue; +%D \stoptypen +%D +%D The first alternative obeys: + +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: + +% to be redone: use image + +stripe_gap := 5; +stripe_angle := 45; + +def stripe_path_n (text s_spec) (text s_draw) expr 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 ; + +def stripe_path_a (text s_spec) (text s_draw) expr 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; + +%D A few normalizing macros: + +primarydef p xsized w = + (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) +enddef ; + +primarydef p xysized s = + 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 +enddef ; + +let sized = xysized ; + +def xscale_currentpicture(expr w) = % obsolete + currentpicture := currentpicture xsized w ; +enddef; + +def yscale_currentpicture(expr h) = % obsolete + currentpicture := currentpicture ysized h ; +enddef; + +def xyscale_currentpicture(expr w, h) = % obsolete + currentpicture := currentpicture xysized (w,h) ; +enddef; + +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 +%D is located in the first quadrant. Now guess what kind of +%D path fullsquare and unitcircle do return. + +path fullsquare, unitcircle ; + +fullsquare := unitsquare shifted - center unitsquare ; +unitcircle := fullcircle shifted urcorner fullcircle ; + +%D Some more paths: + +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 ; + +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 ; + +path urtriangle, ultriangle, lltriangle, lrtriangle ; + +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 ; +fulldiamond := unitdiamond shifted - center unitdiamond ; + +%D More robust: + +% let normalscaled = scaled ; +% let normalxscaled = xscaled ; +% let normalyscaled = yscaled ; +% +% def scaled expr s = normalscaled (s) enddef ; +% def xscaled expr s = normalxscaled (s) enddef ; +% def yscaled expr s = normalyscaled (s) enddef ; + +%D Shorter + +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 Some personal code that might move to another module + +def set_grid(expr w, h, nx, ny) = + 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 ; +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 +enddef ; + +%D usage: \type{innerpath peepholed outerpath}. +%D +%D beginfig(1); +%D def fullsquare = (unitsquare shifted -center unitsquare) enddef ; +%D fill (fullsquare scaled 200) withcolor red ; +%D path p ; p := (fullcircle scaled 100) ; bboxmargin := 0 ; +%D fill p peepholed bbox p ; +%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 + else : + llcorner q -- lrcorner q -- urcorner q -- ulcorner q -- + reverse p -- ulcorner q -- cycle + fi + fi + endgroup +enddef ; + +boolean intersection_found ; + +secondarydef p intersection_point q = + begingroup + save x_, y_ ; + (x_,y_) = p intersectiontimes q ; + if x_<0 : + intersection_found := false ; + center p % origin + else : + intersection_found := true ; + .5[point x_ of p, point y_ of q] + fi + 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 +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 +enddef ; + +%D Some colors. + +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 ; + +%D Well, this is the dangerous and naive version: + +def drawfill text 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 ; + mfun_do_drawfill +enddef ; + +def mfun_do_drawfill text t = + draw _c_ t ; + fill _c_ t ; +enddef; + +def undrawfill expr c = + drawfill c withcolor background % rather useless +enddef ; + +%D Moved from mp-char.mp + +vardef paired primary d = + if pair d : d else : (d,d) fi +enddef ; + +vardef tripled primary d = + if color d : d else : (d,d,d) fi +enddef ; + +% maybe secondaries: + +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 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 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 = ( + if pair p : + 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 + fi +) enddef ; + +%D Also handy (math ladders): + +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) + endfor +enddef ; + +%D Saves typing: + +% vardef bottomboundary primary p = (llcorner p -- lrcorner p) enddef ; +% vardef rightboundary primary p = (lrcorner p -- urcorner p) 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 ; + +%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 ; + +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 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 = ( + 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 : + p + uniformdeviate s + fi +) enddef ; + +%D Not perfect (alternative for interpath) + +vardef interpolated(expr s, p, q) = + 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 paralleled d = ( + p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p) +) 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 +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 +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 +enddef ; + +%D Rather fundamental. + +% not yet ok + +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 ; +vardef rightpath expr p = leftrightpath(p,false) enddef ; + +%D Drawoptions + +def saveoptions = + save _op_ ; def _op_ = enddef ; +enddef ; + +%D Tracing. (not yet in lexer) + +let normaldraw = draw ; +let normalfill = fill ; + +% bugged in mplib so ... + +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 ; +def drawlabeloptions (text t) = def _lab_opt_ = t enddef ; enddef ; +def draworiginoptions (text t) = def _ori_opt_ = t enddef ; enddef ; +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) ; +enddef ; + +resetdrawoptions ; + +%D Path. + +def drawpath expr p = + normaldraw p _pth_opt_ +enddef ; + +%D Arrow. + +vardef drawarrowpath expr p = + save autoarrows ; boolean autoarrows ; autoarrows := true ; + drawarrow p _pth_opt_ +enddef ; + +def midarrowhead expr 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 +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_ +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 do_drawpoints 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 ; +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 ; +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 ; +enddef; + +%D Bounding box. + +def drawboundingbox expr p = + normaldraw boundingbox p _bnd_opt_ +enddef ; + +%D Origin. + +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 ; +enddef; + +%D Axis. + +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 ; + +% 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 ; +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 ; +enddef ; + +def do_drawticks 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 ; +enddef ; + +%D Tracing. + +def visualizeddraw expr c = + 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 +enddef ; + +def do_visualizeddraw text t = + 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_ ; +enddef ; + +def visualizepaths = + let fill = visualizedfill ; + let draw = visualizeddraw ; +enddef ; + +def naturalizepaths = + let fill = normalfill ; + let draw = normaldraw ; +enddef ; + +extra_endfig := extra_endfig & " naturalizepaths ; " ; + +%D Also handy: + +extra_beginfig := extra_beginfig & " truecorners := 0 ; " ; % restores +extra_beginfig := extra_beginfig & " miterlimit := 10 ; " ; % restores +extra_beginfig := extra_beginfig & " linejoin := rounded ; " ; % restores +extra_beginfig := extra_beginfig & " linecap := rounded ; " ; % restores + +%D Normally, arrowheads don't scale well. So we provide a +%D hack. + +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)) ; +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) +enddef ; + +%D The next two macros are adapted versions of plain +%D \METAPOST\ definitions. + +def _finarr text t = + if autoarrows : set_ahlength (t) fi ; + draw _apth t ; + filldraw 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 ; + +%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) +enddef ; + +def rightarrow (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ; +def leftarrow (expr pat,tim,len) = pointarrow(pat,tim,len,+len) enddef ; +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 drawdot point .5 along somepath ; +%D drawdot point 3cm on somepath ; +%D \stoptypen +%D +%D The number denotes a percentage (fraction). + +primarydef pct along pat = % also negative + (arctime (pct * (arclength pat)) of pat) of pat +enddef ; + +primarydef len on pat = + (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat +enddef ; + +% this cuts of a piece from both ends + +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 +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 ; + +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 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) ; +enddef ; + +vardef freedotlabel (expr str, loc, ori) = + interim linecap:=rounded ; + draw loc withpen pencircle scaled freedotlabelsize ; + draw thefreelabel(str,loc,ori) ; +enddef ; + +%D \starttypen +%D drawarrow anglebetween(line_a,line_b,somelabel) ; +%D \stoptypen + +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 ; + 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 mfun_current_picture_stack[] ; +numeric mfun_current_picture_depth ; + +mfun_current_picture_depth := 0 ; + +def pushcurrentpicture = + 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 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) ; + +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) ; + + transform t ; t := identity rotatedaround(origin,120) ; + + r := fullcircle rotated 90 scaled radius shifted (0,radius/4) rotatedaround(origin,135) ; + + 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 ; + + w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ; + + 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 ; + + for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ; + + currentpicture := currentpicture xsized size ; + + 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)) +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 ; + ) + fi +enddef ; + +vardef inverted primary p = + p uncolored white +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 +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 ; + ) + fi +enddef ; + +% yes or no: "text" infont "cmr12" at 24pt ; + +% let normalinfont = infont ; +% +% numeric lastfontsize ; lastfontsize = fontsize defaultfont ; +% +% def infont primary name = % no vardef, no expr +% hide(lastfontsize := fontsize name) % no ; +% normalinfont name +% enddef ; +% +% def scaledat expr size = +% scaled (size/lastfontsize) +% enddef ; +% +% let at = scaledat ; + +% like decimal + +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 +enddef ; + +primarydef p enlonged len = + begingroup + if pair p : + save q ; path q ; q := origin -- p ; + save al ; al := arclength(q) ; + if al > 0 : + point 1 of (q stretched ((al+len)/al)) + else : + p + fi + else : + save al ; al := arclength(p) ; + if al > 0 : + p stretched ((al+len)/al) + else : + p + fi + fi + endgroup +enddef ; + +% path p ; p := (0,0) -- (10cm,5cm) ; +% drawarrow p withcolor red ; +% drawarrow p shortened 1cm withcolor green ; + +primarydef p shortened d = + reverse ( ( reverse (p enlonged -d) ) enlonged -d ) +enddef ; + +% yes or no, untested -) + +def xshifted expr dx = shifted(dx,0) enddef ; +def yshifted expr dy = shifted(0,dy) enddef ; + +% also handy + +% right: str = readfrom ("abc" & ".def" ) ; +% wrong: str = readfrom "abc" & ".def" ; + +% Every 62th read fails so we need to try again! + +% def readfile (expr name) = +% if (readfrom (name) <> EOF) : +% scantokens("input " & name & ";") ; +% elseif (readfrom (name) <> EOF) : +% scantokens("input " & name & ";") ; +% fi ; +% closefrom (name) ; +% enddef ; +% +% this sometimes fails on the elseif, so : +% + +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 ; +enddef ; + +% permits redefinition of end in macro + +inner end ; + +% this will be redone (when needed) using scripts and backend handling + +let normalwithcolor = withcolor ; + +def remapcolors = + def withcolor primary c = normalwithcolor remappedcolor(c) enddef ; +enddef ; + +def normalcolors = + let withcolor = normalwithcolor ; +enddef ; + +def resetcolormap = + color color_map[][][] ; + normalcolors ; +enddef ; + +resetcolormap ; + +def r_color primary c = redpart c enddef ; +def g_color primary c = greenpart c enddef ; +def b_color primary c = bluepart c enddef ; + +def remapcolor(expr old, new) = + color_map[redpart old][greenpart old][bluepart old] := new ; +enddef ; + +def remappedcolor(expr c) = + if known color_map[redpart c][greenpart c][bluepart c] : + color_map[redpart c][greenpart c][bluepart c] + else : + c + fi +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 ; + +% primarydef p recolored t = repathed(0,p) t enddef ; +% primarydef p refilled t = repathed(1,p) t enddef ; +% primarydef p redrawn t = repathed(2,p) t enddef ; +% primarydef p retexted t = repathed(3,p) t enddef ; +% primarydef p untexted t = repathed(4,p) t enddef ; + +color refillbackground ; refillbackground := (1,1,1) ; + +def restroke suffix p = p := repathed (21,p) enddef ; % keep attributes +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 ; + fi ; + endfor ; + setbounds _p_ to _b_ ; + _p_ + endgroup +enddef ; + +% After a question of Denis on how to erase a z variable, Jacko +% suggested to assign whatever to x and y. So a clearz +% variable can be defined as: +% +% vardef clearz@# = +% x@# := whatever ; +% y@# := whatever ; +% enddef ; +% +% but Jacko suggested a redefinition of clearxy: +% +% def clearxy text s = +% clearxy_index_:=0; +% for $:=s: +% clearxy_index_:=clearxy_index_+1; endfor; +% if clearxy_index_=0: +% save x,y; +% else: +% forsuffixes $:=s: x$:=whatever; y$:=whatever; endfor; +% fi +% 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 +enddef ; + +% so now we can say: clearxy ; as well as clearxy 1, 2, 3 ; + +% show x0 ; z0 = (10,10) ; +% show x0 ; x0 := whatever ; y0 := whatever ; +% show x0 ; z0 = (20,20) ; +% show x0 ; clearxy 0 ; +% 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) +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) +enddef ; + +% cmyk color support + +% vardef cmyk(expr c,m,y,k) = % elsewhere +% (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 +% 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 +% 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 +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 ; + fi ; + fi ; +enddef ; + +% result from metafont discussion list (denisr/boguslawj) + +def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ; +def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ; + +% not perfect, but useful since it removes redundant points. + +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 ; + _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 + else : + p + fi +enddef ; + +vardef simplified expr p = ( + reverse mfun_straightened(+1,mfun_straightened(+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) -- +% (4cm,1cm) -- (4cm,2cm) -- (4cm,2.5cm) -- (4cm,3cm) -- +% (3cm,3cm) -- (2cm,3cm) -- (1cm,3cm) -- (-1cm,3cm) -- +% .5[(-1cm,3cm),(1cm,1cm)] -- (1cm,1cm) -- cycle ; +% +% p := unitcircle scaled 4cm ; +% +% drawpath p ; drawpoints p ; drawpointlabels p ; +% p := p shifted (4cm,0) ; p := straightened p ; +% drawpath p ; drawpoints p ; drawpointlabels p ; +% p := p shifted (4cm,0) ; p := straightened p ; +% drawpath p ; drawpoints p ; drawpointlabels p ; + +% new + +path originpath ; originpath := origin -- cycle ; + +vardef unitvector primary z = + if abs z = abs origin : z else : z/abs z fi +enddef; + +% also new + +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 +enddef ; + +% handy + +def withgray primary 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 ; + +% an improved plain mp macro + +vardef center primary p = + 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 +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 + 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 ; +enddef ; + +% makes a (line) into an infinite one (handy for calculating +% intersection points + +vardef infinite expr 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) +enddef ; + +% obscure macros: create var from string and replace - and : +% (needed for process color id's) .. will go away + +string mfun_clean_ascii[] ; + +def register_dirty_chars(expr str) = + for i = 0 upto length(str)-1 : + 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 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 ; +enddef ; + +vardef setunstringed (expr s, v) = + scantokens(cleanstring(s)) := v ; +enddef ; + +vardef getunstringed (expr s) = + scantokens(cleanstring(s)) +enddef ; + +vardef unstringed (expr s) = + 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) = % will move + begingroup + save defaultfont, defaultscale, size ; + string defaultfont ; defaultfont := "cmtt10"; % i.e. infofont + numeric defaultscale ; defaultscale := 8pt / fontsize defaultfont; + 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 ; + endfor ; + for x=MinX upto MaxX: + label.bot(decimal x, (x*DeltaX,-size)) ; + endfor ; + for y=MinY upto MaxY: + label.lft(decimal y, (-size,y*DeltaY)) ; + endfor ; + endgroup +enddef; + +% new, handy for: +% +% \startuseMPgraphic{map}{n} +% \includeMPgraphic{map:germany} ; +% c_phantom (\MPvar{n}<1) ( +% fill map_germany withcolor \MPcolor{lightgray} ; +% draw map_germany withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ; +% ) ; +% \includeMPgraphic{map:austria} ; +% c_phantom (\MPvar{n}<2) ( +% fill map_austria withcolor \MPcolor{lightgray} ; +% draw map_austria withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ; +% ) ; +% c_phantom (\MPvar{n}<3) ( +% \includeMPgraphic{map:swiss} ; +% fill map_swiss withcolor \MPcolor{lightgray} ; +% draw map_swiss withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ; +% ) ; +% c_phantom (\MPvar{n}<4) ( +% \includeMPgraphic{map:luxembourg} ; +% fill map_luxembourg withcolor \MPcolor{lightgray} ; +% draw map_luxembourg withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ; +% ) ; +% \stopuseMPgraphic +% +% \useMPgraphic{map}{n=3} + +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 ; +enddef ; + +%D Handy: + +def break = + exitif true fi ; +enddef ; + +%D New too: + +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 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 +enddef ; + +% done + +endinput ; diff --git a/metapost/context/base/mp-txts.mp b/metapost/context/base/mp-txts.mpii index f208c7149..d3d25293d 100644 --- a/metapost/context/base/mp-txts.mp +++ b/metapost/context/base/mp-txts.mpii @@ -11,8 +11,7 @@ %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. -if unknown context_tool : input mp-tool ; fi ; -if known context_txts : endinput ; fi ; +if known context_txts : endinput ; fi ; boolean context_txts ; context_txts := true ; |