diff options
115 files changed, 3434 insertions, 2134 deletions
diff --git a/doc/context/presentations/context/2020/context-2020-luametatex.tex b/doc/context/presentations/context/2020/context-2020-luametatex.tex index 10b57660e..ae2b72713 100644 --- a/doc/context/presentations/context/2020/context-2020-luametatex.tex +++ b/doc/context/presentations/context/2020/context-2020-luametatex.tex @@ -526,4 +526,6 @@ documents that come with the distribution. \stopitemize +\stoptitle + \stopdocument diff --git a/doc/context/sources/general/manuals/luametafun/luametafun.tex b/doc/context/sources/general/manuals/luametafun/luametafun.tex index 785fd03df..a90e265f1 100644 --- a/doc/context/sources/general/manuals/luametafun/luametafun.tex +++ b/doc/context/sources/general/manuals/luametafun/luametafun.tex @@ -36,6 +36,7 @@ \component luametafun-fonts \component luametafun-color \component luametafun-groups + \component luametafun-extensions \component luametafun-interface \stopbodymatter diff --git a/doc/context/sources/general/manuals/luametatex/luametatex.tex b/doc/context/sources/general/manuals/luametatex/luametatex.tex index bd4029a57..3c02391ce 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex.tex @@ -55,6 +55,10 @@ % rpi 64 : 26.0 (overclocked) % amd 10 fitlet : 28.2 +% 20210812 : 298 pages +% +% mingw : 9.7 + % But speed can differ a bit per compilation (upto .5 seconds maybe due to how % compiled code is organized which might influence caching. Who knows ... (or % cares). For instance at 20200407 I measured 10.9 seconds after some new low level @@ -63,7 +67,8 @@ % took 10.5 seconds, that is, we were at exactly 24 pages per second but after % switching to gcc9 it dropped again. In december 2020, with IPO enabled I crossed % the 26 pps barrier and went below 10 seconds but that was also after some further -% cleanup in \LMTX. +% cleanup in \LMTX. Mid August 2021 I measured over 30 pps but not all is due to +% the engine I guess. % msvc 1899k (2% slower than mingw) % msvc /GL 2297k (similar to mingw) diff --git a/metapost/context/base/mpxl/mp-apos.mpxl b/metapost/context/base/mpxl/mp-apos.mpxl index 65d3e86fb..3070d3a8a 100644 --- a/metapost/context/base/mpxl/mp-apos.mpxl +++ b/metapost/context/base/mpxl/mp-apos.mpxl @@ -179,16 +179,17 @@ newscriptindex mfid_getmultipars ; mfid_getmultipars := scriptindex "getmultipar def getposboxes (expr tags, anchor) = runscript mfid_getposboxes tags anchor ; enddef ; def getmultipars(expr tags, anchor) = runscript mfid_getmultipars tags anchor ; enddef ; -newscriptindex mfid_getpospage ; mfid_getpospage := scriptindex "getpospage" ; vardef getpospage (expr n) = runscript mfid_getpospage n enddef ; -newscriptindex mfid_getposparagraph ; mfid_getposparagraph := scriptindex "getposparagraph" ; vardef getposparagraph (expr n) = runscript mfid_getposparagraph n enddef ; -newscriptindex mfid_getposcolumn ; mfid_getposcolumn := scriptindex "getposcolumn" ; vardef getposcolumn (expr n) = runscript mfid_getposcolumn n enddef ; -newscriptindex mfid_getposregion ; mfid_getposregion := scriptindex "getposregion" ; vardef getposregion (expr n) = runscript mfid_getposregion n enddef ; +newscriptindex mfid_getpospage ; mfid_getpospage := scriptindex "getpospage" ; vardef getpospage (expr n) = runscript mfid_getpospage n enddef ; +newscriptindex mfid_getposparagraph ; mfid_getposparagraph := scriptindex "getposparagraph" ; vardef getposparagraph(expr n) = runscript mfid_getposparagraph n enddef ; +newscriptindex mfid_getposcolumn ; mfid_getposcolumn := scriptindex "getposcolumn" ; vardef getposcolumn (expr n) = runscript mfid_getposcolumn n enddef ; +newscriptindex mfid_getposregion ; mfid_getposregion := scriptindex "getposregion" ; vardef getposregion (expr n) = runscript mfid_getposregion n enddef ; -newscriptindex mfid_getposx ; mfid_getposx := scriptindex "getposx" ; vardef getposx (expr n) = runscript mfid_getposx n enddef ; -newscriptindex mfid_getposy ; mfid_getposy := scriptindex "getposy" ; vardef getposy (expr n) = runscript mfid_getposy n enddef ; -newscriptindex mfid_getposwidth ; mfid_getposwidth := scriptindex "getposwidth" ; vardef getposwidth (expr n) = runscript mfid_getposwidth n enddef ; -newscriptindex mfid_getposheight ; mfid_getposheight := scriptindex "getposheight" ; vardef getposheight (expr n) = runscript mfid_getposheight n enddef ; -newscriptindex mfid_getposdepth ; mfid_getposdepth := scriptindex "getposdepth" ; vardef getposdepth (expr n) = runscript mfid_getposdepth n enddef ; +newscriptindex mfid_getposx ; mfid_getposx := scriptindex "getposx" ; vardef getposx(expr n) = runscript mfid_getposx n enddef ; +newscriptindex mfid_getposy ; mfid_getposy := scriptindex "getposy" ; vardef getposy(expr n) = runscript mfid_getposy n enddef ; + +newscriptindex mfid_getposwidth ; mfid_getposwidth := scriptindex "getposwidth" ; vardef getposwidth (expr n) = runscript mfid_getposwidth n enddef ; +newscriptindex mfid_getposheight ; mfid_getposheight := scriptindex "getposheight" ; vardef getposheight(expr n) = runscript mfid_getposheight n enddef ; +newscriptindex mfid_getposdepth ; mfid_getposdepth := scriptindex "getposdepth" ; vardef getposdepth (expr n) = runscript mfid_getposdepth n enddef ; newscriptindex mfid_getposleftskip ; mfid_getposleftskip := scriptindex "getposleftskip" ; vardef getposleftskip (expr n) = runscript mfid_getposleftskip n enddef ; newscriptindex mfid_getposrightskip ; mfid_getposrightskip := scriptindex "getposrightskip" ; vardef getposrightskip (expr n) = runscript mfid_getposrightskip n enddef ; @@ -203,9 +204,15 @@ newscriptindex mfid_getposlowerleft ; mfid_getposlowerleft := scriptindex "get newscriptindex mfid_getposupperright ; mfid_getposupperright := scriptindex "getposupperright" ; vardef getposupperright(expr n) = runscript mfid_getposupperright n enddef ; newscriptindex mfid_getposlowerright ; mfid_getposlowerright := scriptindex "getposlowerright" ; vardef getposlowerright(expr n) = runscript mfid_getposlowerright n enddef ; +newscriptindex mfid_getposllx ; mfid_getposllx := scriptindex "getposllx" ; vardef getposllx(expr n) = runscript mfid_getposllx n enddef ; +newscriptindex mfid_getposlly ; mfid_getposlly := scriptindex "getposlly" ; vardef getposlly(expr n) = runscript mfid_getposlly n enddef ; +newscriptindex mfid_getposurx ; mfid_getposurx := scriptindex "getposurx" ; vardef getposurx(expr n) = runscript mfid_getposurx n enddef ; +newscriptindex mfid_getposury ; mfid_getposury := scriptindex "getposury" ; vardef getposury(expr n) = runscript mfid_getposury n enddef ; + permanent getposboxes, getmultipars, getpospage, getposparagraph, getposcolumn, getposregion, getposx, getposy, getposwidth, getposheight, getposdepth, getposleftskip, getposrightskip, getposhsize, getposparindent, getposhangindent, getposhangafter, - getposxy, getposupperleft, getposlowerleft, getposupperright, getposlowerright ; + getposxy, getposupperleft, getposlowerleft, getposupperright, getposlowerright, + getposllx, getposlly, getposurx, getposury ; diff --git a/metapost/context/base/mpxl/mp-luas.mpxl b/metapost/context/base/mpxl/mp-luas.mpxl index 00e7876a8..24a2fc8fe 100644 --- a/metapost/context/base/mpxl/mp-luas.mpxl +++ b/metapost/context/base/mpxl/mp-luas.mpxl @@ -138,18 +138,30 @@ permanent resolvedcolor ; % Modes: -vardef texmode (expr s) = lua.mp("mode", s) enddef ; -vardef systemmode(expr s) = lua.mp("systemmode",s) enddef ; +newscriptindex mfid_mode ; mfid_mode := scriptindex "mode" ; +newscriptindex mfid_systemmode ; mfid_systemmode := scriptindex "systemmode" ; + +vardef texmode (expr s) = runscript mfid_mode s enddef ; +vardef systemmode (expr s) = runscript mfid_systemmode s enddef ; + +% let processingmode = systemmode ; permanent texmode, systemmode ; % A few helpers -vardef isarray suffix a = lua.mp.isarray (str a) enddef ; -vardef prefix suffix a = lua.mp.prefix (str a) enddef ; -vardef dimension suffix a = lua.mp.dimension(str a) enddef ; +newscriptindex mfid_isarray ; mfid_isarray := scriptindex "isarray" ; +newscriptindex mfid_prefix ; mfid_prefix := scriptindex "prefix" ; +newscriptindex mfid_dimension ; mfid_dimension := scriptindex "dimension" ; +newscriptindex mfid_isobject ; mfid_isobject := scriptindex "isobject" ; + +vardef isarray suffix a = runscript mfid_isarray (str a) enddef ; +vardef prefix suffix a = runscript mfid_prefix (str a) enddef ; +vardef dimension suffix a = runscript mfid_dimension(str a) enddef ; -permanent isarray, prefix, dimension ; +vardef isobject expr p = if picture p : runscript mfid_isobject prescriptpart p else : false fi enddef ; + +permanent isarray, prefix, dimension, isobject ; % More access @@ -175,17 +187,31 @@ permanent setmacro, setdimen, setcount, settoks, setglobalmacro, setglobaldimen, setglobalcount, setglobaltoks ; -% todo: mfid_ - -vardef positionpath (expr name) = lua.mp.positionpath (name) enddef ; -vardef positioncurve (expr name) = lua.mp.positioncurve (name) enddef ; -vardef positionxy (expr name) = lua.mp.positionxy (name) enddef ; -vardef positionpxy (expr name) = lua.mp.positionpxy (name) enddef ; -vardef positionwhd (expr name) = lua.mp.positionwhd (name) enddef ; -vardef positionpage (expr name) = lua.mp.positionpage (name) enddef ; -vardef positionregion(expr name) = lua.mp.positionregion(name) enddef ; -vardef positionbox (expr name) = lua.mp.positionbox (name) enddef ; -vardef positionanchor = lua.mp.positionanchor() enddef ; +newscriptindex mfid_positionpath ; mfid_positionpath := scriptindex("positionpath") ; +newscriptindex mfid_positioncurve ; mfid_positioncurve := scriptindex("positioncurve") ; +newscriptindex mfid_positionxy ; mfid_positionxy := scriptindex("positionxy") ; +newscriptindex mfid_positionx ; mfid_positionx := scriptindex("positionx") ; +newscriptindex mfid_positiony ; mfid_positiony := scriptindex("positiony") ; +newscriptindex mfid_positionpar ; mfid_positionpar := scriptindex("positionpar") ; +newscriptindex mfid_positionwhd ; mfid_positionwhd := scriptindex("positionwhd") ; +newscriptindex mfid_positionpage ; mfid_positionpage := scriptindex("positionpage") ; +newscriptindex mfid_positionregion ; mfid_positionregion := scriptindex("positionregion") ; +newscriptindex mfid_positionbox ; mfid_positionbox := scriptindex("positionbox") ; +newscriptindex mfid_positionanchor ; mfid_positionanchor := scriptindex("positionanchor") ; + +vardef positionpath (expr name) = runscript mfid_positionpath name enddef ; +vardef positioncurve (expr name) = runscript mfid_positioncurve name enddef ; +vardef positionxy (expr name) = runscript mfid_positionxy name enddef ; +vardef positionx (expr name) = runscript mfid_positionx name enddef ; +vardef positiony (expr name) = runscript mfid_positiony name enddef ; +vardef positionpar (expr name) = runscript mfid_positionpar name enddef ; +vardef positionwhd (expr name) = runscript mfid_positionwhd name enddef ; +vardef positionpage (expr name) = runscript mfid_positionpage name enddef ; +vardef positioncolumn (expr name) = runscript mfid_positioncolumn name enddef ; +vardef positionparagraph(expr name) = runscript mfid_positionparagraph name enddef ; +vardef positionregion (expr name) = runscript mfid_positionregion name enddef ; +vardef positionbox (expr name) = runscript mfid_positionbox name enddef ; +vardef positionanchor = runscript mfid_positionanchor enddef ; vardef positioninregion = currentpicture := currentpicture shifted - positionxy(positionanchor) ; @@ -195,8 +221,9 @@ vardef positionatanchor(expr name) = currentpicture := currentpicture shifted - positionxy(name) ; enddef ; -permanent positionpath, positioncurve, positionxy, positionpxy, positionwhd, positionpage, - positionregion, positionbox, positionanchor, positioninregion, positionatanchor ; +permanent positionpath, positioncurve, positionxy, positionwhd, + positionpage, positionregion, positioncolumn, positionparagraph, + positionbox, positionanchor, positioninregion, positionatanchor ; let wdpart = redpart ; let htpart = greenpart ; @@ -204,8 +231,8 @@ let dppart = bluepart ; permanent wdpart, htpart, dppart; -vardef texvar(expr name) = lua.mp.texvar(name) enddef ; -vardef texstr(expr name) = lua.mp.texstr(name) enddef ; +newscriptindex mfid_texvar ; mfid_texvar := scriptindex "texvar" ; vardef texvar(expr s) = runscript mfid_texvar s enddef ; +newscriptindex mfid_texstr ; mfid_texstr := scriptindex "texstr" ; vardef texstr(expr s) = runscript mfid_texstr s enddef ; newscriptindex mfid_path_lengthof ; mfid_path_lengthof := scriptindex "pathlengthof" ; newscriptindex mfid_path_pointof ; mfid_path_pointof := scriptindex "pathpointof" ; diff --git a/metapost/context/base/mpxl/mp-mlib.mpxl b/metapost/context/base/mpxl/mp-mlib.mpxl index 35854a987..65146081e 100644 --- a/metapost/context/base/mpxl/mp-mlib.mpxl +++ b/metapost/context/base/mpxl/mp-mlib.mpxl @@ -17,19 +17,6 @@ newinternal boolean metafun_loaded_mlib ; metafun_loaded_mlib := true ; immutabl % numeric LUATEXFUNCTIONALITY ; LUATEXFUNCTIONALITY := runscript("mp.print(LUATEXFUNCTIONALITY or (status and status.development_id) or 6346)") ; -%D Objects: - -vardef isobject expr p = - if picture p : - % lua.mp.isobject(prescriptpart p) - runscript("mp.isobject(" & prescriptpart p & ")") - else : - false - fi -enddef ; - -permanent isobject ; - %D Color and transparency %D %D Separable: @@ -146,12 +133,11 @@ newinternal textextoffset ; textextoffset := 0 ; permanent textextoffset ; -%%%%%%% mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space) -color mfun_tt_b ; -numeric mfun_tt_n ; mfun_tt_n := 0 ; -picture mfun_tt_p ; mfun_tt_p := nullpicture ; -picture mfun_tt_o ; mfun_tt_o := nullpicture ; -picture mfun_tt_c ; mfun_tt_c := nullpicture ; +rgbcolor mfun_tt_r ; +numeric mfun_tt_n ; mfun_tt_n := 0 ; +picture mfun_tt_p ; mfun_tt_p := nullpicture ; +picture mfun_tt_o ; mfun_tt_o := nullpicture ; +picture mfun_tt_c ; mfun_tt_c := nullpicture ; if unknown mfun_trial_run : boolean mfun_trial_run ; @@ -213,8 +199,9 @@ immutable inicatcoderegime, texcatcoderegime, luacatcoderegime, notcatcoderegime permanent catcoderegime ; -newscriptindex mfid_sometextext ; mfid_sometextext := scriptindex "sometextext" ; -newscriptindex mfid_madetextext ; mfid_madetextext := scriptindex "madetextext" ; +newscriptindex mfid_sometextext ; mfid_sometextext := scriptindex "sometextext" ; +newscriptindex mfid_madetextext ; mfid_madetextext := scriptindex "madetextext" ; +newscriptindex mfid_boxdimensions ; mfid_boxdimensions := scriptindex "boxdimensions" ; vardef rawtextext(expr s) = if s = "" : @@ -254,6 +241,10 @@ vardef rawmadetext = mfun_tt_c enddef ; +% \setbox\scratchbox\hbox{!!!!!!!!!!!!!} +% \putboxincache{one}{a}\scratchbox +% \startMPcode draw rawtexbox("one","a") ; \stopMPcode + vardef validtexbox(expr category, name) = if category == "" : false @@ -269,11 +260,12 @@ enddef ; vardef rawtexbox(expr category, name) = mfun_tt_c := nullpicture ; if validtexbox(category,name) : - mfun_tt_b := lua.mp.mf_tb_dimensions(category, name) ; + % mfun_tt_r := lua.mp.mf_tb_dimensions(category, name) ; + mfun_tt_r := runscript mfid_boxdimensions category name ; addto mfun_tt_c doublepath unitsquare - xscaled wdpart mfun_tt_b - yscaled (htpart mfun_tt_b + dppart mfun_tt_b) - shifted (0,- dppart mfun_tt_b) + xscaled wdpart mfun_tt_r + yscaled (htpart mfun_tt_r + dppart mfun_tt_r) + shifted (0,- dppart mfun_tt_r) withprescript "mf_object=box" withprescript "bx_category=" & if numeric category : decimal fi category withprescript "bx_name=" & if numeric name : decimal fi name ; @@ -1671,102 +1663,20 @@ permanent tostring, topair, quote, quotation ; % but running lua is fast enough so we can gain on string construction in metapost % which is also not that efficient. -vardef mfun_key_to_lua(expr k) = - if numeric k : decimal k else : "'" & k & "'" fi -enddef ; - -vardef mfun_point_to_lua(expr k,p,i) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",{" & - decimal xpart (point i of p) & "," & - decimal ypart (point i of p) & "," & - decimal xpart (precontrol i of p) & "," & - decimal ypart (precontrol i of p) & "," & - decimal xpart (postcontrol i of p) & "," & - decimal ypart (postcontrol i of p) - & "})" ) ; -enddef ; - -vardef mfun_transform_to_lua(expr k,t) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",{" & - decimal xxpart t & "," & % rx - decimal xypart t & "," & % sx - decimal yxpart t & "," & % sy - decimal yypart t & "," & % ry - decimal xpart t & "," & % tx - decimal ypart t % ty - & "})" ) ; -enddef ; - -vardef mfun_numeric_to_lua(expr k,n) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & "," & decimal n & ")" ) ; -enddef ; - -vardef mfun_pair_to_lua(expr k,p) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",{" & - decimal xpart p & "," & - decimal ypart p - & "})" ) ; -enddef ; - -vardef mfun_rgbcolor_to_lua(expr k,c) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",{" & - decimal redpart c & "," & - decimal greenpart c & "," & - decimal bluepart c - & "})" ) ; -enddef ; - -vardef mfun_cmykcolor_to_lua(expr k,c) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",{" & - decimal cyanpart c & "," & - decimal magentapart c & "," & - decimal yellowpart c & "," & - decimal blackpart c - & "})" ) ; -enddef ; - -vardef mfun_path_to_lua(expr k,p) = - runscript("metapost.pushvariable(" & mfun_key_to_lua(k) & ")") ; - for i=0 upto length(p) : - mfun_point_to_lua(i+1,p,i) ; - endfor ; - runscript("metapost.popvariable()") ; -enddef ; - -vardef mfun_boolean_to_lua(expr k,b) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & if b : ",true)" else : ",false)" fi ) ; -enddef ; - -vardef mfun_string_to_lua(expr k,s) = - runscript( "metapost.setvariable(" & mfun_key_to_lua(k) & ",[==[" & s & "]==])" ) ; -enddef ; +newscriptindex mfid_passvariable ; mfid_passvariable := scriptindex("passvariable") ; +newscriptindex mfid_pushvariable ; mfid_pushvariable := scriptindex("pushvariable") ; +newscriptindex mfid_popvariable ; mfid_popvariable := scriptindex("popvariable") ; -def passvariable(expr key, value) = - if numeric value : mfun_numeric_to_lua (key,value) ; - elseif pair value : mfun_pair_to_lua (key,value) ; - elseif string value : mfun_string_to_lua (key,value) ; - elseif boolean value : mfun_boolean_to_lua (key,value) ; - elseif path value : mfun_path_to_lua (key,value) ; - elseif rgbcolor value : mfun_rgbcolor_to_lua (key,value) ; - elseif cmykcolor value : mfun_cmykcolor_to_lua(key,value) ; - elseif transform value : mfun_transform_to_lua(key,value) ; - fi ; -enddef ; +def passvariable (expr key, value) = runscript mfid_passvariable key value ; enddef ; +def startpassingvariable(expr key) = runscript mfid_pushvariable key ; enddef ; +def stoppassingvariable = runscript mfid_popvariable ; enddef ; def passarrayvariable(expr key)(suffix values)(expr first, last, stp) = - runscript("metapost.pushvariable(" & mfun_key_to_lua(key) & ")") ; + startpassingvariable(key) ; for i=first step stp until last : passvariable(i, values[i]) ; endfor - runscript("metapost.popvariable()") ; -enddef ; - -def startpassingvariable(expr k) = - runscript("metapost.pushvariable(" & mfun_key_to_lua(k) & ")") ; -enddef ; - -def stoppassingvariable = - runscript("metapost.popvariable()") ; + stoppassingvariable ; enddef ; permanent passvariable, passarrayvariable, startpassingvariable, stoppassingvariable ; @@ -1844,7 +1754,6 @@ permanent format, formatted ; % def strfmt = format enddef ; % old % def varfmt = formatted enddef ; % old - % def fmttext = lua.mp.formatted enddef ; % new @@ -1894,6 +1803,18 @@ permanent comment, report ; % todo: use mfid_* cum suis +newscriptindex mfid_hash_new ; mfid_hash_new := scriptindex("lmt_hash_new") ; +newscriptindex mfid_hash_dispose ; mfid_hash_dispose := scriptindex("lmt_hash_dispose") ; +newscriptindex mfid_hash_in ; mfid_hash_in := scriptindex("lmt_hash_in") ; +newscriptindex mfid_hash_from ; mfid_hash_from := scriptindex("lmt_hash_from") ; +newscriptindex mfid_hash_to ; mfid_hash_to := scriptindex("lmt_hash_to") ; + +def newhash = runscript mfid_hash_new enddef ; +def disposehash (expr n) = runscript mfid_hash_dispose n enddef ; +def inhash (expr n, key) = runscript mfid_hash_in n key enddef ; +def fromhash (expr n, key) = runscript mfid_hash_from n key enddef ; +def tohash (expr n, key, value) = runscript mfid_hash_to n key value enddef ; + vardef uniquelist(suffix list) = % this can be optimized by passing all values at once and returning % a result but for now this is ok .. we need an undef foo @@ -1905,20 +1826,20 @@ vardef uniquelist(suffix list) = i := 1 ; j := 0 ; fi ; - h := lua.mp.newhash() ; + h := runscript mfid_hash_new ; forever : exitif unknown list[i] ; - if not lua.mp.inhash(h,list[i]) : + if not (runscript mfid_hash_in h list[i]) : j := j + 1 ; list[j] := list[i] ; - lua.mp.tohash(h,list[i]) ; + runscript mfid_hash_to h list[i] ; fi ; i := i + 1 ; endfor ; for n = j+1 step 1 until i-1 : dispose(list[n]) endfor ; - lua.mp.disposehash(h) ; + runscript mfid_hash_dispose h ; enddef ; permanent uniquelist ; diff --git a/metapost/context/base/mpxl/mp-xbox.mpxl b/metapost/context/base/mpxl/mp-xbox.mpxl index 2b8b94c27..08589cb93 100644 --- a/metapost/context/base/mpxl/mp-xbox.mpxl +++ b/metapost/context/base/mpxl/mp-xbox.mpxl @@ -5,6 +5,14 @@ % copyright : Public domain % patched : Hans Hagen % +% author : Karl Berry +% version : $Id: rboxes.mp,v 1.2 2004/09/19 21:47:11 karl Exp $ +% copyright : Public domain +% patched : Hans Hagen +% +% The code is the same but I've added a boxes_ namespace for some so that we don't +% clash with metafun. + % The code is the same but I've added s boxes_ namespace for soem so that we don't % clash with metafun. Loading and initialization is now under metafun control. @@ -13,7 +21,8 @@ if known metafun_loaded_xbox : endinput ; fi ; newinternal boolean metafun_loaded_xbox ; metafun_loaded_xbox := true ; immutable metafun_loaded_xbox ; % Find the length of the prefix of string s for which cond is true for each character -% c of the prefix. +% c of the prefix. Loading and initialization is now under metafun control. Only the +% mpxl variant will be adapted. When needed this file will be adapted. vardef boxes_str_prefix (expr s) (text cond) = save i_, c; string c; i_ = 0; @@ -295,3 +304,29 @@ if makingfigure : boxes_init_all; fi ; +% Rectangular boxes with rounded corners + +newinternal rbox_radius ; rbox_radius := 8bp ; + +vardef rboxit@#(text tt) = + boxes_begin("boxes_the_rounded","boxes_size",@#,tt) ; + boxes_generic_declare (pair) _n.sw, _n.s, _n.se, _n.e, _n.ne, _n.n, _n.nw, _n.w ; + 0 = xpart(@#nw - @#sw) = ypart(@#se - @#sw) ; + 0 = xpart(@#ne - @#se) = ypart(@#ne - @#nw) ; + @#w = .5[@#nw,@#sw] ; + @#s = .5[@#sw,@#se] ; + @#e = .5[@#ne,@#se] ; + @#n = .5[@#ne,@#nw] ; + @#ne - @#c = @#c - @#sw = (@#dx,@#dy) + .5*(urcorner boxes_pic@# - llcorner boxes_pic@#) ; + boxes_end(boxes_clear,@#) ; +enddef; + +def boxes_the_rounded(suffix $) = + save _r ; _r = min(rbox_radius, .5*ypart($.n-$.s), .5*xpart($.e-$.w)); + $.sw + (_r,0) {right} .. {right} $.se - (_r,0) .. + $.se + (0,_r) {up} .. {up} $.ne - (0,_r) .. + $.ne - (_r,0) {left} .. {left} $.nw + (_r,0) .. + $.nw - (0,_r) {down} .. {down} $.sw + (0,_r) .. + cycle +enddef; + diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 505f63b17..ba4178650 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -713,8 +713,8 @@ function scripts.context.run(ctxdata,filename) local basename = filebasename(filename) -- use splitter local pathname = filepathpart(filename) -- - if not filesuffix(filename) then - filename = addsuffix(filename,"tex") + if filesuffix(filename) == "" then + filename = fileaddsuffix(filename,"tex") end -- if pathname == "" and not a_global and filename ~= usedfiles.nop then diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua index 62212a10e..1d8f37b67 100644 --- a/scripts/context/lua/mtx-fonts.lua +++ b/scripts/context/lua/mtx-fonts.lua @@ -16,7 +16,7 @@ local lower = string.lower local concat = table.concat local write_nl = (logs and logs.writer) or (texio and texio.write_nl) or print -local otlversion = 3.118 +local otlversion = 3.119 local helpinfo = [[ <?xml version="1.0"?> diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index dcfc43f5f..a4df7e1a1 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -1201,7 +1201,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 38747, stripped down to: 19489 +-- original size: 38742, stripped down to: 19489 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -3285,7 +3285,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-io"] = package.loaded["l-io"] or true --- original size: 11951, stripped down to: 6430 +-- original size: 11988, stripped down to: 6430 if not modules then modules={} end modules ['l-io']={ version=1.001, @@ -5110,7 +5110,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 18253, stripped down to: 10816 +-- original size: 18217, stripped down to: 10792 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -5300,15 +5300,15 @@ local separator,pattern if onwindows then local slash=S("/\\")/"/" pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) + (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), + Cs(((1-S("*?/\\"))^0*slash)^0), + Cs(P(1)^0) } else pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) + (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), + C(((1-S("*?/"))^0*P("/"))^0), + C(P(1)^0) } end local filter=Cs (( @@ -7467,7 +7467,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 32815, stripped down to: 18257 +-- original size: 33089, stripped down to: 18163 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7794,9 +7794,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -9236,7 +9233,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-prs"] = package.loaded["util-prs"] or true --- original size: 24692, stripped down to: 16432 +-- original size: 24819, stripped down to: 16424 if not modules then modules={} end modules ['util-prs']={ version=1.001, @@ -9285,8 +9282,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -21547,7 +21544,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16409, stripped down to: 11591 +-- original size: 16456, stripped down to: 11636 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21593,7 +21590,7 @@ local readables={} local usedreadables={} local compilelua=luautilities.compile local luasuffixes=luautilities.suffixes -caches.base=caches.base or "luatex-cache" +caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" caches.more=caches.more or "context" caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } local direct_cache=false @@ -25935,8 +25932,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1026528 --- stripped bytes : 402906 +-- original bytes : 1026972 +-- stripped bytes : 403431 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index dcfc43f5f..a4df7e1a1 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -1201,7 +1201,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 38747, stripped down to: 19489 +-- original size: 38742, stripped down to: 19489 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -3285,7 +3285,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-io"] = package.loaded["l-io"] or true --- original size: 11951, stripped down to: 6430 +-- original size: 11988, stripped down to: 6430 if not modules then modules={} end modules ['l-io']={ version=1.001, @@ -5110,7 +5110,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 18253, stripped down to: 10816 +-- original size: 18217, stripped down to: 10792 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -5300,15 +5300,15 @@ local separator,pattern if onwindows then local slash=S("/\\")/"/" pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) + (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), + Cs(((1-S("*?/\\"))^0*slash)^0), + Cs(P(1)^0) } else pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) + (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), + C(((1-S("*?/"))^0*P("/"))^0), + C(P(1)^0) } end local filter=Cs (( @@ -7467,7 +7467,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 32815, stripped down to: 18257 +-- original size: 33089, stripped down to: 18163 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7794,9 +7794,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -9236,7 +9233,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-prs"] = package.loaded["util-prs"] or true --- original size: 24692, stripped down to: 16432 +-- original size: 24819, stripped down to: 16424 if not modules then modules={} end modules ['util-prs']={ version=1.001, @@ -9285,8 +9282,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -21547,7 +21544,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16409, stripped down to: 11591 +-- original size: 16456, stripped down to: 11636 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21593,7 +21590,7 @@ local readables={} local usedreadables={} local compilelua=luautilities.compile local luasuffixes=luautilities.suffixes -caches.base=caches.base or "luatex-cache" +caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" caches.more=caches.more or "context" caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } local direct_cache=false @@ -25935,8 +25932,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1026528 --- stripped bytes : 402906 +-- original bytes : 1026972 +-- stripped bytes : 403431 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index dcfc43f5f..a4df7e1a1 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -1201,7 +1201,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 38747, stripped down to: 19489 +-- original size: 38742, stripped down to: 19489 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -3285,7 +3285,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-io"] = package.loaded["l-io"] or true --- original size: 11951, stripped down to: 6430 +-- original size: 11988, stripped down to: 6430 if not modules then modules={} end modules ['l-io']={ version=1.001, @@ -5110,7 +5110,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 18253, stripped down to: 10816 +-- original size: 18217, stripped down to: 10792 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -5300,15 +5300,15 @@ local separator,pattern if onwindows then local slash=S("/\\")/"/" pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) + (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), + Cs(((1-S("*?/\\"))^0*slash)^0), + Cs(P(1)^0) } else pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) + (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), + C(((1-S("*?/"))^0*P("/"))^0), + C(P(1)^0) } end local filter=Cs (( @@ -7467,7 +7467,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 32815, stripped down to: 18257 +-- original size: 33089, stripped down to: 18163 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7794,9 +7794,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -9236,7 +9233,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-prs"] = package.loaded["util-prs"] or true --- original size: 24692, stripped down to: 16432 +-- original size: 24819, stripped down to: 16424 if not modules then modules={} end modules ['util-prs']={ version=1.001, @@ -9285,8 +9282,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -21547,7 +21544,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16409, stripped down to: 11591 +-- original size: 16456, stripped down to: 11636 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21593,7 +21590,7 @@ local readables={} local usedreadables={} local compilelua=luautilities.compile local luasuffixes=luautilities.suffixes -caches.base=caches.base or "luatex-cache" +caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" caches.more=caches.more or "context" caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } local direct_cache=false @@ -25935,8 +25932,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1026528 --- stripped bytes : 402906 +-- original bytes : 1026972 +-- stripped bytes : 403431 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index dcfc43f5f..a4df7e1a1 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -1201,7 +1201,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 38747, stripped down to: 19489 +-- original size: 38742, stripped down to: 19489 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -3285,7 +3285,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-io"] = package.loaded["l-io"] or true --- original size: 11951, stripped down to: 6430 +-- original size: 11988, stripped down to: 6430 if not modules then modules={} end modules ['l-io']={ version=1.001, @@ -5110,7 +5110,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 18253, stripped down to: 10816 +-- original size: 18217, stripped down to: 10792 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -5300,15 +5300,15 @@ local separator,pattern if onwindows then local slash=S("/\\")/"/" pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) + (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), + Cs(((1-S("*?/\\"))^0*slash)^0), + Cs(P(1)^0) } else pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) + (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), + C(((1-S("*?/"))^0*P("/"))^0), + C(P(1)^0) } end local filter=Cs (( @@ -7467,7 +7467,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 32815, stripped down to: 18257 +-- original size: 33089, stripped down to: 18163 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7794,9 +7794,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -9236,7 +9233,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-prs"] = package.loaded["util-prs"] or true --- original size: 24692, stripped down to: 16432 +-- original size: 24819, stripped down to: 16424 if not modules then modules={} end modules ['util-prs']={ version=1.001, @@ -9285,8 +9282,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -21547,7 +21544,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16409, stripped down to: 11591 +-- original size: 16456, stripped down to: 11636 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21593,7 +21590,7 @@ local readables={} local usedreadables={} local compilelua=luautilities.compile local luasuffixes=luautilities.suffixes -caches.base=caches.base or "luatex-cache" +caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" caches.more=caches.more or "context" caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } local direct_cache=false @@ -25935,8 +25932,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1026528 --- stripped bytes : 402906 +-- original bytes : 1026972 +-- stripped bytes : 403431 -- end library merge diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index aee36ce61..25e2ed4d7 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.08.10 12:37} +\newcontextversion{2021.08.19 19:40} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index ec8a50d33..7d3289b97 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.08.10 12:37} +\edef\contextversion{2021.08.19 19:40} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-ro.mkii b/tex/context/base/mkii/mult-ro.mkii index 50a9ea08f..9aede3730 100644 --- a/tex/context/base/mkii/mult-ro.mkii +++ b/tex/context/base/mkii/mult-ro.mkii @@ -151,6 +151,7 @@ \setinterfacevariable{commands}{comenzi} \setinterfacevariable{comment}{comentariu} \setinterfacevariable{component}{componenta} +\setinterfacevariable{compress}{compress} \setinterfacevariable{compressseparator}{compressseparator} \setinterfacevariable{compressstopper}{compressstopper} \setinterfacevariable{concept}{concept} diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua index 51c32ec1d..4f29e09d6 100644 --- a/tex/context/base/mkiv/back-exp.lua +++ b/tex/context/base/mkiv/back-exp.lua @@ -325,9 +325,9 @@ local styletemplate = [[ local numbertoallign = { [0] = "justify", ["0"] = "justify", [variables.normal ] = "justify", - [1] = "right", ["1"] = "right", [variables.flushright] = "right", - [2] = "center", ["2"] = "center", [variables.middle ] = "center", - [3] = "left", ["3"] = "left", [variables.flushleft ] = "left", + "right", ["1"] = "right", [variables.flushright] = "right", + "center", ["2"] = "center", [variables.middle ] = "center", + "left", ["3"] = "left", [variables.flushleft ] = "left", } function wrapups.allusedstyles(filename) diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua index 8a8ec67c7..6c844342a 100644 --- a/tex/context/base/mkiv/buff-ini.lua +++ b/tex/context/base/mkiv/buff-ini.lua @@ -121,6 +121,11 @@ local function exists(name) return cache[name] end +local function getcontent(name) + local buffer = name and cache[name] + return buffer and buffer.data or "" +end + local function empty(name) if find(getcontent(name),"%S") then return false @@ -129,11 +134,6 @@ local function empty(name) end end -local function getcontent(name) - local buffer = name and cache[name] - return buffer and buffer.data or "" -end - local function getlines(name) local buffer = name and cache[name] return buffer and splitlines(buffer.data) diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 61325b615..da7aa9dc0 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.08.10 12:37} +\newcontextversion{2021.08.19 19:40} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 74e3cea56..d837240b4 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.08.10 12:37} +\edef\contextversion{2021.08.19 19:40} %D Kind of special: diff --git a/tex/context/base/mkiv/data-tmp.lua b/tex/context/base/mkiv/data-tmp.lua index 9a8a586cd..1948f1ea5 100644 --- a/tex/context/base/mkiv/data-tmp.lua +++ b/tex/context/base/mkiv/data-tmp.lua @@ -74,7 +74,7 @@ local usedreadables = { } local compilelua = luautilities.compile local luasuffixes = luautilities.suffixes -caches.base = caches.base or "luatex-cache" -- can be local +caches.base = caches.base or (LUATEXENGINE and LUATEXENGINE .. "-cache") or "luatex-cache" -- can be local caches.more = caches.more or "context" -- can be local caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua index cf6c232a6..267c63f7a 100644 --- a/tex/context/base/mkiv/font-cft.lua +++ b/tex/context/base/mkiv/font-cft.lua @@ -439,7 +439,7 @@ do }, colorschemes = { default = { - [1] = { t_string }, + { t_string }, } }, files = { diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua index a72f1bf42..9bb8d4cc1 100644 --- a/tex/context/base/mkiv/font-mis.lua +++ b/tex/context/base/mkiv/font-mis.lua @@ -21,7 +21,7 @@ local readers = otf.readers if readers then - otf.version = otf.version or 3.118 + otf.version = otf.version or 3.119 otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true) function fonts.helpers.getfeatures(name,save) diff --git a/tex/context/base/mkiv/font-ocm.lua b/tex/context/base/mkiv/font-ocm.lua index ef0b02a14..e54799b23 100644 --- a/tex/context/base/mkiv/font-ocm.lua +++ b/tex/context/base/mkiv/font-ocm.lua @@ -40,16 +40,16 @@ callback.register("provide_charproc_data",function(action,f,...) end) local defaults = { - [1] = function() return 0, 0 end, - [2] = function() return 0, 0 end, - [3] = function() return 0.001, "" end, + function() return 0, 0 end, + function() return 0, 0 end, + function() return 0.001, "" end, } local function registeractions(t) return { - [1] = t.preroll or defaults[1], - [2] = t.collect or defaults[2], - [3] = t.wrapup or defaults[3], + t.preroll or defaults[1], + t.collect or defaults[2], + t.wrapup or defaults[3], } end diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua index a9ea878c0..b4e753182 100644 --- a/tex/context/base/mkiv/font-osd.lua +++ b/tex/context/base/mkiv/font-osd.lua @@ -630,7 +630,8 @@ local function initializedevanagi(tfmdata) local h = coverage[k] if h then for k, v in next, h do - found = v and v.ligature + -- found = v and v.ligature + found = v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found] = true break @@ -647,7 +648,8 @@ local function initializedevanagi(tfmdata) end else for k, v in next, r do - found = v and v.ligature + -- found = v and v.ligature + found = v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found] = true break @@ -696,7 +698,8 @@ local function initializedevanagi(tfmdata) for k, v in next, halant do local h = r[k] if h then - reph = h.ligature or false + -- reph = h.ligature or false + reph = tonumber(h) or h.ligature or false break end end @@ -713,7 +716,8 @@ local function initializedevanagi(tfmdata) for k, v in next, halant do local h = r[k] if h then - reph = h.ligature or false + -- reph = h.ligature or false + reph = tonumber(h) or h.ligature or false break end end @@ -757,7 +761,8 @@ local function initializedevanagi(tfmdata) local h = coverage[k] if h then for k, v in next, h do - found = v and v.ligature + -- found = v and v.ligature + found = v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found] = true break @@ -774,7 +779,8 @@ local function initializedevanagi(tfmdata) end else for k, v in next, h do - found = v and v.ligature + -- found = v and v.ligature + found = v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found] = true break diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua index 74f209b0a..ae2dda4f3 100644 --- a/tex/context/base/mkiv/font-otl.lua +++ b/tex/context/base/mkiv/font-otl.lua @@ -52,7 +52,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.118 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 3.119 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otl", otf.version, true) otf.svgcache = containers.define("fonts", "svg", otf.version, true) otf.pngcache = containers.define("fonts", "png", otf.version, true) @@ -218,6 +218,9 @@ function otf.load(filename,sub,instance) if cleanup == 0 then checkmemory(used,threshold,tracememory) end + if context then + otfreaders.condense(data) + end otfreaders.pack(data) report_otf("loading done") report_otf("saving %a in cache",filename) diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua index 6f5f2fb41..0f667bcc2 100644 --- a/tex/context/base/mkiv/font-oto.lua +++ b/tex/context/base/mkiv/font-oto.lua @@ -170,7 +170,7 @@ end local function makefake(tfmdata,name,present) local private = getprivate(tfmdata) local character = { intermediate = true, ligatures = { } } - resources.unicodes[name] = private + tfmdata.resources.unicodes[name] = private tfmdata.characters[private] = character tfmdata.descriptions[private] = { name = name } present[name] = private @@ -178,43 +178,55 @@ local function makefake(tfmdata,name,present) end local function make_1(present,tree,name) - for k, v in next, tree do - if k == "ligature" then - present[name] = v + if tonumber(tree) then + present[name] = v + else + for k, v in next, tree do + if k == "ligature" then + present[name] = v + else + make_1(present,v,name .. "_" .. k) + end + end + end +end + +local function make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v) + local character = characters[preceding] + if not character then + if trace_baseinit then + report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) + end + character = makefake(tfmdata,name,present) + end + local ligatures = character.ligatures + if ligatures then + ligatures[unicode] = { char = v } + else + character.ligatures = { [unicode] = { char = v } } + end + if done then + local d = done[name] + if not d then + done[name] = { "dummy", v } else - make_1(present,v,name .. "_" .. k) + d[#d+1] = v end end end local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done) - for k, v in next, tree do - if k == "ligature" then - local character = characters[preceding] - if not character then - if trace_baseinit then - report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) - end - character = makefake(tfmdata,name,present) - end - local ligatures = character.ligatures - if ligatures then - ligatures[unicode] = { char = v } + if tonumber(tree) then + make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,tree) + else + for k, v in next, tree do + if k == "ligature" then + make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v) else - character.ligatures = { [unicode] = { char = v } } + local code = present[name] or unicode + local name = name .. "_" .. k + make_2(present,tfmdata,characters,v,name,code,k,done) end - if done then - local d = done[name] - if not d then - done[name] = { "dummy", v } - else - d[#d+1] = v - end - end - else - local code = present[name] or unicode - local name = name .. "_" .. k - make_2(present,tfmdata,characters,v,name,code,k,done) end end end diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua index 2f8934508..3b5edebc4 100644 --- a/tex/context/base/mkiv/font-otr.lua +++ b/tex/context/base/mkiv/font-otr.lua @@ -682,15 +682,15 @@ local weights = { } local widths = { - [1] = "ultracondensed", - [2] = "extracondensed", - [3] = "condensed", - [4] = "semicondensed", - [5] = "normal", - [6] = "semiexpanded", - [7] = "expanded", - [8] = "extraexpanded", - [9] = "ultraexpanded", + "ultracondensed", + "extracondensed", + "condensed", + "semicondensed", + "normal", + "semiexpanded", + "expanded", + "extraexpanded", + "ultraexpanded", } setmetatableindex(weights, function(t,k) @@ -703,31 +703,31 @@ setmetatableindex(widths,function(t,k) return "normal" end) -local panoseweights = { - [ 0] = "normal", - [ 1] = "normal", - [ 2] = "verylight", - [ 3] = "light", - [ 4] = "thin", - [ 5] = "book", - [ 6] = "medium", - [ 7] = "demi", - [ 8] = "bold", - [ 9] = "heavy", - [10] = "black", +local panoseweights = { [0] = + "normal", + "normal", + "verylight", + "light", + "thin", + "book", + "medium", + "demi", + "bold", + "heavy", + "black", } -local panosewidths = { - [ 0] = "normal", - [ 1] = "normal", - [ 2] = "normal", - [ 3] = "normal", - [ 4] = "normal", - [ 5] = "expanded", - [ 6] = "condensed", - [ 7] = "veryexpanded", - [ 8] = "verycondensed", - [ 9] = "monospaced", +local panosewidths = { [0] = + "normal", + "normal", + "normal", + "normal", + "normal", + "expanded", + "condensed", + "veryexpanded", + "verycondensed", + "monospaced", } -- We implement a reader per table. @@ -2522,6 +2522,10 @@ function readers.compact(fontdata) report("the %a helper is not yet implemented","compact") end +function readers.condense(fontdata) + report("the %a helper is not yet implemented","condense") +end + -- plug in local extenders = { } diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index 30d79c407..8e8be6f95 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -763,7 +763,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip while current do local char = ischar(current,currentfont) if char then - local lg = ligature[char] + local lg = not tonumber(ligature) and ligature[char] if lg then stop = current ligature = lg @@ -776,14 +776,14 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip end end if stop then - local lig = ligature.ligature - if lig then + local ligature = tonumber(ligature) or ligature.ligature + if ligature then if trace_ligatures then local stopchar = getchar(stop) - head, start = markstoligature(head,start,stop,lig) + head, start = markstoligature(head,start,stop,ligature) logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) else - head, start = markstoligature(head,start,stop,lig) + head, start = markstoligature(head,start,stop,ligature) end return head, start, true, false else @@ -799,7 +799,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip if skiphash and skiphash[char] then current = getnext(current) else - local lg = ligature[char] + local lg = not tonumber(ligature) and ligature[char] if lg then if marks[char] then hasmarks = true @@ -833,20 +833,20 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip local match if replace then local char = ischar(replace,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match = true end end if not match and pre then local char = ischar(pre,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match = true end end if not match and not pre or not replace then local n = getnext(discfound) local char = ischar(n,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match = true end end @@ -890,24 +890,26 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip return head, start, true, true end end - local lig = ligature.ligature - if lig then + local ligature = tonumber(ligature) or ligature.ligature + if ligature then if stop then if trace_ligatures then local stopchar = getchar(stop) - -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) - head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) + -- head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,discfound,hasmarks) + head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(ligature)) + -- we can have a rare case of multiple disc in a lig but that makes no sense language wise but if really + -- needed we could backtrack if we're in a disc node else - -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) - head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) + -- head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,discfound,hasmarks) + head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) end else -- weird but happens (in some arabic font) resetinjection(start) - setchar(start,lig) + setchar(start,ligature) if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) + logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(ligature)) end end return head, start, true, false @@ -1484,7 +1486,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup current = getnext(current) -- end else - local lg = ligatures[schar] + local lg = not tonumber(ligatures) and ligatures[schar] if lg then ligatures = lg last = current @@ -1503,7 +1505,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup end end end - local ligature = ligatures.ligature + local ligature = tonumber(ligatures) or ligatures.ligature if ligature then if chainindex then stop = last @@ -1978,7 +1980,9 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) local chainproc = chainprocs[chainkind] if chainproc then local ok - head, start, ok = chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash) + -- HH: chainindex 1 added here (for KAI to check too), there are weird ligatures e.g. + -- char + mark -> char where mark has to disappear + head, start, ok = chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash,1) if ok then done = true end @@ -2471,6 +2475,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s local ck = contexts[k] local seq = ck[3] local f = ck[4] -- first current +local last = start if not startchar or not seq[f][startchar] then -- report("no hit in %a at %i of %i contexts",sequence.type,k,nofcontexts) goto next @@ -2481,7 +2486,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s else local l = ck[5] -- last current local current = start - local last = start +-- local last = start -- current match @@ -3409,7 +3414,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) while s do local char = ischar(s,font) if char then - local lg = lookupmatch[char] + local lg = not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d = 1 @@ -3439,7 +3444,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) break end end - if l and l.ligature then -- so we test for ligature + if l and (tonumber(l) or l.ligature) then -- so we test for ligature lastd = d end -- why not: if not l then break elseif l.ligature then return d end @@ -3580,7 +3585,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) while s do local char = ischar(s) if char then - local lg = lookupmatch[char] + local lg = not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d = 1 @@ -3610,7 +3615,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) break end end - if l and l.ligature then + if l and (tonumber(l) or l.ligature) then lastd = d end end diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua index 4e70bf936..4c3d562c2 100644 --- a/tex/context/base/mkiv/font-oup.lua +++ b/tex/context/base/mkiv/font-oup.lua @@ -44,6 +44,9 @@ directives.register("otf.checksofthyphen",function(v) check_soft_hyphen = v -- only for testing end) +-- After (!) the unicodes have been resolved we compact ligature tables so before that happens +-- we don't need to check for numbers. + local function replaced(list,index,replacement) if type(list) == "number" then return replacement @@ -1043,6 +1046,10 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n local function traverse(p,k,v) if k == "ligature" then collected[v] = { unpack(l) } + elseif tonumber(v) then + insert(l,k) + collected[v] = { unpack(l) } + remove(l) else insert(l,k) for k, vv in next, v do @@ -1230,7 +1237,6 @@ local function tabstr_flat(t) end local function tabstr_mixed(t) -- indexed - local s = { } local n = #t if n == 0 then return "" @@ -1244,6 +1250,7 @@ local function tabstr_mixed(t) -- indexed return tostring(k) -- number or string end else + local s = { } for i=1,n do local k = t[i] if k == true then @@ -1353,6 +1360,21 @@ function readers.pack(data) end end + -- local function pack_indexed(v) -- less code + -- local tag = concat(v," ") + -- local ht = h[tag] + -- if ht then + -- c[ht] = c[ht] + 1 + -- else + -- ht = nt + 1 + -- t[ht] = v + -- c[ht] = 1 + -- h[tag] = ht + -- nt = ht + -- end + -- return ht + -- end + local function pack_mixed(v) local tag = tabstr_mixed(v) local ht = h[tag] @@ -2801,6 +2823,91 @@ function readers.compact(data) end end +if CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 then + + local done = 0 + + local function condense_1(k,v,t) + if type(v) == "table" then + local u = false + local l = false + for k, v in next, v do + if k == "ligature" then + l = v + if u then + break + end + elseif u then + break + else + u = true + end + end + if l and not u then + t[k] = l + done = done + 1 + end + if u then + for k, vv in next, v do + if k ~= "ligature" then + condense_1(k,vv,v) + end + end + end + end + end + + local function condensesteps_1(lookup) + done = 0 + if lookup.type == "gsub_ligature" then + local steps = lookup.steps + if steps then + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + if coverage then + for k, v in next, coverage do + if condense_1(k,v,coverage) then + coverage[k] = v.ligature + done = done + 1 + end + end + end + end + end + end + return done + end + + function readers.condense(data) + if not data or data.condensed then + return + else + data.condensed = true + end + local resources = data.resources + local condensed = 0 + local function condense(what) + local lookups = resources[what] + if lookups then + for i=1,#lookups do + condensed = condensed + condensesteps_1(lookups[i]) + end + elseif trace_optimizations then + report_optimizations("no lookups in %a",what) + end + end + condense("sequences") + condense("sublookups") + if trace_optimizations then + if condensed > 0 then + report_optimizations("%i ligatures condensed",condensed) + end + end + end + +end + local function mergesteps(t,k) if k == "merged" then local merged = { } diff --git a/tex/context/base/mkiv/font-ttf.lua b/tex/context/base/mkiv/font-ttf.lua index d8abed329..fc987d74c 100644 --- a/tex/context/base/mkiv/font-ttf.lua +++ b/tex/context/base/mkiv/font-ttf.lua @@ -269,6 +269,16 @@ local function applyaxis(glyph,shape,deltas,dowidth) else local n1 = dpoints[d1] local n3 = dpoints[d3] + -- Some day I need to figure out these extra points but + -- I'll wait till the standard is more clear and fonts + -- become better (ntg-context: fraunces.ttf > abcdef). + if n1 > nofpoints then + n1 = nofpoints + end + if n3 > nofpoints then + n3 = nofpoints + end + -- local p1 = points[n1] local p3 = points[n3] local p1x = p1[1] diff --git a/tex/context/base/mkiv/good-gen.lua b/tex/context/base/mkiv/good-gen.lua index cee6b3172..1747727c1 100644 --- a/tex/context/base/mkiv/good-gen.lua +++ b/tex/context/base/mkiv/good-gen.lua @@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['good-gen'] = { local type, next = type, next local lower = string.lower - +local filesuffix, replacesuffix = file.suffix, file.replacesuffix local fonts = fonts ----- trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) @@ -134,6 +134,16 @@ function fontgoodies.filenames.resolve(name) return fn end end + elseif filesuffix(name) == "any" then + -- This is a bit weird place but it's a kind of fallback option in case + -- we can't resolve due to a name conflict. + local sequence = fonts.readers.sequence + for i=1,#sequence do + local fn = replacesuffix(name,sequence[i]) + if findfile(fn) ~= "" then + return fn + end + end else -- no lookup, just use the regular mechanism end diff --git a/tex/context/base/mkiv/l-dir.lua b/tex/context/base/mkiv/l-dir.lua index 325039cb1..ac8e2f4e8 100644 --- a/tex/context/base/mkiv/l-dir.lua +++ b/tex/context/base/mkiv/l-dir.lua @@ -230,18 +230,18 @@ if onwindows then -- we could sanitize here -- pattern = Ct { pattern = { - [1] = (Cs(P(".") + slash^1) + Cs(R("az","AZ") * P(":") * slash^0) + Cc("./")) * V(2) * V(3), - [2] = Cs(((1-S("*?/\\"))^0 * slash)^0), - [3] = Cs(P(1)^0) + (Cs(P(".") + slash^1) + Cs(R("az","AZ") * P(":") * slash^0) + Cc("./")) * V(2) * V(3), + Cs(((1-S("*?/\\"))^0 * slash)^0), + Cs(P(1)^0) } else -- assume unix -- pattern = Ct { pattern = { - [1] = (C(P(".") + P("/")^1) + Cc("./")) * V(2) * V(3), - [2] = C(((1-S("*?/"))^0 * P("/"))^0), - [3] = C(P(1)^0) + (C(P(".") + P("/")^1) + Cc("./")) * V(2) * V(3), + C(((1-S("*?/"))^0 * P("/"))^0), + C(P(1)^0) } end diff --git a/tex/context/base/mkiv/l-io.lua b/tex/context/base/mkiv/l-io.lua index f72995abd..6bf7a97bd 100644 --- a/tex/context/base/mkiv/l-io.lua +++ b/tex/context/base/mkiv/l-io.lua @@ -291,7 +291,8 @@ end io.noflines = noflines --- inlined is faster ... beware, better use util-fil +-- inlined is faster ... beware, better use util-fil so these are obsolete +-- and will go local nextchar = { [ 4] = function(f) diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua index 77e5cf12d..5f3bea08c 100644 --- a/tex/context/base/mkiv/l-lpeg.lua +++ b/tex/context/base/mkiv/l-lpeg.lua @@ -665,12 +665,12 @@ end -- lpeg.print(lpeg.P("a","b","c")) -- lpeg.print(lpeg.S("a","b","c")) --- print(lpeg.counter("äáà a",lpeg.P("á") + lpeg.P("à "))) --- print(lpeg.counter("äáà a",lpeg.UP("áà "))) --- print(lpeg.counter("äáà a",lpeg.US("à á"))) --- print(lpeg.counter("äáà a",lpeg.UR("aá"))) --- print(lpeg.counter("äáà a",lpeg.UR("à á"))) --- print(lpeg.counter("äáà a",lpeg.UR(0x0000,0xFFFF))) +-- print(lpeg.counter(lpeg.P("á") + lpeg.P("à "))("äáà a")) +-- print(lpeg.counter(lpeg.UP("áà "))("äáà a")) +-- print(lpeg.counter(lpeg.US("à á"))("äáà a")) +-- print(lpeg.counter(lpeg.UR("aá"))("äáà a")) +-- print(lpeg.counter(lpeg.UR("à á"))("äáà a")) +-- print(lpeg.counter(lpeg.UR(0x0000,0xFFFF))) function lpeg.is_lpeg(p) return p and lpegtype(p) == "pattern" diff --git a/tex/context/base/mkiv/lpdf-wid.lua b/tex/context/base/mkiv/lpdf-wid.lua index 1e91ecd56..e856ddaf4 100644 --- a/tex/context/base/mkiv/lpdf-wid.lua +++ b/tex/context/base/mkiv/lpdf-wid.lua @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['lpdf-wid'] = { -- html5 media in pdf then. -- -- See mail by Michal Vlasák to the mailing list that discusses current support in --- viewers and also mentions a few fixes wrt embedding media. +-- viewers and also mentions (and submitted) a few fixes wrt embedding media. local tonumber, next = tonumber, next local gmatch, gsub, find, lower = string.gmatch, string.gsub, string.find, string.lower @@ -60,6 +60,7 @@ local v_auto = variables.auto local v_embed = variables.embed local v_max = variables.max local v_yes = variables.yes +local v_compress = variables.compress local pdfconstant = lpdf.constant local pdfnull = lpdf.null @@ -649,6 +650,7 @@ local function insertrenderingwindow(specification) Subtype = pdfconstant("Screen"), P = pdfreference(pdfpagereference(page)), A = a, -- needed in order to make the annotation clickable (i.e. don't bark) + T = pdfunicode(label), -- for JS Border = bs, C = bc, AA = actions, @@ -662,7 +664,7 @@ end -- some dictionaries can have a MH (must honor) or BE (best effort) capsule local function insertrendering(specification) - local label = specification.label + local label = specification.label local option = settings_to_hash(specification.option) if not mf[label] then local filename = specification.filename @@ -693,7 +695,7 @@ local function insertrendering(specification) -- } -- } local parameters = pdfdictionary { - Type = pdfconstant(MediaPermissions), + Type = pdfconstant("MediaPermissions"), TF = pdfstring("TEMPALWAYS"), -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS / needed for acrobat/wmp } local descriptor = pdfdictionary { @@ -707,7 +709,7 @@ local function insertrendering(specification) descriptor = codeinjections.embedfile { file = filename, mimetype = mimetype, -- yes or no - compress = false, + compress = option[v_compress] or false, forcereference = true, } end @@ -723,7 +725,7 @@ local function insertrendering(specification) local rendition = pdfdictionary { Type = pdfconstant("Rendition"), S = pdfconstant("MR"), - N = label, + N = pdfunicode(label), C = pdfreference(pdfflushobject(clip)), } mf[label] = pdfreference(pdfflushobject(rendition)) @@ -761,6 +763,21 @@ function codeinjections.processrendering(label) end end +-- needed mapping for access from JS + +local function flushrenderings() + if next(mf) then + local r = pdfarray() + for label, reference in sortedhash(mf) do + r[#r+1] = pdfunicode(label) + r[#r+1] = reference -- already a reference + end + lpdf.addtonames("Renditions",pdfreference(pdfflushobject(pdfdictionary{ Names = r }))) + end +end + +lpdf.registerdocumentfinalizer(flushrenderings,"renderings") + function codeinjections.insertrenderingwindow(specification) local label = specification.label codeinjections.processrendering(label) diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua index 19bf86802..2a8129ca7 100644 --- a/tex/context/base/mkiv/math-ini.lua +++ b/tex/context/base/mkiv/math-ini.lua @@ -120,13 +120,13 @@ local accents = allocate { local codes = allocate { ordinary = 0, [0] = "ordinary", - largeoperator = 1, [1] = "largeoperator", - binaryoperator = 2, [2] = "binaryoperator", - relation = 3, [3] = "relation", - openingsymbol = 4, [4] = "openingsymbol", - closingsymbol = 5, [5] = "closingsymbol", - punctuation = 6, [6] = "punctuation", - variable = 7, [7] = "variable", + largeoperator = 1, "largeoperator", + binaryoperator = 2, "binaryoperator", + relation = 3, "relation", + openingsymbol = 4, "openingsymbol", + closingsymbol = 5, "closingsymbol", + punctuation = 6, "punctuation", + variable = 7, "variable", } local extensibles = allocate { diff --git a/tex/context/base/mkiv/math-map.lua b/tex/context/base/mkiv/math-map.lua index 97860b923..5f93b43fc 100644 --- a/tex/context/base/mkiv/math-map.lua +++ b/tex/context/base/mkiv/math-map.lua @@ -689,9 +689,9 @@ local issygreek = regular_tf.symbols local isgreek = merged(islcgreek,isucgreek,issygreek) local greekremapping = { - [1] = { what = "unchanged" }, -- upright - [2] = { what = "upright", it = "tf", bi = "bf" }, -- upright - [3] = { what = "italic", tf = "it", bf = "bi" }, -- italic + { what = "unchanged" }, -- upright + { what = "upright", it = "tf", bi = "bf" }, -- upright + { what = "italic", tf = "it", bf = "bi" }, -- italic } local usedremap = { } diff --git a/tex/context/base/mkiv/mlib-mpf.lua b/tex/context/base/mkiv/mlib-mpf.lua index 7452c0111..7e2a01ffb 100644 --- a/tex/context/base/mkiv/mlib-mpf.lua +++ b/tex/context/base/mkiv/mlib-mpf.lua @@ -247,7 +247,7 @@ do -- writers - local function mpp(value) + local function rawmpp(value) n = n + 1 local t = type(value) if t == "number" then @@ -268,13 +268,13 @@ do local function mpprint(first,second,...) if second == nil then if first ~= nil then - mpp(first) + rawmpp(first) end else for i=1,select("#",first,second,...) do local value = (select(i,first,second,...)) if value ~= nil then - mpp(value) + rawmpp(value) end end end @@ -653,6 +653,25 @@ do for k, v in next, aux do mp[k] = v end + -- mp.print = table.setmetatablecall(aux, function(t,...) + -- mpprint(...) + -- end) + + mp.print = table.setmetatablecall(aux, function(t,first,second,...) + if second == nil then + if first ~= nil then + rawmpp(first) + end + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + rawmpp(value) + end + end + end + end) + end do diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index af7804506..a06deffe5 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -15390,6 +15390,10 @@ return { ["pe"]="eight", ["ro"]="eight", }, + ["compress"]={ + ["en"]="compress", + ["nl"]="comprimeer", + }, ["embed"]={ ["en"]="embed", ["fr"]="integrer", diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua index 50ced6ead..9f6c8456c 100644 --- a/tex/context/base/mkiv/mult-fun.lua +++ b/tex/context/base/mkiv/mult-fun.lua @@ -189,10 +189,17 @@ return { "setmacro", "setdimen", "setcount", "settoks", "setglobalmacro", "setglobaldimen", "setglobalcount", "setglobaltoks", -- - "positionpath", "positioncurve", "positionxy", "positionpxy", - "positionwhd", "positionpage", "positionregion", "positionbox", + "positionpath", "positioncurve", "positionxy", "positionparagraph", "positioncolumn", + "positionwhd", "positionpage", "positionregion", "positionbox", "positionx", "positiony", "positionanchor", "positioninregion", "positionatanchor", -- + "getposboxesv, getmultipars", + "getpospage", "getposparagraph", "getposcolumn", "getposregion", + "getposx", "getposy", "getposwidth", "getposheight", "getposdepth", + "getposleftskip", "getposrightskip", "getposhsize", "getposparindent", "getposhangindent", "getposhangafter", + "getposxy", "getposupperleft", "getposlowerleft", "getposupperright", "getposlowerright". + "getposllx", "getposlly", "getposurx", "getposury" ; + -- "wdpart", "htpart", "dppart", -- "texvar", "texstr", @@ -201,7 +208,7 @@ return { -- "utfnum", "utflen", "utfsub", -- - "newhash", "disposehash", "inhash", "tohash", + "newhash", "disposehash", "inhash", "tohash", "fromhash", -- "isarray", "prefix", "isobject", -- diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index 5985faf73..59320507a 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -357,7 +357,7 @@ return { -- "quitcondition", "truecondition", "falsecondition", -- - "tracingall", "tracingnone", "loggingall", + "tracingall", "tracingnone", "loggingall", "tracingcatcodes", "showluatokens", -- "aliasmacro", diff --git a/tex/context/base/mkiv/page-mix.lua b/tex/context/base/mkiv/page-mix.lua index 374ba8866..7828b7e56 100644 --- a/tex/context/base/mkiv/page-mix.lua +++ b/tex/context/base/mkiv/page-mix.lua @@ -59,7 +59,7 @@ local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid local getlist = nuts.getlist -local getindex = nuts.getindex +local getindex = nuts.getindex or nuts.getsubtype -- luatex catch local getbox = nuts.getbox local getattr = nuts.getattr local getwhd = nuts.getwhd @@ -79,6 +79,8 @@ local new_glue = nodepool.glue local points = number.points +local setinsertcontent = tex.setinsertcontent or tex.setbox + local settings_to_hash = utilities.parsers.settings_to_hash local variables = interfaces.variables @@ -986,9 +988,8 @@ local function getsplit(result,n) for i=1,#list-1 do setdepth(list[i],0) end - local b = vpack(l) -- multiple arguments, todo: fastvpack --- setbox("global",c,b) -- when we wrap in a box - tex.setinsertcontent(c,tonode(b)) -- when we wrap in a box + local b = vpack(l) -- multiple arguments, todo: fastvpack + setinsertcontent(c,tonode(b)) -- when we wrap in a box r.inserts[c] = nil end diff --git a/tex/context/base/mkiv/publ-dat.lua b/tex/context/base/mkiv/publ-dat.lua index f09e97a8d..382f70471 100644 --- a/tex/context/base/mkiv/publ-dat.lua +++ b/tex/context/base/mkiv/publ-dat.lua @@ -632,13 +632,13 @@ do local r_value = reference * Carg(1) / resolve local balanced = P { - [1] = ((escape * (left+right)) + (collapsed + r_value + 1 - (left+right))^1 + V(2))^0, - [2] = left * V(1) * right, + ((escape * (left+right)) + (collapsed + r_value + 1 - (left+right))^1 + V(2))^0, + left * V(1) * right, } -- local unbalanced = P { - -- [1] = left * V(2) * right, - -- [2] = ((escape * (left+right)) + (collapsed + 1 - (left+right))^1 + V(1))^0, + -- left * V(2) * right, + -- ((escape * (left+right)) + (collapsed + 1 - (left+right))^1 + V(1))^0, -- } local unbalanced = (left/"") * balanced * (right/"") * P(-1) diff --git a/tex/context/base/mkiv/publ-fnd.lua b/tex/context/base/mkiv/publ-fnd.lua index 32d0c11be..5ba173365 100644 --- a/tex/context/base/mkiv/publ-fnd.lua +++ b/tex/context/base/mkiv/publ-fnd.lua @@ -147,8 +147,8 @@ local p_expression = P("match")/"" * Cs(p_compare) ) / test_key_value local pattern = Cs { - [1] = V(2) * (p_combine * V(2))^0, - [2] = p_expression, + V(2) * (p_combine * V(2))^0, + p_expression, } -- -- -- -- -- -- -- -- -- -- -- -- -- diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua index 5ab8196c8..efc157a2b 100644 --- a/tex/context/base/mkiv/spac-ver.lua +++ b/tex/context/base/mkiv/spac-ver.lua @@ -710,19 +710,19 @@ local function snap_topskip(current,method) return w, 0 end -local categories = { - [0] = "discard", - [1] = "largest", - [2] = "force", - [3] = "penalty", - [4] = "add", - [5] = "disable", - [6] = "nowhite", - [7] = "goback", - [8] = "packed", - [9] = "overlay", - [10] = "enable", - [11] = "notopskip", +local categories = { [0] = + "discard", + "largest", + "force", + "penalty", + "add", + "disable", + "nowhite", + "goback", + "packed", + "overlay", + "enable", + "notopskip", } categories = allocate(table.swapped(categories,categories)) diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 67e5b7a47..61569f5d1 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 42d1b8d7b..163af8eee 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-syn.lua b/tex/context/base/mkiv/strc-syn.lua index 6b50da4ac..f8b78b940 100644 --- a/tex/context/base/mkiv/strc-syn.lua +++ b/tex/context/base/mkiv/strc-syn.lua @@ -86,12 +86,12 @@ function synonyms.register(class,kind,spec) local tag = definition.tag or "" data.metadata.kind = kind -- runtime, not saved in format (yet) if not hash[tag] then - if definition.used == nil then - definition.used = false - end - if definition.shown == nil then - definition.shown = false - end +-- if definition.used == nil then +-- definition.used = false +-- end +-- if definition.shown == nil then +-- definition.shown = false +-- end local entries = data.entries entries[#entries+1] = spec hash[tag] = spec @@ -121,24 +121,26 @@ end function synonyms.isused(class,tag) local data = tobesaved[class] local okay = data.hash[tag] - return okay and okay.definition.used + return okay and okay.definition.used or false end function synonyms.isshown(class,tag) local data = tobesaved[class] local okay = data.hash[tag] - return okay and okay.definition.shown + return okay and okay.definition.shown or false end function synonyms.resetused(class) for tag, data in next, tobesaved[class].hash do - data.definition.used = false +-- data.definition.used = false + data.definition.used = nil end end function synonyms.resetshown(class) for tag, data in next, tobesaved[class].hash do - data.definition.shown = false +-- data.definition.shown = false + data.definition.shown = nil end end diff --git a/tex/context/base/mkiv/util-prs.lua b/tex/context/base/mkiv/util-prs.lua index 7e2bf0110..6fcc66082 100644 --- a/tex/context/base/mkiv/util-prs.lua +++ b/tex/context/base/mkiv/util-prs.lua @@ -55,9 +55,13 @@ local nobracket = 1 - (lbracket + rbracket) local escape, left, right = P("\\"), P('{'), P('}') +-- lpegpatterns.balanced = P { +-- [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, +-- [2] = left * V(1) * right +-- } lpegpatterns.balanced = P { - [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, - [2] = left * V(1) * right + ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, + left * V(1) * right } local nestedbraces = P { lbrace * (nobrace + V(1))^0 * rbrace } diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua index 9f7112eb9..a92b47b3f 100644 --- a/tex/context/base/mkiv/util-tab.lua +++ b/tex/context/base/mkiv/util-tab.lua @@ -417,9 +417,9 @@ if JITSUPPORTED then else - local f_v = formatters["[%q]=%q,"] - local f_t = formatters["[%q]="] - local f_q = formatters["%q,"] + -- local f_v = formatters["[%q]=%q,"] + -- local f_t = formatters["[%q]="] + -- local f_q = formatters["%q,"] function table.fastserialize(t,prefix) -- todo, move local function out local r = { type(prefix) == "string" and prefix or "return" } @@ -720,6 +720,7 @@ local function serialize(root,name,specification) local t -- = { } local n = 1 + -- local m = 0 -- no gain local unknown = false local function do_serialize(root,name,depth,level,indexed) @@ -850,6 +851,12 @@ local function serialize(root,name,specification) n = n + 1 t[n] = f_key_str_value_str(depth,tostring(k),tostring(v)) end end + -- if n > 100000 then -- no gain + -- local k = m + 1 + -- t[k] = concat(t,"\n",k,n) + -- n = k + -- m = k + -- end end end if level > 0 then @@ -898,6 +905,7 @@ local function serialize(root,name,specification) n = n + 1 t[n] = f_table_finish() return concat(t,"\n") + -- return concat(t,"\n",1,n) -- no gain end table.serialize = serialize diff --git a/tex/context/base/mkxl/anch-bar.mkxl b/tex/context/base/mkxl/anch-bar.mkxl index 71cc7f163..9fa9d6bf2 100644 --- a/tex/context/base/mkxl/anch-bar.mkxl +++ b/tex/context/base/mkxl/anch-bar.mkxl @@ -15,8 +15,6 @@ \unprotect -%D This can be done better now ... - %D We will implement a sidebar mechanism using the functionality from \type %D {core-pos}. %D @@ -54,6 +52,8 @@ %D \input tufte %D \stopsidebar %D \stoptyping +%D +%D This can be done better now ... maybe also by using the syncpos features. \installcorenamespace{sidebar} diff --git a/tex/context/base/mkxl/anch-bck.mklx b/tex/context/base/mkxl/anch-bck.mklx index 740ed693b..5c9382a7b 100644 --- a/tex/context/base/mkxl/anch-bck.mklx +++ b/tex/context/base/mkxl/anch-bck.mklx @@ -97,9 +97,9 @@ \installcommandhandler \??textbackground {textbackground} \??textbackground \appendtoks - \frozen\instance\setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}% - \frozen\instance\setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}% - \frozen\instance\setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}% + \frozen\instance\protected\edefcsname \currenttextbackground\endcsname{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}% + \frozen\instance\protected\edefcsname\e!start\currenttextbackground\endcsname{\starttextbackground[\currenttextbackground]}% + \frozen\instance\protected\edefcsname\e!stop \currenttextbackground\endcsname{\stoptextbackground}% \to \everydefinetextbackground \newconstant \c_anch_backgrounds_pos_state @@ -134,9 +134,11 @@ \ifparameter#settings\or \setupcurrenttextbackground[#settings]% \fi - \doifelse{\textbackgroundparameter\c!state}\v!start + \ifcstok{\textbackgroundparameter\c!state}\v!start \anch_backgrounds_text_preset_yes + \else \anch_backgrounds_text_preset_nop + \fi \anch_backgrounds_text_start_indeed} \def\anch_backgrounds_text_level_start @@ -292,10 +294,8 @@ \kern\textbackgroundskip\nobreak \fi \fi - \dosetleftskipadaption{\textbackgroundparameter\c!leftoffset}% - \advance\leftskip\leftskipadaption - \dosetleftskipadaption{\textbackgroundparameter\c!rightoffset}% - \advance\rightskip\leftskipadaption + \doadaptleftskip {\textbackgroundparameter\c!leftoffset}% + \doadaptrightskip{\textbackgroundparameter\c!rightoffset}% % new \dosetraggedcommand{\textbackgroundparameter\c!align}% \raggedcommand diff --git a/tex/context/base/mkxl/anch-pgr.mkxl b/tex/context/base/mkxl/anch-pgr.mkxl index 3c4dcf680..4ffedbfc3 100644 --- a/tex/context/base/mkxl/anch-pgr.mkxl +++ b/tex/context/base/mkxl/anch-pgr.mkxl @@ -245,7 +245,7 @@ {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% \ht\scratchbox\d_overlay_height \dp\scratchbox\zeropoint - \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox + \anch_mark_tagged_box\scratchbox\MPanchorid\zerocount % needs an hbox \box\scratchbox \vfill}} @@ -427,7 +427,7 @@ \def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups {\ifnum\MPp{#2}<\realpageno \else - \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}% + \noexpand\anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}% \fi} \appendtoks diff --git a/tex/context/base/mkxl/anch-pos.lmt b/tex/context/base/mkxl/anch-pos.lmt index 94eb443c6..5e53406da 100644 --- a/tex/context/base/mkxl/anch-pos.lmt +++ b/tex/context/base/mkxl/anch-pos.lmt @@ -6,33 +6,46 @@ if not modules then modules = { } end modules ['anch-pos'] = { license = "see context related readme files" } ---[[ldx-- -<p>We save positional information in the main utility table. Not only -can we store much more information in <l n='lua'/> but it's also -more efficient.</p> ---ldx]]-- - --- plus (extra) is obsolete but we will keep it for a while +-- We save positional information in the main utility table. Not only can we store +-- much more information in Lua but it's also more efficient. In the meantime these +-- files have become quite large. In some cases that get noticed by a hickup in the +-- start and/or finish, but that is the price we pay for progress. +-- +-- This was the last module that got rid of directly setting scanners, with a little +-- performance degradation but not that noticeable. It is also a module that has been +-- on the (partial) redo list for a while. -- --- maybe replace texsp by our own converter (stay at the lua end) --- eventually mp will have large numbers so we can use sp there too +-- We can gain a little when we group positions but then we still have to deal with +-- regions and cells so we either end up with lots of extra small tables pointing to +-- them and/or assembling/disassembling. I played with that and rejected the idea +-- until I ran into a test case where we had 50.000 one line paragraphs in an eight +-- columns setup, and there we save 25 M on a 75 M tuc file. So, I played a bit more +-- and we can have a solution that is of similar performance for regular documents +-- (in spite of the extra overhead) but also works ok for the large files. In normal +-- documents it is never a problem, but there are always exceptions to the normal and +-- often these are also cases where positions are not really used but end up in the +-- tuc file anyway. -- --- this is one of the first modules using scanners and we need to replace it by --- implement and friends +-- Currently (because we never had split tags) we do splitting at access time, which +-- is sort of inefficient but still ok. Much of this mechanism comes from MkII where +-- TeX was the bottleneck. -- --- we could have namespaces, like p, page, region, columnarea, textarea but then --- we need virtual table accessors as well as have tag/id accessors ... we don't --- save much here (at least not now) +-- By grouping we need to set more metatable so in the end that is also overhead +-- but on the average we're okay because excessive serialization also comes at a price +-- and this way we also delay some activities till the moment it is realy used (which +-- is not always the case with positional information. We will make this transition +-- stepwise so till we're done there will be inefficiencies and overhead. -- --- This was the last module that got rid of directly setting scanners, with a little --- performance degradation but not that noticeable. +-- The pure hash based variant combined with filtering is in anch-pos.lua and previous +-- lmt versions! That is the reference. -local tostring, next, setmetatable, tonumber = tostring, next, setmetatable, tonumber -local sort = table.sort +local tostring, next, setmetatable, tonumber, rawget, rawset = tostring, next, setmetatable, tonumber, rawget, rawset +local sort, sortedhash = table.sort, table.sortedhash local format, gmatch = string.format, string.gmatch -local lpegmatch = lpeg.match +local P, R, C, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.C, lpeg.Cc, lpeg.match local insert, remove = table.insert, table.remove local allocate = utilities.storage.allocate +local setmetatableindex, setmetatablenewindex = table.setmetatableindex, table.setmetatablenewindex local report = logs.reporter("positions") @@ -55,11 +68,11 @@ local texsetcount = tex.setcount local texget = tex.get local texsp = tex.sp ----- texsp = string.todimen -- because we cache this is much faster but no rounding - -local setmetatableindex = table.setmetatableindex -local setmetatablenewindex = table.setmetatablenewindex +local texgetnest = tex.getnest +local texgetparstate = tex.getparstate local nuts = nodes.nuts +local tonut = nodes.tonut local setlink = nuts.setlink local getlist = nuts.getlist @@ -67,8 +80,12 @@ local setlist = nuts.setlist local getbox = nuts.getbox local getid = nuts.getid local getwhd = nuts.getwhd +local setprop = nuts.setprop + +local getparstate = nuts.getparstate local hlist_code = nodes.nodecodes.hlist +local par_code = nodes.nodecodes.par local find_tail = nuts.tail ----- hpack = nuts.hpack @@ -85,6 +102,7 @@ local formatters = string.formatters local collected = allocate() local tobesaved = allocate() +local positionsused = false local jobpositions = { collected = collected, @@ -109,138 +127,707 @@ local default = { -- not r and paragraphs etc hs = 0, -- hsize pi = 0, -- parindent ps = false, -- parshape - dir = 0, + dir = 0, -- obsolete + r2l = false, -- righttoleft } } local f_b_tag = formatters["b:%s"] local f_e_tag = formatters["e:%s"] local f_p_tag = formatters["p:%s"] -local f_w_tag = formatters["w:%s"] +----- f_w_tag = formatters["w:%s"] local f_region = formatters["region:%s"] local f_tag_three = formatters["%s:%s:%s"] local f_tag_two = formatters["%s:%s"] -local nofregular = 0 -local nofspecial = 0 -local splitter = lpeg.splitat(":",true) - -local pagedata = { } -local columndata = setmetatableindex("table") -- per page -local freedata = setmetatableindex("table") -- per page - -local function initializer() - tobesaved = jobpositions.tobesaved - collected = jobpositions.collected - for tag, data in next, collected do - local prefix, rest = lpegmatch(splitter,tag) - if prefix == "p" then - nofregular = nofregular + 1 - elseif prefix == "page" then - nofregular = nofregular + 1 - pagedata[tonumber(rest) or 0] = data - elseif prefix == "free" then - nofspecial = nofspecial + 1 - local t = freedata[data.p or 0] - t[#t+1] = data - elseif prefix == "columnarea" then - columndata[data.p or 0][data.c or 0] = data - end - setmetatable(data,default) - end - -- - local pages = structures.pages.collected - if pages then - local last = nil - for p=1,#pages do - local region = "page:" .. p - local data = pagedata[p] - local free = freedata[p] - if free then - sort(free,function(a,b) return b.y < a.y end) -- order matters ! - end - if data then - last = data - last.free = free - elseif last then - local t = setmetatableindex({ free = free, p = p },last) - if not collected[region] then - collected[region] = t +-- Because positions are set with a delay we cannot yet make the tree -- so that +-- is a finalizer step. But, we already have a dual split. + +-- local treemode = false +local treemode = true + +local function checkshapes(s) + for p, data in next, s do + local n = #data + if n > 1 then + local d1 = data[1] + local ph = d1[2] + local pd = d1[3] + local xl = d1[4] + local xr = d1[5] + for i=2,n do + local di = data[i] + local h = di[2] + local d = di[3] + local l = di[4] + local r = di[5] + if r == xr then + di[5] = nil + if l == xl then + di[4] = nil + if d == pd then + di[3] = nil + if h == ph then + di[2] = nil + else + ph = h + end + else + pd, ph = d, h + end + else + ph, pd, xl = h, d, l + end else - -- something is wrong + ph, pd, xl, xr = h, d, l, r end - pagedata[p] = t end end end - jobpositions.pagedata = pagedata end -function jobpositions.used() - return next(collected) -- we can safe it -end +local columndata = { } +local freedata = { } -- we can make these weak +local syncdata = { } -- we can make these weak +local columndone = false -function jobpositions.getfree(page) - return freedata[page] -end +if treemode then --- we can gain a little when we group positions but then we still have to --- deal with regions and cells so we either end up with lots of extra small --- tables pointing to them and/or assembling/disassembling so in the end --- it makes no sense to do it (now) and still have such a mix --- --- proof of concept code removed ... see archive - -local function finalizer() - -- We make the (possible extensive) shape lists sparse working - -- from the end. We could also drop entries here that have l and - -- r the same which saves testing later on. - for k, v in next, tobesaved do - local s = v.s - if s then - for p, data in next, s do - local n = #data - if n > 1 then - local ph = data[1][2] - local pd = data[1][3] - local xl = data[1][4] - local xr = data[1][5] - for i=2,n do - local di = data[i] - local h = di[2] - local d = di[3] - local l = di[4] - local r = di[5] - if r == xr then - di[5] = nil - if l == xl then - di[4] = nil - if d == pd then - di[3] = nil - if h == ph then - di[2] = nil - else - ph = h + -- At some point we can install extra ones. I actually was halfway making a more + -- general installer but we have quite some distinct handling down here and it + -- became messy. So I rolled that back. Also, users and modules will quite likely + -- stay in the "user" namespace. + + -- syncpos : indirect access via helper, todo after we switch: direct setters + -- free : indirect access via helper, todo after we switch: direct setters + -- columnarea : indirect access via helper, todo after we switch: direct setters + + -- todo: keep track of total and check that against # (sanity check) + + local prefix_number = { "text", "textarea", "page", "p", "free", "columnarea" } + local prefix_label_number = { "syncpos" } + local prefix_number_rest = { "region", "b", "e" } + + -- no need to split: syncpos free columnarea (textarea?) + + local function splitter_pattern() + local p_number = R("09")^1/tonumber + local p_colon = P(":") + local p_label = C(P(1 - p_colon)^0) + local p_rest = C(P(1)^0) + return + C(lpeg.utfchartabletopattern(prefix_number )) * p_colon * p_number * P(-1) + + C(lpeg.utfchartabletopattern(prefix_label_number)) * p_colon * (p_number + p_label) * p_colon * p_number * P(-1) + + C(lpeg.utfchartabletopattern(prefix_number_rest )) * p_colon * (p_number + p_rest) + + Cc("user") * p_rest + end + + -- In the end these metatable entries are not more efficient than copying + -- but it's all about making sure that the tuc file doesn't explode. + + columndata = { } + columndone = false + + local deltapacking = true -- so we can see the difference + + local function checkcommondata(v,common) + if common then + local i = v.i + local t = common[i] + if t then + local m = t.mt + if not m then + setmetatable(t,default) + m = { __index = t } + t.mt = m + end + setmetatable(v,m) + return + end + end + setmetatable(v,default) + end + + local function initializer() + tobesaved = jobpositions.tobesaved + collected = jobpositions.collected + -- + local p_splitter = splitter_pattern() + -- + local list = nil + -- + local shared = setmetatableindex(rawget(collected,"shared"),"table") + local x_y_w_h_list = shared.x_y_w_h + local y_w_h_d_list = shared.y_w_h_d + local x_h_d_list = shared.x_h_d + local x_h_d_hs_list = shared.x_h_d_hs + -- + columndata = setmetatableindex(function(t,k) + setmetatableindex(t,"table") + list = rawget(collected,"columnarea") + if list then + -- for tag, data in next, list do + for i=1,#list do + local data = list[i] + columndata[data.p or 0][data.c or 0] = data + checkcommondata(data,y_w_h_d_list) + end + end + columndone = true + return t[k] + end) + -- + -- todo: use a raw collected and a weak proxy + -- + setmetatableindex(collected,function(t,k) + local prefix, one, two = lpegmatch(p_splitter,k) + local list = rawget(t,prefix) + if list and type(list) == "table" then + v = list[one] or false + if v then + if prefix == "p" then + if deltapacking and type(v) == "number" then + for i=one,1,-1 do + local l = list[i] + if type(l) ~= "number" then + if not getmetatable(l) then + checkcommondata(l,x_h_d_hs_list) end - else - pd, ph = d, h + v = setmetatable({ y = v }, { __index = l }) + list[one] = v + break + end + end + else + checkcommondata(v,x_h_d_hs_list) + end + elseif prefix == "text" or prefix == "textarea" then + if type(v) == "number" then + for i=one,1,-1 do + local l = list[i] + if type(l) ~= "number" then + if not getmetatable(l) then + checkcommondata(l,x_y_w_h_list) + end + v = setmetatable({ p = p }, { __index = l }) + list[one] = v + break end - else - ph, pd, xl = h, d, l end else - ph, pd, xl, xr = h, d, l, r + checkcommondata(v,x_y_w_h_list) + end + elseif prefix == "columnarea" then + if not columndone then + checkcommondata(v,y_w_h_d_list) + end + elseif prefix == "syncpos" then + -- will become an error + if two then + -- v = syncdata[one][two] or { } + v = v[two] or { } + else + v = { } + end + -- for j=1,#v do + -- checkcommondata(v[j],x_h_d_list) + -- end + elseif prefix == "free" then + -- will become an error + elseif prefix == "page" then + checkcommondata(v) + else + checkcommondata(v) + end + else + if prefix == "page" then + for i=one,1,-1 do + local data = list[i] + if data then + v = setmetatableindex({ free = free or false, p = p },last) + list[one] = v + break + end + end + end + end + t[k] = v + return v + else + t[k] = false + return false + end + end) + -- + setmetatableindex(tobesaved,function(t,k) + local prefix, one, two = lpegmatch(p_splitter,k) + local v = rawget(t,prefix) + if v and type(v) == "table" then + v = v[one] + if v and two then + v = v[two] + end + return v -- or default + else + -- return default + end + end) + -- + setmetatablenewindex(tobesaved,function(t,k,v) + local prefix, one, two = lpegmatch(p_splitter,k) + local p = rawget(t,prefix) + if not p then + p = { } + rawset(t,prefix,p) + end + if type(one) == "number" then -- maybe Cc(0 1 2) + if #p < one then + for i=#p+1,one-1 do + p[i] = { } -- false + end + end + end + if two then + local pone = p[one] + if not pone then + pone = { } + p[one] = pone + end + if type(two) == "number" then -- maybe Cc(0 1 2) + if #pone < two then + for i=#pone+1,two-1 do + pone[i] = { } -- false + end + end + end + pone[two] = v + else + p[one] = v + end + end) + -- + syncdata = setmetatableindex(function(t,category) + -- p's and y's are not shared so no need to resolve + local list = rawget(collected,"syncpos") + local tc = list and rawget(list,category) + if tc then + sort(tc,function(a,b) + local ap = a.p + local bp = b.p + if ap == bp then + return b.y < a.y + else + return ap < bp + end + end) + tc.start = 1 + for i=1,#tc do + checkcommondata(tc[i],x_h_d_list) + end + else + tc = { } + end + t[category] = tc + return tc + end) + -- + for k, v in next, collected do + if k ~= "shared" and next(v) then + positionsused = true + break + end + end + end + + function jobpositions.used() + return positionsused + end + + local function finalizer() + + -- We make the (possible extensive) shape lists sparse working from the end. We + -- could also drop entries here that have l and r the same which saves testing + -- later on. + + local nofpositions = 0 + local nofpartials = 0 + local nofdeltas = 0 + -- + local x_y_w_h_size = 0 + local x_y_w_h_list = { } + local x_y_w_h_hash = setmetatableindex(function(t,x) + local y = setmetatableindex(function(t,y) + local w = setmetatableindex(function(t,w) + local h = setmetatableindex(function(t,h) + x_y_w_h_size = x_y_w_h_size + 1 + t[h] = x_y_w_h_size + x_y_w_h_list[x_y_w_h_size] = { x = x, y = y, w = w, h = h } + return x_y_w_h_size + end) + t[w] = h + return h + end) + t[y] = w + return w + end) + t[x] = y + return y + end) + -- + local y_w_h_d_size = 0 + local y_w_h_d_list = { } + local y_w_h_d_hash = setmetatableindex(function(t,y) + local w = setmetatableindex(function(t,w) + local h = setmetatableindex(function(t,h) + local d = setmetatableindex(function(t,d) + y_w_h_d_size = y_w_h_d_size + 1 + t[d] = y_w_h_d_size + y_w_h_d_list[y_w_h_d_size] = { y = y, w = w, h = h, d = d } + return y_w_h_d_size + end) + t[h] = d + return d + end) + t[w] = h + return h + end) + t[y] = w + return w + end) + -- + local x_h_d_size = 0 + local x_h_d_list = { } + local x_h_d_hash = setmetatableindex(function(t,x) + local h = setmetatableindex(function(t,h) + local d = setmetatableindex(function(t,d) + x_h_d_size = x_h_d_size + 1 + t[d] = x_h_d_size + x_h_d_list[x_h_d_size] = { x = x, h = h, d = d } + return x_h_d_size + end) + t[h] = d + return d + end) + t[x] = h + return h + end) + -- + local x_h_d_hs_size = 0 + local x_h_d_hs_list = { } + local x_h_d_hs_hash = setmetatableindex(function(t,x) + local h = setmetatableindex(function(t,h) + local d = setmetatableindex(function(t,d) + local hs = setmetatableindex(function(t,hs) + x_h_d_hs_size = x_h_d_hs_size + 1 + t[hs] = x_h_d_hs_size + x_h_d_hs_list[x_h_d_hs_size] = { x = x, h = h, d = d, hs = hs } + return x_h_d_hs_size + end) + t[d] = hs + return hs + end) + t[h] = d + return d + end) + t[x] = h + return h + end) + -- + rawset(tobesaved,"shared", { + x_y_w_h = x_y_w_h_list, + y_w_h_d = y_w_h_d_list, + x_h_d = x_h_d_list, + x_h_d_hs = x_h_d_hs_list, + }) + -- + -- If fonts can use crazy and hard to grasp packing tricks so can we. The "i" field + -- refers to a shared set of values. In addition we pack some sequences. + -- + -- how about free + -- + for k, v in sortedhash(tobesaved) do + if k == "p" then + -- numeric + local n = #v + for i=1,n do + local t = v[i] + local hsh = x_h_d_hs_hash[t.x or 0][t.h or 0][t.d or 0][t.hs or 0] + t.x = nil + t.h = nil + t.d = nil + t.hs = nil -- not in syncpos + t.i = hsh + local s = t.s + if s then + checkshapes(s) + end + end + if deltapacking then + -- delta packing (y) + local last + local current + for i=1,n do + current = v[i] + if last then + for k, v in next, last do + if k ~= "y" and v ~= current[k] then + goto DIFFERENT + end + end + for k, v in next, current do + if k ~= "y" and v ~= last[k] then + goto DIFFERENT + end + end + v[i] = current.y or 0 + nofdeltas = nofdeltas + 1 + goto CONTINUE + end + ::DIFFERENT:: + last = current + ::CONTINUE:: + end + end + -- + nofpositions = nofpositions + n + nofpartials = nofpartials + n + elseif k == "syncpos" then + -- hash + for k, t in next, v do + -- numeric + local n = #t + for j=1,n do + local t = t[j] + local hsh = x_h_d_hash[t.x or 0][t.h or 0][t.d or 0] + t.x = nil + t.h = nil + t.d = nil + t.i = hsh + end + nofpositions = nofpositions + n + nofpartials = nofpartials + n + end + elseif k == "text" or k == "textarea" then + -- numeric + local n = #v + for i=1,n do + local t = v[i] + local hsh = x_y_w_h_hash[t.x or 0][t.y or 0][t.w or 0][t.h or 0] + t.x = nil + t.y = nil + t.w = nil + t.h = nil + t.i = hsh + end + nofpositions = nofpositions + n + nofpartials = nofpartials + n + if deltapacking then + -- delta packing (p) + local last + local current + for i=1,n do + current = v[i] + if last then + for k, v in next, last do + if k ~= "p" and v ~= current[k] then + goto DIFFERENT + end + end + for k, v in next, current do + if k ~= "p" and v ~= last[k] then + goto DIFFERENT + end + end + v[i] = current.p or 0 + nofdeltas = nofdeltas + 1 + goto CONTINUE end + ::DIFFERENT:: + last = current + ::CONTINUE:: end end + elseif k == "columnarea" then + -- numeric + local n = #v + for i=1,n do + local t = v[i] + local hsh = y_w_h_d_hash[t.y or 0][t.w or 0][t.h or 0][t.d or 0] + t.y = nil + t.w = nil + t.h = nil + t.d = nil + t.i = hsh + end + nofpositions = nofpositions + n + nofpartials = nofpartials + n + else -- probably only b has shapes + for k, t in next, v do -- no need to sort + local s = t.s + if s then + checkshapes(s) + end + nofpositions = nofpositions + 1 + end end end + + statistics.register("positions", function() + if nofpositions > 0 then + return format("%s collected, %i deltas, %i shared partials, %i partial entries", + nofpositions, nofdeltas, nofpartials, + x_y_w_h_size + y_w_h_d_size + x_h_d_size + x_h_d_hs_size + ) + else + return nil + end + end) + end + + freedata = setmetatableindex(function(t,page) + local list = rawget(collected,"free") + local free = { } + if list then + local size = 0 + for i=1,#list do + local l = list[i] + if l.p == page then + size = size + 1 + free[size] = l + checkcommondata(l) + end + end + sort(free,function(a,b) return b.y < a.y end) -- order matters ! + end + t[page] = free + return free + end) + + job.register('job.positions.collected', tobesaved, initializer, finalizer) + +else + + columndata = setmetatableindex("table") -- per page + freedata = setmetatableindex("table") -- per page + + local function initializer() + tobesaved = jobpositions.tobesaved + collected = jobpositions.collected + -- + local pagedata = { } + local p_splitter = lpeg.splitat(":",true) + + for tag, data in next, collected do + local prefix, rest = lpegmatch(p_splitter,tag) + if prefix == "page" then + pagedata[tonumber(rest) or 0] = data + elseif prefix == "free" then + local t = freedata[data.p or 0] + t[#t+1] = data + elseif prefix == "columnarea" then + columndata[data.p or 0][data.c or 0] = data + end + setmetatable(data,default) + end + local pages = structures.pages.collected + if pages then + local last = nil + for p=1,#pages do + local region = "page:" .. p + local data = pagedata[p] + local free = freedata[p] + if free then + sort(free,function(a,b) return b.y < a.y end) -- order matters ! + end + if data then + last = data + last.free = free + elseif last then + local t = setmetatableindex({ free = free, p = p },last) + if not collected[region] then + collected[region] = t + else + -- something is wrong + end + pagedata[p] = t + end + end + end + jobpositions.pagedata = pagedata -- never used + + end + + local function finalizer() + + -- We make the (possible extensive) shape lists sparse working from the end. We + -- could also drop entries here that have l and r the same which saves testing + -- later on. + + local nofpositions = 0 + + for k, v in next, tobesaved do + local s = v.s + if s then + checkshapes(s) + end + nofpositions = nofpositions + 1 + end + + statistics.register("positions", function() + if nofpositions > 0 then + return format("%s collected",nofpositions) + else + return nil + end + end) + + end + + local p_number = lpeg.patterns.cardinal/tonumber + local p_tag = P("syncpos:") * p_number * P(":") * p_number + + syncdata = setmetatableindex(function(t,category) + setmetatable(t,nil) + for tag, pos in next, collected do + local c, n = lpegmatch(p_tag,tag) + if c then + local tc = t[c] + if tc then + tc[n] = pos + else + t[c] = { [n] = pos } + end + end + end + for k, list in next, t do + sort(list,function(a,b) + local ap = a.p + local bp = b.p + if ap == bp then + return b.y < a.y + else + return ap < bp + end + end) + list.start = 1 + end + return t[category] + end) + + job.register('job.positions.collected', tobesaved, initializer, finalizer) + +end + +function jobpositions.getfree(page) + return freedata[page] end -job.register('job.positions.collected', tobesaved, initializer, finalizer) +function jobpositions.getsync(category) + return syncdata[category] or { } +end local regions = { } local nofregions = 0 @@ -491,7 +1078,6 @@ local function e_region(specification) local last = tobesaved[region] if last then local y = getvpos() - local x, y = getpos() if specification.correct then local h = (last.y or 0) - y last.h = h ~= 0 and h or nil @@ -507,13 +1093,22 @@ jobpositions.e_region = e_region local lastregion -local function setregionbox(n,tag,k,lo,ro,to,bo,column) -- kind +local function setregionbox(n,tag,index,k,lo,ro,to,bo,column) -- kind if not tag or tag == "" then nofregions = nofregions + 1 - tag = f_region(nofregions) + tag = "region" + index = nofregions + elseif index ~= 0 then + -- So we can cheat and pass a zero index and enforce tag as is needed in + -- cases where we fallback on automated region tagging (framed). + tag = tag .. ":" .. index end local box = getbox(n) local w, h, d = getwhd(box) + -- We could set directly but then we also need to check for gaps but as this + -- is direct is is unlikely that we get a gap. We then also need to intecept + -- these auto regions (comning from framed). Too messy and the split in the + -- setter is fast enough. tobesaved[tag] = { -- p = texgetcount("realpageno"), -- we copy them x = 0, @@ -532,8 +1127,18 @@ local function setregionbox(n,tag,k,lo,ro,to,bo,column) -- kind return tag, box end -local function markregionbox(n,tag,correct,...) -- correct needs checking - local tag, box = setregionbox(n,tag,...) +-- we can have a finalizer property that we catch in the backend but that demands +-- a check for property for each list .. what is the impact + +-- textarea operates *inside* a box so experiments with pre/post hooks in the +-- backend driver didn't work out (because a box can be larger) +-- +-- it also gives no gain to split prefix and number here because in the end we +-- push and pop tags as strings, but it save a little on expansion so we do it +-- in the interface + +local function markregionbox(n,tag,index,correct,...) -- correct needs checking + local tag, box = setregionbox(n,tag,index,...) -- todo: check if tostring is needed with formatter local push = new_latelua { action = b_region, tag = tag } local pop = new_latelua { action = e_region, correct = correct } @@ -577,195 +1182,290 @@ function jobpositions.settobesaved(name,tag,data) end end -local nofparagraphs = 0 +do -implement { - name = "parpos", - actions = function() - nofparagraphs = nofparagraphs + 1 - texsetcount("global","c_anch_positions_paragraph",nofparagraphs) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local t = { - p = true, - c = true, - r = true, - x = true, - y = true, - h = h, - d = d, - hs = texget("hsize"), -- never 0 - } - local leftskip = texget("leftskip",false) - local rightskip = texget("rightskip",false) - local hangindent = texget("hangindent") - local hangafter = texget("hangafter") - local parindent = texget("parindent") - local parshape = texget("parshape") - if leftskip ~= 0 then - t.ls = leftskip - end - if rightskip ~= 0 then - t.rs = rightskip - end - if hangindent ~= 0 then - t.hi = hangindent + local nofparagraphs = 0 + + local function enhancepar_1(data) + if data then + local par = data.par -- we can pass twice when we copy + local state = par and getparstate(data.par,true) + if state then + local x, y = getpos() + if x ~= 0 then + data.x = x + end + if y ~= 0 then + data.y = y + end + data.p = texgetcount("realpageno") -- we should use a variable set in otr + if column then + data.c = column + end + if region then + data.r = region + end + -- + data.par = nil + local leftskip = state.leftskip + local rightskip = state.rightskip + local hangindent = state.hangindent + local hangafter = state.hangafter + local parindent = state.parindent + local parshape = state.parshape + if hangafter ~= 0 and hangafter ~= 1 then + data.ha = hangafter + end + if hangindent ~= 0 then + data.hi = hangindent + end + data.hs = state.hsize + if leftskip ~= 0 then + data.ls = leftskip + end + if parindent ~= 0 then + data.pi = parindent + end + if rightskip ~= 0 then + data.rs = rightskip + end + if parshape and #parshape > 0 then + data.ps = parshape + end + end end - if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero - t.ha = hangafter + return data + end + + local function enhancepar_2(data) + if data then + local x, y = getpos() + if x ~= 0 then + data.x = x + end + if y ~= 0 then + data.y = y + end + data.p = texgetcount("realpageno") -- we should use a variable set in otr + if column then + data.c = column + end + if region then + data.r = region + end end - if parindent ~= 0 then - t.pi = parindent + return data + end + + implement { + name = "parpos", + actions = function() + nofparagraphs = nofparagraphs + 1 + texsetcount("global","c_anch_positions_paragraph",nofparagraphs) + local name = f_p_tag(nofparagraphs) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + -- + local top = texgetnest("top","head") + local nxt = top.next + if nxt then + nxt = tonut(nxt) + end + local data + if nxt and getid(nxt) == par_code then -- todo: check node type + local t = { + h = h, + d = d, + par = nxt, + } + tobesaved[name] = t + ctx_latelua { action = enhancepar_1, specification = t } + else + -- This is kind of weird but it happens in tables (rows) so we probably + -- need less. + local state = texgetparstate() + local leftskip = state.leftskip + local rightskip = state.rightskip + local hangindent = state.hangindent + local hangafter = state.hangafter + local parindent = state.parindent + local parshape = state.parshape + local t = { + p = true, + c = true, + r = true, + x = true, + y = true, + h = h, + d = d, + hs = state.hsize, -- never 0 + } + if leftskip ~= 0 then + t.ls = leftskip + end + if rightskip ~= 0 then + t.rs = rightskip + end + if hangindent ~= 0 then + t.hi = hangindent + end + if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero + t.ha = hangafter + end + if parindent ~= 0 then + t.pi = parindent + end + if parshape and #parshape > 0 then + t.ps = parshape + end + tobesaved[name] = t + ctx_latelua { action = enhancepar_2, specification = t } + end end - if parshape and #parshape > 0 then - t.ps = parshape + } + + implement { + name = "dosetposition", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } end - local name = f_p_tag(nofparagraphs) - tobesaved[name] = t - ctx_latelua { action = enhance, specification = t } - end -} + } -implement { - name = "dosetposition", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} + implement { + name = "dosetpositionwhd", + arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, + public = true, + protected = true, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end + } -implement { - name = "dosetpositionwhd", - arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, - public = true, - protected = true, - actions = function(name,w,h,d) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} + implement { + name = "dosetpositionbox", + arguments = { "argument", "integerargument" }, + public = true, + protected = true, + actions = function(name,n) + local box = getbox(n) + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end + } -implement { - name = "dosetpositionbox", - arguments = { "argument", "integerargument" }, - public = true, - protected = true, - actions = function(name,n) - local box = getbox(n) - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} + implement { + name = "dosetpositionplus", + arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, + public = true, + protected = true, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + e = scanstring(), + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end + } -implement { - name = "dosetpositionplus", - arguments = { "argument", "dimenargument", "dimenargument", "dimenargument" }, - public = true, - protected = true, - actions = function(name,w,h,d) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - e = scanstring(), - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} + implement { + name = "dosetpositionstrut", + arguments = "argument", + public = true, + protected = true, + actions = function(name) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end + } -implement { - name = "dosetpositionstrut", - arguments = "argument", - public = true, - protected = true, - actions = function(name) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} + implement { + name = "dosetpositionstrutkind", + arguments = { "argument", "integerargument" }, + public = true, + protected = true, + actions = function(name,kind) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + k = kind, + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end + } -implement { - name = "dosetpositionstrutkind", - arguments = { "argument", "integerargument" }, - public = true, - protected = true, - actions = function(name,kind) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - k = kind, - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetinteger("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } - end -} +end function jobpositions.getreserved(tag,n) if tag == v_column then @@ -1384,18 +2084,18 @@ implement { actions = MPpardata } -implement { - name = "MPposset", - arguments = "argument", - public = true, - actions = function(name) - local b = f_b_tag(name) - local e = f_e_tag(name) - local w = f_w_tag(name) - local p = f_p_tag(getparagraph(b)) - MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) - end -} +-- implement { +-- name = "MPposset", +-- arguments = "argument", +-- public = true, +-- actions = function(name) +-- local b = f_b_tag(name) +-- local e = f_e_tag(name) +-- local w = f_w_tag(name) +-- local p = f_p_tag(getparagraph(b)) +-- MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) +-- end +-- } implement { name = "MPls", @@ -1451,7 +2151,7 @@ implement { implement { name = "MPrest", - arguments = { "argument", "argument" }, + arguments = "2 arguments", public = true, actions = function(name,default) local jpi = collected[name] @@ -1515,7 +2215,7 @@ implement { implement { name = "doifelseoverlapping", - arguments = { "argument", "argument" }, + arguments = "2 arguments", public = true, protected = true, actions = function(one,two) @@ -1548,53 +2248,53 @@ implement { public = true, protected = true, actions = function() - doifelse(next(collected)) + doifelse(positionsused) end } implement { name = "markregionbox", - arguments = "integer", + arguments = { "integer", "integer" }, actions = markregionbox } implement { name = "setregionbox", - arguments = "integer", + arguments = { "integer", "integer" }, actions = setregionbox } implement { name = "markregionboxtagged", - arguments = { "integer", "string" }, + arguments = { "integer", "string", "integer" }, actions = markregionbox } implement { name = "markregionboxtaggedn", - arguments = { "integer", "string", "integer" }, - actions = function(box,tag,n) - markregionbox(box,tag,nil,nil,nil,nil,nil,nil,n) + arguments = { "integer", "string", "integer", "integer" }, + actions = function(box,tag,index,n) + markregionbox(box,tag,index,nil,nil,nil,nil,nil,nil,n) end } implement { name = "setregionboxtagged", - arguments = { "integer", "string" }, + arguments = { "integer", "string", "integer" }, actions = setregionbox } implement { name = "markregionboxcorrected", - arguments = { "integer", "string", true }, + arguments = { "integer", "string", "integer", true }, actions = markregionbox } implement { name = "markregionboxtaggedkind", - arguments = { "integer", "string", "integer", "dimen", "dimen", "dimen", "dimen" }, - actions = function(box,tag,n,d1,d2,d3,d4) - markregionbox(box,tag,nil,n,d1,d2,d3,d4) + arguments = { "integer", "string", "integer", "integer", "dimen", "dimen", "dimen", "dimen" }, + actions = function(box,tag,index,n,d1,d2,d3,d4) + markregionbox(box,tag,index,nil,n,d1,d2,d3,d4) end } @@ -1607,27 +2307,6 @@ implement { end } --- statistics (at least for the moment, when testing) - --- statistics.register("positions", function() --- local total = nofregular + nofusedregions + nofmissingregions --- if total > 0 then --- return format("%s collected, %s regulars, %s regions, %s unresolved regions", --- total, nofregular, nofusedregions, nofmissingregions) --- else --- return nil --- end --- end) - -statistics.register("positions", function() - local total = nofregular + nofspecial - if total > 0 then - return format("%s collected, %s regular, %s special",total,nofregular,nofspecial) - else - return nil - end -end) - -- We support the low level positional commands too: local newsavepos = nodes.pool.savepos diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl index 2bf7fab6f..70197e93e 100644 --- a/tex/context/base/mkxl/anch-pos.mkxl +++ b/tex/context/base/mkxl/anch-pos.mkxl @@ -164,7 +164,7 @@ {\anch_positions_initialize \hbox % \hpack {\edef\currentposition{#1}% - \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr + \dosetpositionwhd\currentposition{#2}{#3}{#4}% \anch_positions_trace_left \dopositionaction\currentposition \hss}} @@ -184,7 +184,8 @@ \def\anch_positions_set_box_finish#1% {\anch_positions_initialize - \hbox to \wd\nextbox % \hpack + %\hbox to \wd\nextbox + \hpack to \wd\nextbox {\edef\currentposition{#1}% \dosetpositionbox\currentposition\nextbox \anch_positions_trace_left @@ -244,7 +245,7 @@ {\anch_positions_initialize \hbox % \hpack {\edef\currentposition{#1}% - \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr + \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% \anch_positions_trace_right \dopositionaction\currentposition \hss}} @@ -288,12 +289,15 @@ % Is this really always needed? We use \enabletextarearegistration for page areas so why % not also for this. +% +% At some point we can switch to dedicated markers because there are not +% that many variants: text, page, textarea, columnarea, free. \protected\def\anch_mark_column_box#1#2% box n {\global\advance\c_anch_column\plusone - \clf_markregionboxtaggedn#1{columnarea:\the\c_anch_column}#2\relax} % extra height + \clf_markregionboxtaggedn#1{columnarea}\c_anch_column#2\relax} % extra height -\protected\def\anch_mark_region_box +\protected\def\anch_mark_region_box % auto region:index {\iftrialtypesetting \expandafter\gobbleoneargument \orelse\ifpositioning @@ -308,38 +312,45 @@ \protected\def\anch_mark_flow_box#1% will be extended / renamed {\hpack\bgroup \global\advance\c_anch_text\plusone - \clf_markregionboxtagged#1{textarea:\the\c_anch_text}% + \clf_markregionboxtagged#1{textarea}\c_anch_text % will become flow: \box#1% \egroup} -\protected\def\anch_mark_tagged_box#1#2% - {\clf_markregionboxtagged#1{#2}} +\protected\def\anch_mark_tagged_box#1#2#3% + {\clf_markregionboxtagged#1{#2}#3\relax} \protected\def\anch_mark_flow_only#1% will be extended / renamed {\global\advance\c_anch_text\plusone - \clf_markregionboxcorrected#1{textarea:\the\c_anch_text}} + \clf_markregionboxcorrected#1{textarea}\c_anch_text}% will become flow: \protected\def\anch_make_page_box#1% maybe like text - {\clf_setregionboxtagged#1{page:\the\realpageno}} + {\clf_setregionboxtagged#1{page}\realpageno} \protected\def\anch_mark_text_box#1% - {\clf_markregionboxtagged#1{text:\the\realpageno}} % needs an hbox + {\clf_markregionboxtagged#1{text}\realpageno} % needs an hbox -\newcount\c_anch_free - -\protected\def\anch_mark_tagged_box_free#1#2#3#4#5#6% only needed when positions +\protected\def\anch_mark_tagged_box_free {\ifpositioning - \global\advance\c_anch_free\plusone % could be done at the lua end - \clf_markregionboxtaggedkind - #1% - {free:\number\c_anch_free}% - #2\space % kind - #3\space % leftoffset - #4\space % rightoffset - #5\space % topoffset - #6\relax % bottomoffset + \expandafter\anch_mark_tagged_box_free_yes + \else + \expandafter\gobblesixarguments \fi} +\newcount\c_anch_free + +\protected\def\anch_mark_tagged_box_free_yes#1#2#3#4#5#6% only needed when positions + {\global\advance\c_anch_free\plusone % could be done at the lua end + \clf_markregionboxtaggedkind + #1% + {free}% + \c_anch_free + #2% kind % single token value + #3% leftoffset % single token value + #4% rightoffset % single token value + #5% topoffset % single token value + #6% bottomoffset % single token value + \relax} + % \reservedautoregiontag % define at lua end %D We can copy a position with: diff --git a/tex/context/base/mkxl/anch-snc.lmt b/tex/context/base/mkxl/anch-snc.lmt index 57789a5a0..c97be2b39 100644 --- a/tex/context/base/mkxl/anch-snc.lmt +++ b/tex/context/base/mkxl/anch-snc.lmt @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['anch-snc'] = { license = "see context related readme files" } -local tonumber, next, setmetatable = tonumber, next, setmetatable +local tonumber, next, setmetatable, rawget = tonumber, next, setmetatable, rawget local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy local match, find = string.match, string.find local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns @@ -17,9 +17,10 @@ graphics = graphics or { } local synchronizers = { } graphics.synchronizers = synchronizers +local jobpositions = job.positions + local p_number = lpegpatterns.cardinal/tonumber local p_space = lpegpatterns.whitespace^0 -local p_tag = P("syncpos:") * p_number * P(":") * p_number local p_option = p_number * ((P(",") * p_space * P("reset") * Cc(true)) + Cc(false)) -- for now local list = { } @@ -31,39 +32,10 @@ local kinds = { below = 5, } -local allentries = setmetatableindex(function(t,category) - setmetatable(t,nil) - for tag, pos in next, job.positions.collected do - local c, n = lpegmatch(p_tag,tag) - if c then - local tc = t[c] - if tc then - tc[n] = pos - else - t[c] = { [n] = pos } - end - end - end - for k, list in next, t do - sort(list,function(a,b) - local ap = a.p - local bp = b.p - if ap == bp then - return b.y < a.y - else - return ap < bp - end - end) - list.start = 1 - end - setmetatableindex(t,"table") - return t[category] -end) - local lastdone = { } function synchronizers.collect(category,realpage,region) - local all = allentries[category] + local all = jobpositions.getsync(category) local m = 0 local n = #all list = { } @@ -78,7 +50,7 @@ function synchronizers.collect(category,realpage,region) local r = pos.r if r == region then if not done then - local region = job.positions.collected[r] + local region = jobpositions.collected[r] list.region = region list.page = region rtop = (region.y or 0) + (region.h or 0) @@ -106,8 +78,8 @@ function synchronizers.collect(category,realpage,region) local p = pos.p if p == realpage then if not done then - local region = job.positions.collected[pos.r] - local page = job.positions.collected["page:"..realpage] or region + local region = jobpositions.collected[pos.r] + local page = jobpositions.collected["page:"..realpage] or region list.region = region list.page = page rtop = (region.y or 0) + (region.h or 0) @@ -224,6 +196,8 @@ function synchronizers.collapse() return n end +-- These operate on the currently set list: + function synchronizers.getsize () return #list end function synchronizers.gettop (n) return list[n].top end function synchronizers.getbottom(n) return list[n].bottom end diff --git a/tex/context/base/mkxl/anch-snc.mkxl b/tex/context/base/mkxl/anch-snc.mkxl index 436305634..dcf2c86cb 100644 --- a/tex/context/base/mkxl/anch-snc.mkxl +++ b/tex/context/base/mkxl/anch-snc.mkxl @@ -125,10 +125,12 @@ %D \stoptext %D \stoptyping +%D We could actually use par positions but in \LMTX\ we have syncpos entries +%D somewhat optimized. + \unprotect -\ifdefined\??syncposcounter \else \installcorenamespace{syncposcounter} \fi -\ifdefined\s!syncpos \else \def\s!syncpos {syncpos} \fi +\installcorenamespace{syncposcounter} \let\c_sync_n\relax @@ -137,7 +139,7 @@ \expandafter\newcount\csname\??syncposcounter:#1\endcsname \fi} -\permanent\tolerant\protected\def\syncposition[#1]#*[#2]% we could actually use par positions +\permanent\tolerant\protected\def\syncposition[#1]#*[#2]% {\dontleavehmode \ifcsname\??syncposcounter:#1\endcsname \let\c_sync_n\lastnamedcs diff --git a/tex/context/base/mkxl/back-exp.lmt b/tex/context/base/mkxl/back-exp.lmt index a465cee92..de1a1830e 100644 --- a/tex/context/base/mkxl/back-exp.lmt +++ b/tex/context/base/mkxl/back-exp.lmt @@ -334,9 +334,9 @@ local styletemplate <const> = [[ local numbertoallign = { [0] = "justify", ["0"] = "justify", [variables.normal ] = "justify", - [1] = "right", ["1"] = "right", [variables.flushright] = "right", - [2] = "center", ["2"] = "center", [variables.middle ] = "center", - [3] = "left", ["3"] = "left", [variables.flushleft ] = "left", + "right", ["1"] = "right", [variables.flushright] = "right", + "center", ["2"] = "center", [variables.middle ] = "center", + "left", ["3"] = "left", [variables.flushleft ] = "left", } function wrapups.allusedstyles(filename) diff --git a/tex/context/base/mkxl/buff-ini.mkxl b/tex/context/base/mkxl/buff-ini.mkxl index a91e3272b..ed16bd6e3 100644 --- a/tex/context/base/mkxl/buff-ini.mkxl +++ b/tex/context/base/mkxl/buff-ini.mkxl @@ -115,7 +115,8 @@ \setupbuffer [\c!before=, - \c!after=] + \c!after=, + \c!define=\v!yes] \newcount\c_buff_n_of_defined @@ -125,8 +126,12 @@ \global\advance\c_buff_n_of_defined\plusone \setexpandedbufferparameter\c!number{\number\c_buff_n_of_defined}% \edef\currentdefinedbuffer{def-\number\c_buff_n_of_defined}% - \frozen\instance\setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}% - \frozen\instance\setuevalue{\e!get \currentbuffer}{\buff_get_stored {\currentbuffer}{\currentdefinedbuffer}}% + \ifcstok{\bufferparameter\c!define}\v!yes + \frozen\instance\protected\edefcsname\e!start\currentbuffer\endcsname + {\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}% + \frozen\instance\protected\edefcsname\e!get \currentbuffer\endcsname + {\buff_get_stored {\currentbuffer}{\currentdefinedbuffer}}% + \fi \to \everydefinebuffer \protected\def\buff_start_defined diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 74d3aa873..7b5f090d9 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.08.10 12:37} +\newcontextversion{2021.08.19 19:40} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/cont-run.lmt b/tex/context/base/mkxl/cont-run.lmt index a256a4104..448992b4b 100644 --- a/tex/context/base/mkxl/cont-run.lmt +++ b/tex/context/base/mkxl/cont-run.lmt @@ -219,6 +219,14 @@ local function processjob() environment.lmtxmode = CONTEXTLMTXMODE -- should be true + -- directives + -- silent + -- batchmode + +if arguments.directives then + directives.enable(arguments.directives) +end + if arguments.nosynctex then luatex.synctex.setup { state = interfaces.variables.never, diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 91ec43d30..978808ec5 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.08.10 12:37} +\immutable\edef\contextversion{2021.08.19 19:40} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/core-sys.mkxl b/tex/context/base/mkxl/core-sys.mkxl index a0bd9debd..b8bd7905e 100644 --- a/tex/context/base/mkxl/core-sys.mkxl +++ b/tex/context/base/mkxl/core-sys.mkxl @@ -257,7 +257,8 @@ \appendtoks \ifcstok{\highlightparameter\c!define}\v!yes - \frozen\instance\setuevalue\currenthighlight{\typo_highlights_indeed{\currenthighlight}}% + \frozen\instance\protected\edefcsname\currenthighlight\endcsname + {\typo_highlights_indeed{\currenthighlight}}% \fi \to \everydefinehighlight @@ -291,6 +292,7 @@ \aliased\let\directhighlight\typo_highlights_indeed +%D Defining commands (rather old): \permanent\protected\def\defineexpandable {\integerdef\c_syst_parameter_catcode\catcode\hashasciicode diff --git a/tex/context/base/mkxl/core-uti.lmt b/tex/context/base/mkxl/core-uti.lmt index 1bb50060d..de514df30 100644 --- a/tex/context/base/mkxl/core-uti.lmt +++ b/tex/context/base/mkxl/core-uti.lmt @@ -19,7 +19,7 @@ saves much runtime but at the cost of more memory usage.</p> local math = math local format, match = string.format, string.match -local next, type, tostring, tonumber = next, type, tostring, tonumber +local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable local concat = table.concat local definetable = utilities.tables.definetable @@ -43,7 +43,7 @@ local report_passes = logs.reporter("job","passes") job = job or { } local job = job -job.version = 1.32 +job.version = 1.33 job.packversion = 1.02 -- some day we will implement loading of other jobs and then we need @@ -209,6 +209,67 @@ local skiplist = { "positions", } +-- I'm not that impressed by the savings. It's some 5 percent on the luametatex +-- manual and probably some more on the m4 files (if so I might enable it). + +local deltapacking = false +-- local deltapacking = true + +local function packnumberdata(tobesaved) + if deltapacking and tobesaved[1] then + local last + local current + for i=1,#tobesaved do + current = tobesaved[i] + if last then + if last.numbers and last.block then + for k, v in next, last do + if k ~= "numbers" and v ~= current[k] then + goto DIFFERENT + end + end + for k, v in next, current do + if k ~= "numbers" and v ~= last[k] then + goto DIFFERENT + end + end + tobesaved[i] = { + numbers = current.numbers, + } + goto CONTINUE + else + current = nil + end + end + ::DIFFERENT:: + last = current + ::CONTINUE:: + end + end +end + +local function unpacknumberdata(collected) + if deltapacking and collected[1] then + local key = "numbers" + local last = collected[1] + local meta = false + for i=2,#collected do + local c = collected[i] + if c.block then + last = c + meta = false + elseif c.numbers then + if not meta then + meta = { __index = last } + end + setmetatable(c, meta) + end + end + end +end + +-- -- -- + -- not ok as we can have arbitrary keys in userdata and dataset so some day we -- might need a bit more granularity, like skippers @@ -253,6 +314,7 @@ function job.save(filename) -- we could return a table but it can get pretty lar end if job.pack then packers.strip(jobpacker) +packnumberdata(jobpacker.index) -- f:write("do\n\n") f:write(serialize(jobpacker,"utilitydata.job.packed",true),"\n\n") -- f:write("end\n\n") @@ -265,7 +327,6 @@ end local function load(filename) if lfs.isfile(filename) then - local function dofile(filename) local result = loadstring(io.loaddata(filename)) if result then @@ -274,7 +335,6 @@ local function load(filename) return nil end end - local okay, data = pcall(dofile,filename) if okay and type(data) == "table" then local jobversion = job.version @@ -299,28 +359,26 @@ function job.load(filename) local utilitydata = load(filename) if utilitydata then local jobpacker = utilitydata.job.packed - local handlers = { } +unpacknumberdata(jobpacker.index) for i=1,#savelist do - local list = savelist[i] - local target = list[1] - local initializer = list[3] - local result = accesstable(target,utilitydata) + local list = savelist[i] + local target = list[1] + local result = accesstable(target,utilitydata) if result then local done = packers.unpack(result,jobpacker,true) if done then migratetable(target,mark(result)) - if type(initializer) == "function" then - handlers[#handlers+1] = { initializer, result } - end else report_passes("pack version mismatch") end end end - -- so we have all tables available (unpacked) - for i=1,#handlers do - local handler = handlers[i] - handler[1](handler[2]) + end + for i=1,#savelist do + local list = savelist[i] + local initializer = list[3] + if type(initializer) == "function" then + initializer(utilitydata and accesstable(list[1],utilitydata) or nil) end end statistics.stoptiming(_load_) diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt index 65221abf5..d84ecbcbc 100644 --- a/tex/context/base/mkxl/driv-shp.lmt +++ b/tex/context/base/mkxl/driv-shp.lmt @@ -148,7 +148,6 @@ local flush_character do local vfinjectors = fonts.helpers.vfinjectors local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) - if nesting > 100 then return elseif nesting == 0 then @@ -194,7 +193,6 @@ local flush_character do end local refactored = 1000000 - for i=1,#vfcommands do local packet = vfcommands[i] local command = packet[1] diff --git a/tex/context/base/mkxl/file-job.lmt b/tex/context/base/mkxl/file-job.lmt index dac6f6d9a..84186a2d0 100644 --- a/tex/context/base/mkxl/file-job.lmt +++ b/tex/context/base/mkxl/file-job.lmt @@ -550,7 +550,9 @@ end local function poptree() top = remove(treestack) - -- inspect(top) + if #top[#top].branches == 0 then + top[#top].branches = nil -- saves space in tuc + end end do @@ -558,10 +560,15 @@ do local function log_tree(report,top,depth) report("%s%s: %s",depth,top.type,top.name) local branches = top.branches - if #branches > 0 then - depth = depth .. " " - for i=1,#branches do - log_tree(report,branches[i],depth) + if branches then + local n = #branches + if n > 0 then + depth = depth .. " " + for i=1,n do + log_tree(report,branches[i],depth) + end + else + top.brances = nil -- saves space in tuc end end end @@ -1046,6 +1053,7 @@ function document.setcommandline() -- has to happen at the tex end in order to e -- in the new mtx=context approach we always pass a stub file so we need to -- to trick the files table which actually only has one entry in a tex job + if arguments.timing then context.usemodule { "timing" } end diff --git a/tex/context/base/mkxl/font-def.lmt b/tex/context/base/mkxl/font-def.lmt index 614f98036..d71132180 100644 --- a/tex/context/base/mkxl/font-def.lmt +++ b/tex/context/base/mkxl/font-def.lmt @@ -183,6 +183,7 @@ function resolvers.file(specification) specification.forcedname = name specification.name = removesuffix(name) else + -- maybe when no suffix and not found, then still run over suffixes specification.name = name -- can be resolved end end diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx index d865da949..9985df105 100644 --- a/tex/context/base/mkxl/font-lib.mklx +++ b/tex/context/base/mkxl/font-lib.mklx @@ -46,7 +46,7 @@ \registerctxluafile{font-ota}{autosuffix} % \registerctxluafile{font-ots-pre-scale}{autosuffix,optimize} \registerctxluafile{font-ots}{autosuffix,optimize} -\registerctxluafile{font-otd}{optimize} +\registerctxluafile{font-otd}{autosuffix,optimize} \registerctxluafile{font-otc}{} \registerctxluafile{font-oth}{} \registerctxluafile{font-osd}{} diff --git a/tex/context/base/mkxl/font-ogr.lmt b/tex/context/base/mkxl/font-ogr.lmt index ef0af904c..87166b36d 100644 --- a/tex/context/base/mkxl/font-ogr.lmt +++ b/tex/context/base/mkxl/font-ogr.lmt @@ -36,6 +36,9 @@ otf.pngenabled = true -- what here and what in backend ... +local report_fonts = logs.reporter("backend","fonts") +local trace_fonts trackers.register("backend.fonts",function(v) trace_fonts = v end) + do -- This is a prelude to something better but I'm still experimenting. We should delay more. @@ -59,7 +62,8 @@ do local t_properties = t_tfmdata.properties local d_tfmdata = setmetatableindex({ },t_tfmdata) local d_properties = setmetatableindex({ },t_properties) - d_properties.basefontname = "ContextRuntimeFont" .. droppedin + local d_basefontname = "ContextRuntimeFont" .. droppedin + d_properties.basefontname = d_basefontname d_tfmdata.properties = d_properties local d_characters = { } -- setmetatableindex({ },t_characters) -- hm, index vs unicode local d_descriptions = { } -- setmetatableindex({ },t_descriptions) -- hm, index vs unicode @@ -75,6 +79,9 @@ do d_properties.indexdata = { indexdata, ... } -- can take quite some memory local slot = #fonts + 1 fonts[slot] = { id = droppedin } + if trace_fonts then + report_fonts("registering dropin %a using method %a",d_basefontname,method) + end return slot, droppedin, d_tfmdata, d_properties end @@ -84,9 +91,10 @@ do if method and shapes then local characters = tfmdata.characters local descriptions = tfmdata.descriptions - local droppedin, tfmdrop, dropchars, dropdescs, colrshapes + local droppedin, tfmdrop, dropchars, dropdescs, colrshapes, props local idx = 255 local slot = 0 + -- sorted ? for k, v in next, characters do local index = v.index if index then @@ -97,7 +105,7 @@ do if idx >= 255 then idx = 1 colrshapes = setmetatableindex({ },shapes) - slot, droppedin, tfmdrop = dropins.provide(method,tfmdata,colrshapes) + slot, droppedin, tfmdrop, props = dropins.provide(method,tfmdata,colrshapes) dropchars = tfmdrop.characters dropdescs = tfmdrop.descriptions else diff --git a/tex/context/base/mkxl/font-otd.lmt b/tex/context/base/mkxl/font-otd.lmt new file mode 100644 index 000000000..3f1b212db --- /dev/null +++ b/tex/context/base/mkxl/font-otd.lmt @@ -0,0 +1,284 @@ +if not modules then modules = { } end modules ['font-otd'] = { + version = 1.001, + optimize = true, + comment = "companion to font-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type = type +local match = string.match +local sequenced = table.sequenced + +local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end) +local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end) + +local report_otf = logs.reporter("fonts","otf loading") +local report_process = logs.reporter("fonts","otf process") + +local allocate = utilities.storage.allocate + +local fonts = fonts +local otf = fonts.handlers.otf +local hashes = fonts.hashes +local definers = fonts.definers +local constructors = fonts.constructors +local specifiers = fonts.specifiers + +local fontidentifiers = hashes.identifiers +local fontresources = hashes.resources +local fontproperties = hashes.properties +local fontdynamics = hashes.dynamics + +local contextsetups = specifiers.contextsetups +local contextnumbers = specifiers.contextnumbers +local contextmerged = specifiers.contextmerged + +local setmetatableindex = table.setmetatableindex + +local a_to_script = { } +local a_to_language = { } + +-- we can have a scripts hash in fonts.hashes + +function otf.setdynamics(font,attribute) + -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller + local features = contextsetups[attribute] + if features then + local dynamics = fontdynamics[font] + dynamic = contextmerged[attribute] or 0 + local script, language + if dynamic == 2 then -- merge + language = features.language or fontproperties[font].language or "dflt" + script = features.script or fontproperties[font].script or "dflt" + else -- if dynamic == 1 then -- replace + language = features.language or "dflt" + script = features.script or "dflt" + end + if script == "auto" then + -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer + script = definers.checkedscript(fontidentifiers[font],fontresources[font],features) + end + local ds = dynamics[script] -- can be metatable magic (less testing) +-- or dynamics.dflt + if not ds then + ds = { } + dynamics[script] = ds + end + local dsl = ds[language] +-- or ds.dflt + if not dsl then + dsl = { } + ds[language] = dsl + end + local dsla = dsl[attribute] + if not dsla then + local tfmdata = fontidentifiers[font] + a_to_script [attribute] = script + a_to_language[attribute] = language + -- we need to save some values .. quite messy + local properties = tfmdata.properties + local shared = tfmdata.shared + local s_script = properties.script + local s_language = properties.language + local s_mode = properties.mode + local s_features = shared.features + properties.mode = "node" + properties.language = language + properties.script = script + properties.dynamics = true -- handy for tracing + shared.features = { } + -- end of save + local set = constructors.checkedfeatures("otf",features) + set.mode = "node" -- really needed + dsla = otf.setfeatures(tfmdata,set) + if trace_dynamics then + report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set) + end + -- we need to restore some values + properties.script = s_script + properties.language = s_language + properties.mode = s_mode + shared.features = s_features + -- end of restore + dynamics[script][language][attribute] = dsla -- cache + elseif trace_dynamics then + -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language) + end + return dsla + end +end + +function otf.scriptandlanguage(tfmdata,attr) + local properties = tfmdata.properties + if attr and attr > 0 then + return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt" + else + return properties.script or "dflt", properties.language or "dflt" + end +end + +-- we reimplement the dataset resolver + +local autofeatures = fonts.analyzers.features +local featuretypes = otf.tables.featuretypes +local defaultscript = otf.features.checkeddefaultscript +local defaultlanguage = otf.features.checkeddefaultlanguage + +local resolved = { } -- we only resolve a font,script,language,attribute pair once +local wildcard = "*" + +-- what about analyze in local and not in font + +-- needs checking: some added features can pass twice + +local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match + +local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1)) + +local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage) + local features = sequence.features + if features then + local order = sequence.order + if order then + local featuretype = featuretypes[sequence.type or "unknown"] + local lookupdone = false + for i=1,#order do -- + local kind = order[i] -- + local e_e + local a_e = a_enabled and a_enabled[kind] -- the value (location) + if a_e ~= nil then + e_e = a_e + else + e_e = s_enabled and s_enabled[kind] -- the value (font) + end + if e_e then + local usedattribute, usedscript, usedlanguage, usedlookup + local valid = type(e_e) == "string" and lpegmatch(pattern,e_e) + if valid then + -- we have hit always + usedattribute = autofeatures[kind] or false + usedlanguage = "*" + usedscript = "*" + usedlookup = { valid, usedattribute, sequence, kind } + else + -- we already checked for e_e + local scripts = features[kind] -- + local languages = scripts[script] or scripts[wildcard] + if not languages and autoscript then + langages = defaultscript(featuretype,autoscript,scripts) + end + if languages then + -- we need detailed control over default because we want to trace + -- only first attribute match check, so we assume simple fina's + -- local valid = false + if languages[language] then + valid = e_e + elseif languages[wildcard] then + valid = e_e + elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then + valid = e_e + end + end + if valid then + usedattribute = autofeatures[kind] or false + usedlanguage = script + usedscript = language + usedlookup = { valid, usedattribute, sequence, kind } + end + end + if not usedlookup then + -- go on + elseif lookupdone then + if trace_applied then + report_process( + "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a, lookup already set by %a", + font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid,sequence.nofsteps,ra[#ra][4]) + end + else + ra[#ra+1] = usedlookup + if trace_applied then + report_process( + "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a, nofsteps %a", + font,attr or 0,dynamic,kind,usedscript,usedlanguage,sequence.name,valid,sequence.nofsteps) + else + return -- no need to look further + end + lookupdone = true + end + end + end + end + end +end + +-- there is some fuzzy language/script state stuff in properties (temporary) + +function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder) + + local script, language, s_enabled, a_enabled, dynamic + + if attr and attr ~= 0 then + dynamic = contextmerged[attr] or 0 + -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list + local features = contextsetups[attr] + a_enabled = features -- location based + if dynamic == 1 then -- or dynamic == -1 then + -- replace + language = features.language or "dflt" + script = features.script or "dflt" + elseif dynamic == 2 then -- or dynamic == -2 then + -- merge + local properties = tfmdata.properties + s_enabled = tfmdata.shared.features -- font based + language = features.language or properties.language or "dflt" + script = features.script or properties.script or "dflt" + else + -- error + local properties = tfmdata.properties + language = properties.language or "dflt" + script = properties.script or "dflt" + end + else + local properties = tfmdata.properties + language = properties.language or "dflt" + script = properties.script or "dflt" + s_enabled = tfmdata.shared.features -- can be made local to the resolver + dynamic = 0 + end + + local res = resolved[font] + if not res then + res = { } + resolved[font] = res + end + local rs = res[script] + if not rs then + rs = { } + res[script] = rs + end + local rl = rs[language] + if not rl then + rl = { } + rs[language] = rl + end + local ra = rl[attr] + if ra == nil then -- attr can be false + ra = { + -- indexed but we can also add specific data by key in: + } + rl[attr] = ra + local sequences = tfmdata.shared.reorderedsequences or tfmdata.resources.sequences + if sequences then + local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript ) + local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage) + for s=1,#sequences do + -- just return nil or ra step + initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage) + end + end + end + return ra + +end diff --git a/tex/context/base/mkxl/font-ots.lmt b/tex/context/base/mkxl/font-ots.lmt index b8fbc9702..ca6490fc0 100644 --- a/tex/context/base/mkxl/font-ots.lmt +++ b/tex/context/base/mkxl/font-ots.lmt @@ -210,8 +210,7 @@ local getscales = nuts.getscales --------------------------------------------------------------------------------------- -- Beware: In ConTeXt components no longer are real components. We only keep track of --- their positions because some complex ligatures might need that. For the moment we --- use an x_ prefix because for now generic follows the other approach. +-- their positions because some complex ligatures might need that. local components = nuts.components local copynocomponents = components.copynocomponents @@ -244,9 +243,6 @@ local setmetatableindex = table.setmetatableindex local nextnode = nuts.traversers.node ------ zwnj = 0x200C ------ zwj = 0x200D - local nodecodes = nodes.nodecodes local glyphcodes = nodes.glyphcodes @@ -261,7 +257,7 @@ local lefttoright_code = nodes.dirvalues.lefttoright local righttoleft_code = nodes.dirvalues.righttoleft local discretionarydisc_code = nodes.disccodes.discretionary -local ligatureglyph_code = glyphcodes.ligature +----- ligatureglyph_code = glyphcodes.ligature local injections = nodes.injections local setmark = injections.setmark @@ -378,7 +374,7 @@ local function cref(dataset,sequence,index) return "no valid dataset" end local merged = sequence.merged and "merged " or "" - if index then + if index and index > 1 then return formatters["feature %a, type %a, %schain lookup %a, index %a"]( dataset[4],sequence.type,merged,sequence.name,index) else @@ -484,7 +480,7 @@ local function markstoligature(head,start,stop,char) end resetinjection(base) setchar(base,char) - setsubtype(base,ligatureglyph_code) + -- setsubtype(base,ligatureglyph_code) setcomponents(base,start) setlink(prev,base,next) flushcomponents(start) @@ -536,7 +532,7 @@ local function inhibited(start,stop) end local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfound,hasmarks) -- brr head - if start == stop and getchar(start) == char then + if start == stop and getchar(start) == char and not hasmarks then resetinjection(start) setchar(start,char) return head, start @@ -556,7 +552,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou resetinjection(base) setchar(base,char) setoptions(base,getoptions(start) | getoptions(stop)) -- maybe only lig options - setsubtype(base,ligatureglyph_code) + -- setsubtype(base,ligatureglyph_code) setcomponents(base,comp) setlink(prev,base,next) if not discfound then @@ -790,7 +786,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip while current do local nxt, char = isnextchar(current,currentfont,currentdynamic,currentscale,currentxscale,currentyscale) if char and not hasglyphoption(current,no_left_ligature_code) then - local lg = ligature[char] + local lg = not tonumber(ligature) and ligature[char] if lg then stop = current ligature = lg @@ -803,14 +799,14 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip end end if stop then - local lig = ligature.ligature - if lig then + local ligature = tonumber(ligature) or ligature.ligature + if ligature then if trace_ligatures then local stopchar = getchar(stop) - head, start = markstoligature(head,start,stop,lig) + head, start = markstoligature(head,start,stop,ligature) logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) else - head, start = markstoligature(head,start,stop,lig) + head, start = markstoligature(head,start,stop,ligature) end return head, start, true, false else @@ -828,7 +824,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip elseif hasglyphoption(current,no_left_ligature_code) then break else - local lg = ligature[char] + local lg = not tonumber(ligature) and ligature[char] if lg then if marks[char] then hasmarks = true @@ -856,7 +852,9 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip -- -- Challenge for Kai (latinmodern): \hyphenation{fii-f-f-iif} fiiffiif -- - if discfound then + if tonumber(ligature) then + -- we're already done (endpoint reached) + elseif discfound then -- todo: check for no right ligature -- don't assume marks in a disc and we don't run over a disc (for now) local pre, post, replace = getdisc(discfound) @@ -920,27 +918,28 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip start = discfound return head, start, true, true end + ligature = ligature.ligature end - local lig = ligature.ligature - if lig then + -- local ligature = tonumber(ligature) or ligature.ligature + if ligature then if stop then if trace_ligatures then local stopchar = getchar(stop) - -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) - head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) + -- head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,discfound,hasmarks) + head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(ligature)) -- we can have a rare case of multiple disc in a lig but that makes no sense language wise but if really -- needed we could backtrack if we're in a disc node else - -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) - head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) + -- head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,discfound,hasmarks) + head, start = toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) end else -- weird but happens (in some arabic font) resetinjection(start) - setchar(start,lig) + setchar(start,ligature) if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) + logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(ligature)) end end return head, start, true, false @@ -1502,19 +1501,19 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup local last = stop local nofreplacements = 1 while current do - local nxt, schar, id = isnextchar(current,currentfont,currentdynamic,currentscale,currentxscale,currentyscale) - if schar then -if current and hasglyphoption(current,no_left_ligature_code) then - break -end - if skiphash and skiphash[schar] then -- marks + local nxt, char, id = isnextchar(current,currentfont,currentdynamic,currentscale,currentxscale,currentyscale) + if char then + if current and hasglyphoption(current,no_left_ligature_code) then + break + end + if skiphash and skiphash[char] then -- marks -- if current == stop then -- maybe add this -- break -- else current = nxt -- end else - local lg = ligatures[schar] + local lg = not tonumber(ligatures) and ligatures[char] if lg then ligatures = lg last = current @@ -1544,7 +1543,8 @@ end break end end - local ligature = ligatures.ligature + -- we can avoid the tonumber as already done but messy + local ligature = tonumber(ligatures) or ligatures.ligature if ligature then if chainindex then stop = last @@ -2001,7 +2001,6 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) local size = ck[5] - ck[4] + 1 local chainlookups = ck[6] local done = false - -- current match if chainlookups then -- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and @@ -2012,7 +2011,6 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) -- if nofchainlookups > size then -- -- bad rules -- end - local chainlookup = chainlookups[1] for j=1,#chainlookup do local chainstep = chainlookup[j] @@ -2020,6 +2018,9 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) local chainproc = chainprocs[chainkind] if chainproc then local ok + -- HH: chainindex 1 added here (for KAI to check too), there are weird ligatures e.g. + -- char + mark -> char where mark has to disappear + -- head, start, ok = chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash,1) head, start, ok = chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash) if ok then done = true @@ -2515,6 +2516,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s local ck = contexts[k] local seq = ck[3] local f = ck[4] -- first current +local last = start if not startchar or not seq[f][startchar] then -- report("no hit in %a at %i of %i contexts",sequence.type,k,nofcontexts) goto next @@ -2525,7 +2527,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s else local l = ck[5] -- last current local current = start - local last = start +-- local last = start if l > f then -- before/current/after | before/current | current/after @@ -3443,7 +3445,7 @@ local function t_run_single(start,stop,lookupcache) while s do local nxt, char = isnextchar(s,currentfont,currentdynamic,currentscale,currentxscale,currentyscale) if char then - local lg = lookupmatch[char] + local lg = not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d = 1 @@ -3473,7 +3475,7 @@ local function t_run_single(start,stop,lookupcache) break end end - if l and l.ligature then -- so we test for ligature + if l and (tonumber(l) or l.ligature) then -- so we test for ligature lastd = d end end @@ -3587,7 +3589,7 @@ local function t_run_multiple(start,stop,steps,nofsteps) while s do local nxt, char = isnextchar(s,currentfont,currentdynamic,currentscale,currentxscale,currentyscale) if char then - local lg = lookupmatch[char] + local lg = not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d = 1 @@ -3617,7 +3619,7 @@ local function t_run_multiple(start,stop,steps,nofsteps) break end end - if l and l.ligature then + if l and (tonumber(l) or l.ligature) then lastd = d end end @@ -3728,7 +3730,14 @@ do -- about 15% on arabtype .. then moving the a test also saves a bit (even when -- often a is not set at all so that one is a bit debatable - local otfdataset = nil -- todo: make an installer + -- local otfdataset = nil + local otfdataset + + otfdataset = function(...) + -- delayed alias + otfdataset = otf.dataset + return otfdataset(...) + end local getfastdisc = { __index = function(t,k) local v = usesfont(k,currentfont) @@ -3752,9 +3761,6 @@ do if nesting == 1 then currentfont = font currentdynamic = dynamic --- currentscale = false --- currentxscale = false --- currentyscale = false currentscale = 1000 currentxscale = 1000 currentyscale = 1000 @@ -3768,11 +3774,11 @@ do factor = getthreshold(font) checkmarks = tfmdata.properties.checkmarks - if not otfdataset then - otfdataset = otf.dataset - end + -- if not otfdataset then + -- otfdataset = otf.dataset + -- end - discs = fastdisc and n and n > 1 and setmetatable({},getfastdisc) -- maybe inline + discs = fastdisc and n and n > 1 and setmetatable({},getfastdisc) spaces = setmetatable({},getfastspace) elseif currentfont ~= font then @@ -3806,7 +3812,7 @@ do -- We don't goto the next node when a disc node is created so that we can then treat -- the pre, post and replace. It's a bit of a hack but works out ok for most cases. - for s=1,#datasets do + for s=1,#datasets do -- todo: datasets.n local dataset = datasets[s] local state = dataset[2] local sequence = dataset[3] -- sequences[s] -- also dataset[5] @@ -4194,8 +4200,8 @@ registerotffeature { } } --- Moved here (up) a bit. This doesn't really belong in generic so it will --- move to a context module some day. +-- Moved here (up) a bit. This doesn't really belong in generic so it will move to a +-- context module some day. local function markinitializer(tfmdata,value) local properties = tfmdata.properties @@ -4223,239 +4229,3 @@ registerotffeature { -- Also see (!!). otf.handlers = handlers - -if context then - return -else - -- todo: move the following code someplace else -end - -local setspacekerns = nodes.injections.setspacekerns if not setspacekerns then os.exit() end - -local tag = "kern" - --- if fontfeatures then - --- function handlers.trigger_space_kerns(head,dataset,sequence,initialrl,font,dynamic) --- local features = fontfeatures[font] --- local enabled = features and features.spacekern and features[tag] --- if enabled then --- setspacekerns(font,sequence) --- end --- return head, enabled --- end - --- else -- generic (no hashes) - - function handlers.trigger_space_kerns(head,dataset,sequence,initialrl,font,dynamic) - local shared = fontdata[font].shared - local features = shared and shared.features - local enabled = features and features.spacekern and features[tag] - if enabled then - setspacekerns(font,sequence) - end - return head, enabled - end - --- end - --- There are fonts out there that change the space but we don't do that kind of --- things in TeX. - -local function hasspacekerns(data) - local resources = data.resources - local sequences = resources.sequences - local validgpos = resources.features.gpos - if validgpos and sequences then - for i=1,#sequences do - local sequence = sequences[i] - local steps = sequence.steps - if steps and sequence.features[tag] then - local kind = sequence.type - if kind == "gpos_pair" or kind == "gpos_single" then - for i=1,#steps do - local step = steps[i] - local coverage = step.coverage - local rules = step.rules - if rules then - -- not now: analyze (simple) rules - elseif not coverage then - -- nothing to do - elseif kind == "gpos_single" then - -- maybe a message that we ignore - elseif kind == "gpos_pair" then - local format = step.format - if format == "move" or format == "kern" then - local kerns = coverage[32] - if kerns then - return true - end - for k, v in next, coverage do - if v[32] then - return true - end - end - elseif format == "pair" then - local kerns = coverage[32] - if kerns then - for k, v in next, kerns do - local one = v[1] - if one and one ~= true then - return true - end - end - end - for k, v in next, coverage do - local kern = v[32] - if kern then - local one = kern[1] - if one and one ~= true then - return true - end - end - end - end - end - end - end - end - end - end - return false -end - -otf.readers.registerextender { - name = "spacekerns", - action = function(data) - data.properties.hasspacekerns = hasspacekerns(data) - end -} - -local function spaceinitializer(tfmdata,value) -- dynamic - local resources = tfmdata.resources - local spacekerns = resources and resources.spacekerns - if value and spacekerns == nil then - local rawdata = tfmdata.shared and tfmdata.shared.rawdata - local properties = rawdata.properties - if properties and properties.hasspacekerns then - local sequences = resources.sequences - local validgpos = resources.features.gpos - if validgpos and sequences then - local left = { } - local right = { } - local last = 0 - local feat = nil - for i=1,#sequences do - local sequence = sequences[i] - local steps = sequence.steps - if steps then - -- we don't support space kerns in other features - local kern = sequence.features[tag] - if kern then - local kind = sequence.type - if kind == "gpos_pair" or kind == "gpos_single" then - if feat then - for script, languages in next, kern do - local f = feat[script] - if f then - for l in next, languages do - f[l] = true - end - else - feat[script] = languages - end - end - else - feat = kern - end - for i=1,#steps do - local step = steps[i] - local coverage = step.coverage - local rules = step.rules - if rules then - -- not now: analyze (simple) rules - elseif not coverage then - -- nothing to do - elseif kind == "gpos_single" then - -- makes no sense in TeX - elseif kind == "gpos_pair" then - local format = step.format - if format == "move" or format == "kern" then - local kerns = coverage[32] - if kerns then - for k, v in next, kerns do - right[k] = v - end - end - for k, v in next, coverage do - local kern = v[32] - if kern then - left[k] = kern - end - end - elseif format == "pair" then - local kerns = coverage[32] - if kerns then - for k, v in next, kerns do - local one = v[1] - if one and one ~= true then - right[k] = one[3] - end - end - end - for k, v in next, coverage do - local kern = v[32] - if kern then - local one = kern[1] - if one and one ~= true then - left[k] = one[3] - end - end - end - end - end - end - last = i - end - else - -- no steps ... needed for old one ... we could use the basekerns - -- instead - end - end - end - left = next(left) and left or false - right = next(right) and right or false - if left or right then - spacekerns = { - left = left, - right = right, - } - if last > 0 then - local triggersequence = { - -- no steps, see (!!) - features = { [tag] = feat or { dflt = { dflt = true, } } }, - flags = noflags, - name = "trigger_space_kerns", - order = { tag }, - type = "trigger_space_kerns", - left = left, - right = right, - } - insert(sequences,last,triggersequence) - end - end - end - end - resources.spacekerns = spacekerns - end - return spacekerns -end - -registerotffeature { - name = "spacekern", - description = "space kern injection", - default = true, - initializers = { - node = spaceinitializer, - }, -} diff --git a/tex/context/base/mkxl/font-set.mklx b/tex/context/base/mkxl/font-set.mklx index fd6a2f1ff..98e2e96e1 100644 --- a/tex/context/base/mkxl/font-set.mklx +++ b/tex/context/base/mkxl/font-set.mklx @@ -88,7 +88,7 @@ {\glet\font_preload_default_fonts_tt\relax \glet\font_preload_default_fonts_mm\relax \glet\font_preloads_third_stage \relax -% \glet\font_preloads_fourth_stage \relax + \glet\font_preloads_fourth_stage \relax } \def\font_preloads_zero_stage_indeed diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt index c715c7b77..926455bb8 100644 --- a/tex/context/base/mkxl/lpdf-emb.lmt +++ b/tex/context/base/mkxl/lpdf-emb.lmt @@ -2101,6 +2101,7 @@ function lpdf.flushfonts() local hash = getstreamhash(fontid) if hash then local parent = mainfonts[hash] +-- print("before",fontid,hash,parent) if not parent then local fontdata = usedfonts[fontid] local rawdata = fontdata.shared and fontdata.shared.rawdata @@ -2145,6 +2146,7 @@ function lpdf.flushfonts() noffonts = noffonts + 1 end end +-- print("after ",fontid,hash,parent) if parent then local indices = parent.indices for k, v in next, used do @@ -2159,21 +2161,23 @@ function lpdf.flushfonts() for hash, details in sortedhash(mainfonts) do local filename = details.filename if next(details.indices) then - if trace_fonts then - report_fonts("embedding %a hashed as %a",filename,hash) - end local properties = details.properties local bitmap = properties.usedbitmap local method = properties.method -- will be pk | pdf | svg | ... + if trace_fonts then + if method then + report_fonts("embedding %a hashed as %a using method %a",filename,hash,method) + else + report_fonts("embedding %a hashed as %a",filename,hash) + end + end if bitmap or method then local format = "type3" local writer = mainwriters[format] - if writer then - if trace_fonts then - report_fonts("using main writer %a",format) - end - writer(details) + if trace_fonts then + report_fonts("using main writer %a",format) end + writer(details) else local format = properties.format local writer = mainwriters[format] @@ -2285,7 +2289,10 @@ function lpdf.flushfonts() -- report_fonts("no indices for %a",filename) end if trace_fonts then - report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) + local indices = details.indices + if indices and next(indices) then + report_fonts("embedded indices: % t",table.sortedkeys(details.indices)) + end end mainfonts[details.hash] = false -- done end diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt index 826c1ce21..8d3fc7fde 100644 --- a/tex/context/base/mkxl/lpdf-lmt.lmt +++ b/tex/context/base/mkxl/lpdf-lmt.lmt @@ -3028,6 +3028,7 @@ do -- statistics.register("result saved in file", function() local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "<unset>" + outputfilename = string.gsub(outputfilename,"^%./+","") -- todo: make/use a helper return string.format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf",lpdf.getcompression()) end) -- diff --git a/tex/context/base/mkxl/lpdf-wid.lmt b/tex/context/base/mkxl/lpdf-wid.lmt index fcc7b9c99..87cfcccd1 100644 --- a/tex/context/base/mkxl/lpdf-wid.lmt +++ b/tex/context/base/mkxl/lpdf-wid.lmt @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['lpdf-wid'] = { -- html5 media in pdf then. -- -- See mail by Michal Vlasák to the mailing list that discusses current support in --- viewers and also mentions a few fixes wrt embedding media. +-- viewers and also mentions (and submitted) a few fixes wrt embedding media. local tonumber, next = tonumber, next local gmatch, gsub, find, lower = string.gmatch, string.gsub, string.find, string.lower @@ -60,6 +60,7 @@ local v_auto = variables.auto local v_embed = variables.embed local v_max = variables.max local v_yes = variables.yes +local v_compress = variables.compress local pdfconstant = lpdf.constant local pdfnull = lpdf.null @@ -649,6 +650,7 @@ local function insertrenderingwindow(specification) Subtype = pdfconstant("Screen"), P = pdfreference(pdfpagereference(page)), A = a, -- needed in order to make the annotation clickable (i.e. don't bark) + T = pdfunicode(label), -- for JS Border = bs, C = bc, AA = actions, @@ -662,7 +664,7 @@ end -- some dictionaries can have a MH (must honor) or BE (best effort) capsule local function insertrendering(specification) - local label = specification.label + local label = specification.label local option = settings_to_hash(specification.option) if not mf[label] then local filename = specification.filename @@ -693,7 +695,7 @@ local function insertrendering(specification) -- } -- } local parameters = pdfdictionary { - Type = pdfconstant(MediaPermissions), + Type = pdfconstant("MediaPermissions"), TF = pdfstring("TEMPALWAYS"), -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS / needed for acrobat/wmp } local descriptor = pdfdictionary { @@ -707,7 +709,7 @@ local function insertrendering(specification) descriptor = codeinjections.embedfile { file = filename, mimetype = mimetype, -- yes or no - compress = false, + compress = option[v_compress] or false, forcereference = true, } end @@ -723,7 +725,7 @@ local function insertrendering(specification) local rendition = pdfdictionary { Type = pdfconstant("Rendition"), S = pdfconstant("MR"), - N = label, + N = pdfunicode(label), C = pdfreference(pdfflushobject(clip)), } mf[label] = pdfreference(pdfflushobject(rendition)) @@ -761,6 +763,21 @@ function codeinjections.processrendering(label) end end +-- needed mapping for access from JS + +local function flushrenderings() + if next(mf) then + local r = pdfarray() + for label, reference in sortedhash(mf) do + r[#r+1] = pdfunicode(label) + r[#r+1] = reference -- already a reference + end + lpdf.addtonames("Renditions",pdfreference(pdfflushobject(pdfdictionary{ Names = r }))) + end +end + +lpdf.registerdocumentfinalizer(flushrenderings,"renderings") + function codeinjections.insertrenderingwindow(specification) local label = specification.label codeinjections.processrendering(label) diff --git a/tex/context/base/mkxl/luat-lib.mkxl b/tex/context/base/mkxl/luat-lib.mkxl index d26c90af5..7ad29e29e 100644 --- a/tex/context/base/mkxl/luat-lib.mkxl +++ b/tex/context/base/mkxl/luat-lib.mkxl @@ -18,7 +18,7 @@ \registerctxluafile{util-fil}{autosuffix} \registerctxluafile{util-sac}{autosuffix} \registerctxluafile{util-sto}{} % could also be done in trac-deb.mkiv -\registerctxluafile{util-pck}{} +\registerctxluafile{util-pck}{autosuffix} \registerctxluafile{util-prs}{} \registerctxluafile{util-fmt}{} \registerctxluafile{util-dim}{} diff --git a/tex/context/base/mkxl/lxml-ini.mkxl b/tex/context/base/mkxl/lxml-ini.mkxl index b18d8053b..be249c1f3 100644 --- a/tex/context/base/mkxl/lxml-ini.mkxl +++ b/tex/context/base/mkxl/lxml-ini.mkxl @@ -195,6 +195,23 @@ %xmlpopdocument \endgroup} +% This still doesn't solve a problem with weird grouping (start inside xml and +% end outside, so one has to do proper grouping inside xml mode). +% +% \def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup +% {%\begingroup +% \pushmacro\xmldocument +% \edef\xmldocument{#3}% #2 can be \xmldocument and set as such +% #2{#3}{#4}% +% \pushcatcodetable +% \setcatcodetable\notcatcodes +% \doifelsenothing{#5}% +% {\xmlsetup{#3}{xml:process}}% +% {\xmlsetup{#3}{#5}}% +% \popcatcodetable +% \popmacro\xmldocument +% }%\endgroup} + \permanent\protected\def\xmlprocessfile {\lxml_process\plusone \xmlload} \permanent\protected\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} \permanent\protected\def\xmlprocessbuffer{\lxml_process\zerocount\xmlloadbuffer} diff --git a/tex/context/base/mkxl/math-ini.lmt b/tex/context/base/mkxl/math-ini.lmt index 857f21013..e31b14af3 100644 --- a/tex/context/base/mkxl/math-ini.lmt +++ b/tex/context/base/mkxl/math-ini.lmt @@ -120,13 +120,13 @@ local accents = allocate { local codes = allocate { ordinary = 0, [0] = "ordinary", - largeoperator = 1, [1] = "largeoperator", - binaryoperator = 2, [2] = "binaryoperator", - relation = 3, [3] = "relation", - openingsymbol = 4, [4] = "openingsymbol", - closingsymbol = 5, [5] = "closingsymbol", - punctuation = 6, [6] = "punctuation", - variable = 7, [7] = "variable", + largeoperator = 1, "largeoperator", + binaryoperator = 2, "binaryoperator", + relation = 3, "relation", + openingsymbol = 4, "openingsymbol", + closingsymbol = 5, "closingsymbol", + punctuation = 6, "punctuation", + variable = 7, "variable", } local extensibles = allocate { diff --git a/tex/context/base/mkxl/math-map.lmt b/tex/context/base/mkxl/math-map.lmt index 783b9db74..304cbe592 100644 --- a/tex/context/base/mkxl/math-map.lmt +++ b/tex/context/base/mkxl/math-map.lmt @@ -688,9 +688,9 @@ local issygreek = regular_tf.symbols local isgreek = merged(islcgreek,isucgreek,issygreek) local greekremapping = { - [1] = { what = "unchanged" }, -- upright - [2] = { what = "upright", it = "tf", bi = "bf" }, -- upright - [3] = { what = "italic", tf = "it", bf = "bi" }, -- italic + { what = "unchanged" }, -- upright + { what = "upright", it = "tf", bi = "bf" }, -- upright + { what = "italic", tf = "it", bf = "bi" }, -- italic } local usedremap = { } diff --git a/tex/context/base/mkxl/math-rad.mklx b/tex/context/base/mkxl/math-rad.mklx index 8906efdc8..c5445f8f1 100644 --- a/tex/context/base/mkxl/math-rad.mklx +++ b/tex/context/base/mkxl/math-rad.mklx @@ -110,12 +110,14 @@ \def\m_math_no_degree{{}} +% style width [options: left middle right] + \def\math_radical_alternative{\csname\??mathradicalalternative\mathradicalparameter\c!alternative\endcsname} -\setvalue{\??mathradicalalternative\v!default}% #body% +\defcsname\??mathradicalalternative\v!default\endcsname % #body% {\rootradical{\currentmathradicaldegree}} % {#body}} -\setvalue{\??mathradicalalternative\v!normal}#body% +\defcsname\??mathradicalalternative\v!normal\endcsname#body% {\edef\p_color{\mathradicalparameter\c!color}% \ifempty\p_color \styledrootradical{\currentmathradicaldegree}{#body}% {} really needed as \rootradical expands first @@ -150,7 +152,7 @@ % todo: spacing .. this is just an experiment (article driven) -\setvalue{\??mathradicalalternative\v!mp}#body% we could use dowithnextbox +\defcsname\??mathradicalalternative\v!mp\endcsname#body% we could use dowithnextbox {\begingroup \scratchoffset\mathradicalparameter\c!mpoffset \setbox\nextbox\mathstylehbox{#body}% @@ -213,7 +215,7 @@ \csname\??mathornamentalternative\mathornamentparameter\c!alternative\endcsname{#body}% \endgroup} -\setvalue{\??mathornamentalternative\v!mp}#body% we could use dowithnextbox +\defcsname\??mathornamentalternative\v!mp\endcsname#body% we could use dowithnextbox {\begingroup \scratchoffset\mathornamentparameter\c!mpoffset \setbox\nextbox\mathstylehbox{#body}% diff --git a/tex/context/base/mkxl/meta-ini.mkxl b/tex/context/base/mkxl/meta-ini.mkxl index 8abd1339a..b30f4826f 100644 --- a/tex/context/base/mkxl/meta-ini.mkxl +++ b/tex/context/base/mkxl/meta-ini.mkxl @@ -514,7 +514,8 @@ \meta_mpvar_default \orelse\ifchkdim\m_meta_current_variable\or \todimension\m_meta_current_variable\space\space - \orelse\ifchknum\m_meta_current_variable\or + % \orelse\ifchknum\m_meta_current_variable\or % we need to catch 1>2 + \orunless\iftok{\ifchknum\m_meta_current_variable\or\tointeger\m_meta_current_variable\fi}\emptytoks \tointeger\m_meta_current_variable\space\space \orelse\ifcsname\??colorattribute\currentcolorprefix\m_meta_current_variable\endcsname \MPcolor\m_meta_current_variable\space @@ -532,7 +533,8 @@ \meta_mpvar_default \orelse\ifchkdim\m_meta_current_variable\or \todimension\m_meta_current_variable\space\space - \orelse\ifchknum\m_meta_current_variable\or + % \orelse\ifchknum\m_meta_current_variable\or % we need to catch 1>2 + \orunless\iftok{\ifchknum\m_meta_current_variable\or\tointeger\m_meta_current_variable\fi}\emptytoks \tointeger\m_meta_current_variable\space\space \orelse\ifcsname\??colorattribute\currentcolorprefix\m_meta_current_variable\endcsname \MPcolor\m_meta_current_variable\space diff --git a/tex/context/base/mkxl/mlib-ctx.lmt b/tex/context/base/mkxl/mlib-ctx.lmt index 13dba92cd..64225e308 100644 --- a/tex/context/base/mkxl/mlib-ctx.lmt +++ b/tex/context/base/mkxl/mlib-ctx.lmt @@ -118,15 +118,15 @@ implement { arguments = "string", actions = function(name) local value = metapost.variables[name] - if value ~= nil then - local tvalue = type(value) - if tvalue == "table" then - context(concat(value," ")) - elseif tvalue == "number" or tvalue == "boolean" then - context(tostring(value)) - elseif tvalue == "string" then - context(value) - end + local tvalue = type(value) + if tvalue == "nil" then + context("0") + elseif tvalue == "table" then + context(concat(value," ")) + elseif tvalue == "number" or tvalue == "boolean" then + context(tostring(value)) + elseif tvalue == "string" then + context(value) end end } @@ -362,16 +362,6 @@ function mptex.reset() end implement { - name = "mppushvariables", - actions = metapost.pushvariables, -} - -implement { - name = "mppopvariables", - actions = metapost.popvariables, -} - -implement { name = "mptexset", arguments = "string", actions = mptex.set diff --git a/tex/context/base/mkxl/mlib-lmp.lmt b/tex/context/base/mkxl/mlib-lmp.lmt index e4944c92e..1614f0951 100644 --- a/tex/context/base/mkxl/mlib-lmp.lmt +++ b/tex/context/base/mkxl/mlib-lmp.lmt @@ -8,7 +8,9 @@ if not modules then modules = { } end modules ['mlib-lmp'] = { -- path relates stuff ... todo: use a stack (or numeric index to list) -local type = type +local type, tonumber, tostring = type, tonumber, tostring +local find, match = string.find, string.match +local insert, remove = table.insert, table.remove local aux = mp.aux local mpnumeric = aux.numeric @@ -18,60 +20,86 @@ local registerdirect = metapost.registerdirect local registerscript = metapost.registerscript local scan = mp.scan +local skip = mp.skip local get = mp.get +local inject = mp.inject + local scannumber = scan.number local scanstring = scan.string +local scaninteger = scan.integer +local scannumeric = scan.numeric +local scanwhatever = scan.whatever local scanpath = scan.path local scanproperty = scan.property + local gethashentry = get.hashentry -local p = nil -local n = 0 +local bpfactor = number.dimenfactors.bp -registerscript("pathreset", function() - p = nil - n = 0 -end) +local injectwhatever = inject.whatever +local injectboolean = inject.boolean +local injectnumeric = inject.numeric +local injectstring = inject.string +local injectpair = inject.pair -registerscript("pathlengthof", function() - p = scanpath() - n = p and #p or 1 - mpnumeric(n) -end) +local injectwhd = inject.whd -- scaled +local injectxy = inject.xy +local injectpt = inject.pt -registerscript("pathpointof", function() - local i = scannumber() - if i > 0 and i <= n then - local pi = p[i] - mppair(pi[1],pi[2]) - end -end) +local report = logs.reporter("metapost", "log") +local report_message = logs.reporter("metapost") -registerscript("pathleftof", function() - local i = scannumber() - if i > 0 and i <= n then - local pi = p[i] - mppair(pi[5],pi[6]) - end -end) +local codes = metapost.codes +local types = metapost.types +local procodes = mplib.propertycodes -registerscript("pathrightof", function() - local i = scannumber() - if i > 0 and i <= n then - local pn - if i == 1 then - pn = p[2] or p[1] - else - pn = p[i+1] or p[1] +local implement = interfaces.implement + +do + + local p = nil + local n = 0 + + registerscript("pathreset", function() + p = nil + n = 0 + end) + + registerdirect("pathlengthof", function() + p = scanpath() + return p and #p or 1 + end) + + registerdirect("pathpointof", function() + local i = scannumber() + if i > 0 and i <= n then + local pi = p[i] + injectpair(pi[1],pi[2]) end - mppair(pn[3],pn[4]) - end -end) + end) -local report = logs.reporter("metapost", "log") -local codes = metapost.codes -local types = metapost.types -local procodes = mplib.propertycodes + registerdirect("pathleftof", function() + local i = scannumber() + if i > 0 and i <= n then + local pi = p[i] + injectpair(pi[5],pi[6]) + end + end) + + registerdirect("pathrightof", function() + local i = scannumber() + if i > 0 and i <= n then + local pn + if i == 1 then + pn = p[2] or p[1] + else + pn = p[i+1] or p[1] + end + injectpair(pn[3],pn[4]) + end + end) + +end registerscript("showproperty", function() local k, s, p, d = scanproperty() @@ -92,9 +120,6 @@ end) -- local getmacro = tokens.getters.macro -- local mpgnamespace = getmacro("??graphicvariable") --- local scanmpstring = mp.scan.string --- local injectnumeric = mp.inject.numeric --- local injectstring = mp.inject.string -- registerscript("mpv_numeric", function() injectnumeric (getmacro(mpgnamespace .. getmacro("currentmpcategory") .. ":" .. scanmpstring())) end) -- registerscript("mpv_dimension", function() return getmacro(mpgnamespace .. getmacro("currentmpcategory") .. ":" .. scanmpstring()) end) @@ -103,46 +128,380 @@ end) -- registerscript("mpvar", function() return getmacro(mpgnamespace .. getmacro("currentmpcategory") .. ":" .. scanmpstring(), true) end) -- Isn't it already edef'd? -- registerscript("mpvar", function() return getmacro(metapost.namespace .. scanmpstring(), true) end) -- Isn't it already edef'd? -local scanstring = mp.scan.string -local expandtex = mp.expandtex +do + + local expandtex = mp.expandtex + + local tokenvalues = tokens.values + local dimension_value = tokenvalues.dimension + local integer_value = tokenvalues.integer + local boolean_value = tokenvalues.boolean + local string_value = tokenvalues.string + local unknown_value = tokenvalues.none + + registerdirect("mpvard", function() + if not expandtex(dimension_value,"mpcategoryparameter",true,scanstring()) then + injectnumeric(0) + end + end) + + registerdirect("mpvarn", function() + if not expandtex(integer_value,"mpcategoryparameter",true,scanstring()) then + injectnumeric(0) + end + end) + + registerdirect("mpvars", function() + if not expandtex(string_value,"mpcategoryparameter",true,scanstring()) then + injectstring("") + end + end) + + registerdirect("mpvarb", function() + if not expandtex(boolean_value,"mpcategoryparameter",true,scanstring()) then + injectboolean(false) + end + end) + + registerdirect("mpvar", function() + if not expandtex(unknown_value,"mpcategoryparameter",true,scanstring()) then + injectnumeric(0) + end + end) -local injectnumeric = mp.inject.numeric -local injectstring = mp.inject.string -local injectboolean = mp.inject.boolean + -- -local tokenvalues = tokens.values -local dimension_value = tokenvalues.dimension -local integer_value = tokenvalues.integer -local boolean_value = tokenvalues.boolean -local string_value = tokenvalues.string -local unknown_value = tokenvalues.none + local mpprint = mp.print + local mpquoted = mp.quoted + local getmacro = tokens.getters.macro -registerdirect("mpvard", function() - if not expandtex(dimension_value,"mpcategoryparameter",true,scanstring()) then - injectnumeric(0) + registerscript("texvar", function() mpprint (getmacro(metapost.namespace .. scanstring())) end) + registerscript("texstr", function() mpquoted(getmacro(metapost.namespace .. scanstring())) end) + +end + +do + + registerscript("textextanchor", function() + local x, y = match(scanstring(),"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg + if x and y then + x = tonumber(x) + y = tonumber(y) + end + injectpair(x or 0,y or 0) + end) + +end + +do + + local mpnamedcolor = attributes.colors.mpnamedcolor + local mpprint = mp.aux.print + + mp.mf_named_color = function(str) + mpprint(mpnamedcolor(str)) end -end) -registerdirect("mpvarn", function() - if not expandtex(integer_value,"mpcategoryparameter",true,scanstring()) then - injectnumeric(0) + -- todo: we can inject but currently we always get a string back so then + -- we need to deal with it upstream in the color module ... not now + + registerscript("namedcolor",function() mpprint(mpnamedcolor(scanstring())) end) + +end + +do + + local hashes = table.setmetatableindex("table") + + registerdirect("lmt_hash_new", function() + -- local name = scanstring() + local name = scanwhatever() + hashes[name] = { } + end) + + registerdirect("lmt_hash_dispose", function() + -- local name = scanstring() + local name = scanwhatever() + hashes[name] = nil + end) + + registerdirect("lmt_hash_in", function() + -- local name = scanstring() + local name = scanwhatever() + -- local key = scanstring() + local key = scanwhatever() + local hash = hashes[name] + injectwhatever(hash and hash[key] and true or false) + end) + + registerdirect("lmt_hash_to", function() + -- local name = scanstring() + local name = scanwhatever() + -- local key = scanstring() + local key = scanwhatever() + local value = scanwhatever() + local hash = hashes[name] + if hash then + hash[key] = value + end + end) + + registerdirect("lmt_hash_from", function() + -- local name = scanstring() + local name = scanwhatever() + -- local key = scanstring() + local key = scanwhatever() + local hash = hashes[name] + injectwhatever(hash and hash[key] or false) + end) + + interfaces.implement { + name = "MPfromhash", + arguments = "2 strings", + actions = function(name,key) + local hash = hashes[name] or hashes[tonumber(name)] or hashes[tostring(name)] + if hash then + local v = hash[key] + if v then + context(v) + end + end + end + } + +end + +do + + local bpfactor = number.dimenfactors.bp + local nbdimensions = nodes.boxes.dimensions + + registerdirect("boxdimensions", function() + local category = scanstring() + local index = scanwhatever() + injectwhd(nbdimensions(category,index)) + end) + +end + +do + + local skiptoken = skip.token + + local comma_code = codes.comma + + local getmacro = tokens.getters.macro + local setmacro = tokens.setters.macro + + local getdimen = tex.getdimen + local getcount = tex.getcount + local gettoks = tex.gettoks + local setdimen = tex.setdimen + local setcount = tex.setcount + local settoks = tex.settoks + + -- more helpers + + registerdirect("getmacro", function() return getmacro(scanstring()) end) + registerdirect("getcount", function() return getcount(scanwhatever()) end) + registerdirect("gettoks", function() return gettoks (scanwhatever()) end) + registerdirect("getdimen", function() return getdimen(scanwhatever()) * bpfactor end) + + registerscript("setmacro", function() setmacro(scanstring(),scanstring()) end) + registerscript("setdimen", function() setdimen(scanwhatever(),scannumeric()/bpfactor) end) + registerscript("setcount", function() setcount(scanwhatever(),scannumeric()) end) + registerscript("settoks", function() settoks (scanwhatever(),scanstring()) end) + + registerscript("setglobalmacro", function() setmacro(scanstring(),scanstring(),"global") end) + registerscript("setglobaldimen", function() setdimen("global",scanwhatever(),scannumeric()/bpfactor) end) + registerscript("setglobalcount", function() setcount("global",scanwhatever(),scaninteger()) end) + registerscript("setglobaltoks", function() settoks ("global",scanwhatever(),scanstring()) end) + + local utfnum = utf.byte + local utflen = utf.len + local utfsub = utf.sub + + registerdirect("utfnum", function() return utfnum(scanstring()) end) + registerdirect("utflen", function() return utflen(scanstring()) end) + + registerdirect("utfsub", function() -- we have an optional third argument so we explicitly scan a text argument + return utfsub(scanstring(),skiptoken(comma_code) and scannumeric(),skiptoken(comma_code) and scannumeric()) + end) + + local setlogging = metapost.setlogging + + registerscript("message", function() + setlogging(false) + local str = scanstring() + setlogging(true) + report_message("message : %s",str) + end) + +end + +-- position fun + +do + + local mpprint = mp.print + local mpfprint = mp.fprint + + local jobpositions = job.positions + local getwhd = jobpositions.whd + local getxy = jobpositions.xy + local getposition = jobpositions.position + local getpage = jobpositions.page + local getparagraph = jobpositions.paragraph + local getregion = jobpositions.region + local getcolumn = jobpositions.column + local getmacro = tokens.getters.macro + + registerscript("positionpath", function() + local w, h, d = getwhd(scanstring()) + if w then + mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",0,-d,w,-d,w,h,0,h) + else + mpprint("(origin--cycle)") + end + end) + + registerscript("positioncurve", function() + local w, h, d = getwhd(scanstring()) + if w then + mpfprint("((%p,%p)..(%p,%p)..(%p,%p)..(%p,%p)..cycle)",0,-d,w,-d,w,h,0,h) + else + mpprint("(origin--cycle)") + end + end) + + registerscript("positionbox", function() + local p, x, y, w, h, d = getposition(scanstring()) + if p then + mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h) + else + mpprint("(%p,%p)--cycle",x or 0,y or 0) + end + end) + + registerdirect("positionpage", function() return getpage (scanstring()) or 0 end) + registerdirect("positioncolumn", function() return getcolumn (scanstring()) or 0 end) + registerdirect("positionparagraph", function() return getparagraph(scanstring()) or 0 end) + registerdirect("positionregion", function() return getregion (scanstring()) or "unknown" end) + registerdirect("positionanchor", function() return getmacro ("MPanchorid") end) + registerdirect("positionwhd", function() injectwhd(getwhd(scanstring())) end) + registerdirect("positionxy", function() injectxy (getxy (scanstring())) end) + registerdirect("positionx", function() injectpt (getx (scanstring())) end) + registerdirect("positiony", function() injectpt (gety (scanstring())) end) + +end + +do + + local modes = tex.modes + local systemmodes = tex.systemmodes + + registerdirect("mode", function() injectboolean(modes [scanstring()] and true or false) end) + registerdirect("systemmode", function() injectboolean(systemmodes[scanstring()] and true or false) end) + +end + +-- for alan's nodes: + +do + + local lpegmatch, lpegpatterns, P = lpeg.match, lpeg.patterns, lpeg.P + + -- todo: scansuffix / why no return boolean (first one) + + registerdirect("isarray", function() + injectboolean(find(scanstring(),"%d") and true or false) + end) + + registerdirect("prefix", function() + local str = scanstring() + return match(str,"^(.-)[%d%[]") or str + end) + + local dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer) + + registerdirect("dimension", function() return dimension(scanstring()) end) + + -- todo : share with mlib-pps.lua metapost,isobject + + -- registerdirect("isobject", function() + -- injectboolean(find(scanstring(),"mf_object=")) + -- end + + local p1 = P("mf_object=") + local p2 = lpegpatterns.eol * p1 + local pattern = (1-p2)^0 * p2 + p1 + + registerdirect("isobject", function() + local str = scanstring() + injectboolean(pattern and str ~= "" and lpegmatch(pattern,str)) + end) + +end + +-- key/values (moved here, old mechanism) + +do + + local stack, top = { }, nil + + local function setvariable(k,v) + if top then + top[k] = v + else + metapost.variables[k] = v + end end -end) -registerdirect("mpvars", function() - if not expandtex(string_value,"mpcategoryparameter",true,scanstring()) then - injectstring("") + local function pushvariable(k) + local t = { } + if top then + insert(stack,top) + top[k] = t + else + metapost.variables[k] = t + end + top = t end -end) -registerdirect("mpvarb", function() - if not expandtex(boolean_value,"mpcategoryparameter",true,scanstring()) then - injectboolean(false) + local function popvariable() + top = remove(stack) end -end) -registerdirect("mpvar", function() - if not expandtex(unknown_value,"mpcategoryparameter",true,scanstring()) then - injectnumeric(0) + registerscript("passvariable", function() setvariable (scanstring(), scanwhatever()) end) + registerscript("pushvariable", function() pushvariable(scanstring()) end) + registerscript("popvariable", function() popvariable () end) + + local stack = { } + + local function pushvariables() + insert(stack,metapost.variables) + metapost.variables = { } end -end) + + local function popvariables() + metapost.variables = remove(stack) or metapost.variables + end + + metapost.setvariable = setvariable + metapost.pushvariable = pushvariable + metapost.popvariable = popvariable + metapost.pushvariables = pushvariables + metapost.popvariables = popvariables + + implement { + name = "mppushvariables", + actions = pushvariables, + } + + implement { + name = "mppopvariables", + actions = popvariables, + } + +end + diff --git a/tex/context/base/mkxl/mlib-lua.lmt b/tex/context/base/mkxl/mlib-lua.lmt index ceca9668a..e40954456 100644 --- a/tex/context/base/mkxl/mlib-lua.lmt +++ b/tex/context/base/mkxl/mlib-lua.lmt @@ -16,8 +16,6 @@ local report = logs.reporter("metapost","instance") local codes = mplib.getcodes() local types = mplib.gettypes() --- for k,v in next, mplib do if type(v) == "function" then local f = v mplib[k] = function(...) print(k) return v(...) end end end - table.hashed(codes) table.hashed(types) @@ -29,6 +27,7 @@ local skip = mp.skip local get = mp.get local inject = mp.inject +local bpfactor = number.dimenfactors.bp local currentmpx = nil local stack = { } @@ -106,6 +105,12 @@ inject.whatever = function(...) if trace then reporti("whatever") inject.triplet = inject.color inject.quadruplet = inject.cmykcolor +-- these can be optimized for zero: + +inject.whd = function(w,h,d) injectcolor (currentmpx,(w or 0)*bpfactor,(h or 0)*bpfactor,(d or 0)*bpfactor) end +inject.xy = function(x,y) injectpair (currentmpx,(x or 0)*bpfactor,(y or 0)*bpfactor) end +inject.pt = function(n) injectnumeric(currentmpx,(x or 0)*bpfactor) end + local function same(p,n) local f = p[1] local l = p[n] @@ -122,35 +127,6 @@ local function same(p,n) return false end --- local p = mp.scan.path() --- mp.inject.path(p,true,true) - --- function inject.path(p,close,connector) --- local curled = false --- local n = #p --- if p.close or p.cycle then --- close = true --- end --- if p.curled then --- curled = true --- end --- if n > 1 then --- -- [ ../true | --/false | nil/auto ] --- if connector == nil or connector == "auto" then --- connector = #p[1] > 2 --- end --- if connector == false or connector == "--" then --- curled = true --- elseif connector == true or connector == ".." then --- if close and not same(p,n) then --- p[n+1] = p[1] --- end --- end --- end --- if trace then reporti("path") end --- return injectpath(currentmpx,p,close,curled) --- end - function inject.path(p,close,connector) local closed = false local curled = false diff --git a/tex/context/base/mkxl/mlib-mpf.lmt b/tex/context/base/mkxl/mlib-mpf.lmt index 086bfb0ea..7c359fe96 100644 --- a/tex/context/base/mkxl/mlib-mpf.lmt +++ b/tex/context/base/mkxl/mlib-mpf.lmt @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['mlib-mpf'] = { -- moved from mlib-lua: local type, tostring, tonumber, select, loadstring = type, tostring, tonumber, select, loadstring -local find, match, gsub, gmatch = string.find, string.match, string.gsub, string.gmatch +local find, gsub = string.find, string.gsub local concat = table.concat local formatters = string.formatters @@ -31,8 +31,6 @@ local set = mp.set local get = mp.get local aux = mp.aux local scan = mp.scan -local skip = mp.skip -local inject = mp.inject do @@ -41,7 +39,7 @@ do local f_integer = formatters["%i"] local f_numeric = formatters["%F"] - -- no %n as that can produce -e notation and that is not so nice for scaled butmaybe we + -- no %n as that can produce -e notation and that is not so nice for scaled but maybe we -- should then switch between ... i.e. make a push/pop for the formatters here ... not now. local f_integer = formatters["%i"] @@ -127,31 +125,9 @@ do local buffer = gbuffer local n = 0 - local function mpdirect1(a) + local function mpdirect(a) n = n + 1 buffer[n] = a end - local function mpdirect2(a,b) - n = n + 1 buffer[n] = a - n = n + 1 buffer[n] = b - end - local function mpdirect3(a,b,c) - n = n + 1 buffer[n] = a - n = n + 1 buffer[n] = b - n = n + 1 buffer[n] = c - end - local function mpdirect4(a,b,c,d) - n = n + 1 buffer[n] = a - n = n + 1 buffer[n] = b - n = n + 1 buffer[n] = c - n = n + 1 buffer[n] = d - end - local function mpdirect5(a,b,c,d,e) - n = n + 1 buffer[n] = a - n = n + 1 buffer[n] = b - n = n + 1 buffer[n] = c - n = n + 1 buffer[n] = d - n = n + 1 buffer[n] = e - end local function mpflush(separator) buffer[1] = concat(buffer,separator or "",1,n) @@ -299,7 +275,7 @@ do -- writers - local function mpp(value) + local function rawmpp(value) n = n + 1 local t = type(value) if t == "number" then @@ -320,13 +296,13 @@ do local function mpprint(first,second,...) if second == nil then if first ~= nil then - mpp(first) + rawmpp(first) end else for i=1,select("#",first,second,...) do local value = (select(i,first,second,...)) if value ~= nil then - mpp(value) + rawmpp(value) end end end @@ -404,7 +380,7 @@ do if type(x) == "table" then buffer[n] = f_pair(x[1],x[2]) else - buffer[n] = f_pair(x,y) + buffer[n] = f_pair(x,y or x) end end @@ -413,7 +389,7 @@ do if type(x) == "table" then buffer[n] = f_pair_pt(x[1],x[2]) else - buffer[n] = f_pair_pt(x,y) + buffer[n] = f_pair_pt(x,y or x) end end @@ -605,11 +581,7 @@ do end end - aux.direct = mpdirect1 - aux.direct1 = mpdirect1 - aux.direct2 = mpdirect2 - aux.direct3 = mpdirect3 - aux.direct4 = mpdirect4 + aux.direct = mpdirect aux.flush = mpflush aux.print = mpprint @@ -705,12 +677,29 @@ do for k, v in next, aux do mp[k] = v end + -- mp.print = table.setmetatablecall(aux, function(t,...) + -- mpprint(...) + -- end) + + mp.print = table.setmetatablecall(aux, function(t,first,second,...) + if second == nil then + if first ~= nil then + rawmpp(first) + end + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + rawmpp(value) + end + end + end + end) + end do - -- Another experimental feature: - local mpnumeric = mp.numeric local scanstring = scan.string local scriptindex = metapost.scriptindex @@ -729,27 +718,6 @@ do end --- the next will move to mlib-lmp.lua - -do - - local mpnamedcolor = attributes.colors.mpnamedcolor - local mpprint = aux.print - local scanstring = scan.string - - mp.mf_named_color = function(str) - mpprint(mpnamedcolor(str)) - end - - -- todo: we can inject but currently we always get a string back so then - -- we need to deal with it upstream in the color module ... not now - - metapost.registerscript("namedcolor",function() - mpprint(mpnamedcolor(scanstring())) - end) - -end - function mp.n(t) -- used ? return type(t) == "table" and #t or 0 end @@ -839,407 +807,14 @@ end -- texts: -do - - local mptriplet = mp.triplet - - local bpfactor = number.dimenfactors.bp - local textexts = nil - local mptriplet = mp.triplet - local nbdimensions = nodes.boxes.dimensions - - function mp.mf_tt_initialize(tt) - textexts = tt - end - - function mp.mf_tt_dimensions(n) - local box = textexts and textexts[n] - if box then - -- could be made faster with nuts but not critical - mptriplet(box.width*bpfactor,box.height*bpfactor,box.depth*bpfactor) - else - mptriplet(0,0,0) - end - end - - function mp.mf_tb_dimensions(category,name) - local w, h, d = nbdimensions(category,name) - mptriplet(w*bpfactor,h*bpfactor,d*bpfactor) - end - - -- todo: scan ( ... ) - - function mp.report(a,b,c,...) - if c then - report_message("%s : %s",a,formatters[(gsub(b,"@","%%"))](c,...)) - elseif b then - report_message("%s : %s",a,b) - elseif a then - report_message("message : %s",a) - end - end - -end - -do - - local mpprint = aux.print - local modes = tex.modes - local systemmodes = tex.systemmodes - - function mp.mode(s) - mpprint(modes[s] and true or false) - end - - function mp.systemmode(s) - mpprint(systemmodes[s] and true or false) - end - - mp.processingmode = mp.mode - -end - --- for alan's nodes: - -do - - local mpprint = aux.print - local mpquoted = aux.quoted - - function mp.isarray(str) - mpprint(find(str,"%d") and true or false) - end - - function mp.prefix(str) - mpquoted(match(str,"^(.-)[%d%[]") or str) - end - - -- function mp.dimension(str) - -- local n = 0 - -- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg - -- n = n + 1 - -- end - -- mpprint(n) - -- end - - mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint) - - -- faster and okay as we don't have many variables but probably only - -- basename makes sense and even then it's not called that often - - -- local hash = table.setmetatableindex(function(t,k) - -- local v = find(k,"%d") and true or false - -- t[k] = v - -- return v - -- end) - -- - -- function mp.isarray(str) - -- mpprint(hash[str]) - -- end - -- - -- local hash = table.setmetatableindex(function(t,k) - -- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"' - -- t[k] = v - -- return v - -- end) - -- - -- function mp.prefix(str) - -- mpprint(hash[str]) - -- end - -end - -do - - local scanstring = scan.string - local scannumeric = scan.numeric - local scaninteger = scan.integer - local skiptoken = skip.token - - ----- injectstring = inject.string - ----- injectnumeric = inject.numeric - - local registerdirect = metapost.registerdirect - local registerscript = metapost.registerscript - - local comma_code = metapost.codes.comma - - local getmacro = tokens.getters.macro - local setmacro = tokens.setters.macro - - local getdimen = tex.getdimen - local getcount = tex.getcount - local gettoks = tex.gettoks - local setdimen = tex.setdimen - local setcount = tex.setcount - local settoks = tex.settoks - - local bpfactor = number.dimenfactors.bp - - -- more helpers - - -- registerscript("getmacro", function() injectstring (getmacro(scanstring())) end) - -- registerscript("getcount", function() injectnumeric(getcount(scanstring())) end) - -- registerscript("gettoks", function() injectstring (gettoks (scanstring())) end) - -- registerscript("getdimen", function() injectnumeric(getdimen(scanstring()) * bpfactor) end) - - registerdirect("getmacro", function() return getmacro(scanstring()) end) - registerdirect("getcount", function() return getcount(scanstring()) end) - registerdirect("gettoks", function() return gettoks (scanstring()) end) - registerdirect("getdimen", function() return getdimen(scanstring()) * bpfactor end) - - registerscript("setmacro", function() setmacro(scanstring(),scanstring()) end) - registerscript("setdimen", function() setdimen(scanstring(),scannumeric()/bpfactor) end) - registerscript("setcount", function() setcount(scanstring(),scannumeric()) end) - registerscript("settoks", function() settoks (scanstring(),scanstring()) end) - - registerscript("setglobalmacro", function() setmacro(scanstring(),scanstring(),"global") end) - registerscript("setglobaldimen", function() setdimen("global",scanstring(),scannumeric()/bpfactor) end) - registerscript("setglobalcount", function() setcount("global",scanstring(),scaninteger()) end) - registerscript("setglobaltoks", function() settoks ("global",scanstring(),scanstring()) end) - - local utfnum = utf.byte - local utflen = utf.len - local utfsub = utf.sub - - -- registerscript("utfnum", function() injectnumeric(utfnum(scanstring())) end) - -- registerscript("utflen", function() injectnumeric(utflen(scanstring())) end) - -- - -- registerscript("utfsub", function() -- we have an optional third argument so we explicitly scan a text argument - -- injectstring(utfsub(scanstring(),skiptoken(comma_code) and scannumeric(),skiptoken(comma_code) and scannumeric())) - -- end) - - registerdirect("utfnum", function() return utfnum(scanstring()) end) - registerdirect("utflen", function() return utflen(scanstring()) end) - - registerdirect("utfsub", function() -- we have an optional third argument so we explicitly scan a text argument - utfsub(scanstring(),skiptoken(comma_code) and scannumeric(),skiptoken(comma_code) and scannumeric()) - end) - - local setlogging = metapost.setlogging - - registerscript("message", function() - setlogging(false) - local str = scanstring() - setlogging(true) - report_message("message : %s",str) - end) - -end - --- position fun - -do - - local mpprint = mp.print - local mpfprint = mp.fprint - local mpquoted = mp.quoted - local jobpositions = job.positions - local getwhd = jobpositions.whd - local getxy = jobpositions.xy - local getposition = jobpositions.position - local getpage = jobpositions.page - local getregion = jobpositions.region - local getmacro = tokens.getters.macro - - function mp.positionpath(name) - local w, h, d = getwhd(name) - if w then - mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",0,-d,w,-d,w,h,0,h) - else - mpprint("(origin--cycle)") - end - end - - function mp.positioncurve(name) - local w, h, d = getwhd(name) - if w then - mpfprint("((%p,%p)..(%p,%p)..(%p,%p)..(%p,%p)..cycle)",0,-d,w,-d,w,h,0,h) - else - mpprint("(origin--cycle)") - end - end - - function mp.positionbox(name) - local p, x, y, w, h, d = getposition(name) - if p then - mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h) - else - mpprint("(%p,%p)",x,y) - end - end - - function mp.positionxy(name) - local x, y = getxy(name) - if x then - mpfprint("(%p,%p)",x,y) - else - mpprint("origin") - end - end - - function mp.positionpage(name) - mpfprint("%i",getpage(name) or 0) - end - - function mp.positionregion(name) - local r = getregion(name) - if r then - mpquoted(r) - else - mpquoted("unknown") - end - end - - function mp.positionwhd(name) - local w, h, d = getwhd(name) - if w then - mpfprint("(%p,%p,%p)",w,h,d) - else - mpprint("(0,0,0)") - end - end - - function mp.positionpxy(name) - local p, x, y = getposition(name) - if p then - mpfprint("(%p,%p,%p)",p,x,y) - else - mpprint("(0,0,0)") - end - end - - function mp.positionanchor() - mpquoted(getmacro("MPanchorid")) - end - -end - -do - - -- local mppair = mp.pair - -- - -- function mp.textextanchor(s) - -- local x, y = match(s,"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg - -- if x and y then - -- x = tonumber(x) - -- y = tonumber(y) - -- end - -- mppair(x or 0,y or 0) - -- end - - local injectpair = inject.pair - local scanstring = scan.string - - metapost.registerscript("textextanchor", function() - local x, y = match(scanstring(),"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg - if x and y then - x = tonumber(x) - y = tonumber(y) - end - injectpair(x or 0,y or 0) - end) - -end - -do - - local mpprint = mp.print - local mpquoted = mp.quoted - local getmacro = tokens.getters.macro - - function mp.texvar(name) - mpprint(getmacro(metapost.namespace .. name)) - end - - function mp.texstr(name) - mpquoted(getmacro(metapost.namespace .. name)) - end - -end - -do - - local mpprint = aux.print - local mpvprint = aux.vprint - - local hashes = { } - - function mp.newhash(name) - if name then - hashes[name] = { } - else - for i=1,#hashes+1 do - if not hashes[i] then - hashes[i] = { } - mpvprint(i) - return - end - end - end - end - - function mp.disposehash(n) - if tonumber(n) then - hashes[n] = false - else - hashes[n] = nil - end +function mp.report(a,b,c,...) + if c then + report_message("%s : %s",a,formatters[(gsub(b,"@","%%"))](c,...)) + elseif b then + report_message("%s : %s",a,b) + elseif a then + report_message("message : %s",a) end - - function mp.inhash(n,key) - local h = hashes[n] - mpvprint(h and h[key] and true or false) - end - - function mp.tohash(n,key,value) - local h = hashes[n] - if h then - if value == nil then - h[key] = true - else - h[key] = value - end - end - end - - function mp.fromhash(n,key) - local h = hashes[n] - mpvprint(h and h[key] or false) - end - - interfaces.implement { - name = "MPfromhash", - arguments = "2 strings", - actions = function(name,key) - local h = hashes[name] or hashes[tonumber(name)] - if h then - local v = h[key] or h[tonumber(key)] - if v then - context(v) - end - end - end - } - -end - -do - - -- a bit overkill: just a find(str,"mf_object=") can be enough - -- - -- todo : share with mlib-pps.lua metapost,isobject - - local mpboolean = aux.boolean - - local p1 = P("mf_object=") - local p2 = lpegpatterns.eol * p1 - local pattern = (1-p2)^0 * p2 + p1 - - function mp.isobject(str) - mpboolean(pattern and str ~= "" and lpegmatch(pattern,str)) - end - end function mp.flatten(t) diff --git a/tex/context/base/mkxl/mlib-pos.lmt b/tex/context/base/mkxl/mlib-pos.lmt index 5ea0e1a1e..fd54d7b5f 100644 --- a/tex/context/base/mkxl/mlib-pos.lmt +++ b/tex/context/base/mkxl/mlib-pos.lmt @@ -57,3 +57,7 @@ registerdirect("getposupperleft", function() local x, y = upperleft (scanstring registerdirect("getposlowerleft", function() local x, y = lowerleft (scanstring()) t[1] = x * factor t[2] = y * factor return t end) registerdirect("getposupperright", function() local x, y = upperright(scanstring()) t[1] = x * factor t[2] = y * factor return t end) registerdirect("getposlowerright", function() local x, y = lowerright(scanstring()) t[1] = x * factor t[2] = y * factor return t end) +registerdirect("getposllx", function() local x, y = lowerleft (scanstring()) return x * factor end) +registerdirect("getposlly", function() local x, y = lowerleft (scanstring()) return y * factor end) +registerdirect("getposurx", function() local x, y = upperright(scanstring()) return x * factor end) +registerdirect("getposury", function() local x, y = upperright(scanstring()) return y * factor end) diff --git a/tex/context/base/mkxl/mlib-run.lmt b/tex/context/base/mkxl/mlib-run.lmt index 3e950a2d9..bf3d5434a 100644 --- a/tex/context/base/mkxl/mlib-run.lmt +++ b/tex/context/base/mkxl/mlib-run.lmt @@ -379,49 +379,6 @@ function metapost.reset(mpx) end end --- key/values - -do - - local stack, top = { }, nil - - function metapost.setvariable(k,v) - if top then - top[k] = v - else - metapost.variables[k] = v - end - end - - function metapost.pushvariable(k) - local t = { } - if top then - insert(stack,top) - top[k] = t - else - metapost.variables[k] = t - end - top = t - end - - function metapost.popvariable() - top = remove(stack) - end - - local stack = { } - - function metapost.pushvariables() - insert(stack,metapost.variables) - metapost.variables = { } - end - - function metapost.popvariables() - metapost.variables = remove(stack) or metapost.variables - end - -end - - if not metapost.process then function metapost.process(specification) diff --git a/tex/context/base/mkxl/mlib-scn.lmt b/tex/context/base/mkxl/mlib-scn.lmt index 56fdce0fb..d92ef1385 100644 --- a/tex/context/base/mkxl/mlib-scn.lmt +++ b/tex/context/base/mkxl/mlib-scn.lmt @@ -165,6 +165,15 @@ end) scanners.typescanners = typescanners scanners.tokenscanners = tokenscanners +scanners.whatever = function() + local kind = scantoken(true) + if kind == leftdelimiter_code or kind == tag_code or kind == capsule_code then + return (typescanners[scanexpression(true)] or scanexpression)() + else + return tokenscanners[kind]() + end +end + -- a key like 'color' has code 'declare' local function scanparameters(fenced) diff --git a/tex/context/base/mkxl/mult-sys.mkxl b/tex/context/base/mkxl/mult-sys.mkxl index 2941a7b08..6b8379753 100644 --- a/tex/context/base/mkxl/mult-sys.mkxl +++ b/tex/context/base/mkxl/mult-sys.mkxl @@ -399,6 +399,8 @@ \definesystemconstant {ymove} \definesystemconstant {yoffset} +\definesystemconstant {syncpos} + %D As the name of their define command states, the next set of constants is used in %D the message macro's. diff --git a/tex/context/base/mkxl/node-nut.lmt b/tex/context/base/mkxl/node-nut.lmt index b5a371d5e..7970c1fe5 100644 --- a/tex/context/base/mkxl/node-nut.lmt +++ b/tex/context/base/mkxl/node-nut.lmt @@ -150,6 +150,7 @@ local nuts = { insertbefore = d_insertbefore, appendaftertail = direct.appendaftertail, prependbeforehead = direct.prependbeforehead, + getparstate = direct.getparstate, isdirect = isdirect, isnode = isnode, isnut = isdirect, diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl index 42b472aa2..96872647a 100644 --- a/tex/context/base/mkxl/pack-rul.mkxl +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -558,8 +558,8 @@ \edef\m_overlay_region{\reservedautoregiontag}% \fi} -\def\pack_framed_add_region % experiment - {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} +\def\pack_framed_add_region % experiment, zerocount forces the given region + {\anch_mark_tagged_box\b_framed_normal\m_overlay_region\zerocount} \def\pack_framed_add_background {\ifconditional\c_pack_reanchor diff --git a/tex/context/base/mkxl/page-box.mklx b/tex/context/base/mkxl/page-box.mklx index c8ceeb828..c962b831a 100644 --- a/tex/context/base/mkxl/page-box.mklx +++ b/tex/context/base/mkxl/page-box.mklx @@ -59,15 +59,6 @@ \v_page_target_bottom_fill \v_page_target_bottom}} -\def\page_boxes_apply_offset % #box - {\unless\ifzeropt\topoffset - \expandafter\page_boxes_apply_offset_indeed - \orelse\ifzeropt\backoffset - \expandafter\gobbleoneargument - \else - \expandafter\page_boxes_apply_offset_indeed - \fi} - \def\page_boxes_apply_offset_indeed#box% {\scratchwidth \wd#box% \scratchheight\ht#box% @@ -75,12 +66,28 @@ \setbox#box\vpack {\offinterlineskip \vskip\topoffset - \hskip\doifbothsides\backoffset\backoffset{-\backoffset}% + %\hskip\doifbothsides\backoffset\backoffset{-\backoffset}% + \hskip\doifbothsides++-\backoffset \box#box}% \wd#box\scratchwidth \ht#box\scratchheight \dp#box\scratchdepth} +% a variant (no gain so we stay mkiv compatible): +% +% \def\page_boxes_apply_offset_indeed#box% this needs testing in real situations +% {\boxxoffset#box\dimexpr\boxxoffset#box\doifbothsides++-\backoffset\relax +% \boxyoffset#box\dimexpr\boxyoffset#box-\topoffset\relax} + +\def\page_boxes_apply_offset % #box + {\unless\ifzeropt\topoffset + \expandafter\page_boxes_apply_offset_indeed + \orunless\ifzeropt\backoffset + \expandafter\page_boxes_apply_offset_indeed + \else + \expandafter\gobbleoneargument + \fi} + \def\page_boxes_apply_replicate {\ifnum\layoutparameter\c!nx>\plusone \expandafter\page_boxes_apply_replicate_indeed @@ -251,6 +258,15 @@ \box#1}% \dp#1\zeropoint} +% a variant (no gain so we stay mkiv compatible): +% +% \def\page_boxes_apply_offsets#1% +% {\scratchhoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}% +% \boxxoffset#1\dimexpr\boxxoffset#1+\scratchhoffset\relax +% \boxyoffset#1\dimexpr\boxyoffset#1-\topspace\relax +% \wd#1\dimexpr\paperwidth+\scratchhoffset\relax +% \ht#1\dimexpr\paperheight+\topspace\relax} + %D This is rather specialized: \newconditional\c_page_areas_enabled diff --git a/tex/context/base/mkxl/page-lay.mkxl b/tex/context/base/mkxl/page-lay.mkxl index a4f4666e2..835a3ca4b 100644 --- a/tex/context/base/mkxl/page-lay.mkxl +++ b/tex/context/base/mkxl/page-lay.mkxl @@ -469,35 +469,58 @@ \global\c_page_target_print_orientation\uprotationangle \global\c_page_target_print_reverse \uprotationangle} -\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper -\letvalue{\??layoutprint\v!reset}\page_paper_reset_print - -\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape} -\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror} -\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate} -\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle - \global\c_page_target_paper_reverse \leftrotationangle} -\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle - \global\c_page_target_paper_reverse \leftrotationangle} -\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle - \global\c_page_target_paper_reverse \zerocount} -\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle - \global\c_page_target_paper_reverse \rightrotationangle} - -\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape} -\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror} -\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate} -\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle - \global\c_page_target_print_reverse \leftrotationangle} -\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle - \global\c_page_target_print_reverse \leftrotationangle} -\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle - \global\c_page_target_print_reverse \zerocount} -\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle - \global\c_page_target_print_reverse \rightrotationangle} - -%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi} -%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi} +\letcsname\??layoutpaper\v!reset\endcsname\page_paper_reset_paper +\letcsname\??layoutprint\v!reset\endcsname\page_paper_reset_print + +\defcsname\??layoutpaper\v!landscape\endcsname + {\global\settrue\c_page_target_paper_landscape} + +\defcsname\??layoutpaper\v!mirrored\endcsname + {\global\settrue\c_page_target_paper_mirror} + +\defcsname\??layoutpaper\v!negative\endcsname + {\global\settrue\c_page_target_paper_negate} + +\defcsname\??layoutpaper\v!rotated\endcsname + {\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} + +\defcsname\??layoutpaper\number\rightrotationangle\endcsname + {\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} + +\defcsname\??layoutpaper\number\downrotationangle\endcsname + {\global\c_page_target_paper_orientation\downrotationangle + \global\c_page_target_paper_reverse \zerocount} + +\defcsname\??layoutpaper\number\leftrotationangle\endcsname + {\global\c_page_target_paper_orientation\leftrotationangle + \global\c_page_target_paper_reverse \rightrotationangle} + +\defcsname\??layoutprint\v!landscape\endcsname + {\global\settrue\c_page_target_print_landscape} + +\defcsname\??layoutprint\v!mirrored\endcsname + {\global\settrue\c_page_target_print_mirror} + +\defcsname\??layoutprint\v!negative\endcsname + {\global\settrue\c_page_target_print_negate} + +\defcsname\??layoutprint\v!rotated\endcsname + {\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} + +\defcsname\??layoutprint\number\rightrotationangle\endcsname + {\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} + +\defcsname\??layoutprint\number\downrotationangle \endcsname + {\global\c_page_target_print_orientation\downrotationangle + \global\c_page_target_print_reverse \zerocount} + +\defcsname\??layoutprint\number\leftrotationangle \endcsname + {\global\c_page_target_print_orientation\leftrotationangle + \global\c_page_target_print_reverse \rightrotationangle} \def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname} \def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname} @@ -847,13 +870,6 @@ \installlayoutmethod\v!default{\page_layouts_check_default} \installlayoutmethod\v!normal {\page_layouts_check_default} -% \def\page_layouts_check_next -% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname -% \layoutparameter\c!method -% \else -% \v!normal -% \fi\endcsname} - \permanent\protected\def\page_layouts_check_next {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname \lastnamedcs @@ -907,41 +923,55 @@ {\setfalse\c_page_layouts_location_is_set \setfalse\c_page_layouts_location_is_middle \let\v_page_target_left_fill \relax - \let\v_page_target_right_fill \hss % ? \relax + \let\v_page_target_right_fill \hss % ? \relax \let\v_page_target_top_fill \relax \let\v_page_target_bottom_fill\vss} % \relax} -\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \hss - \let\v_page_target_right_fill \relax} -\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \relax - \let\v_page_target_right_fill \hss} -\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_top_fill \vss - \let\v_page_target_bottom_fill\relax} -\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_top_fill \relax - \let\v_page_target_bottom_fill\vss} -\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set - \settrue\c_page_layouts_location_is_middle - \let\v_page_target_left_fill \hss - \let\v_page_target_right_fill \hss - \let\v_page_target_top_fill \vss - \let\v_page_target_bottom_fill\vss} -\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_ - \setfalse\c_page_layouts_location_is_middle - \let\v_page_target_right_fill \hss - \let\v_page_target_bottom_fill\hss} -\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided} -\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided} +\defcsname\??layoutlocation\v!right\endcsname + {\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill\relax} + +\defcsname\??layoutlocation\v!left\endcsname + {\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \relax + \let\v_page_target_right_fill\hss} + +\defcsname\??layoutlocation\v!bottom\endcsname + {\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\relax} + +\defcsname\??layoutlocation\v!top\endcsname + {\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \relax + \let\v_page_target_bottom_fill\vss} + +\defcsname\??layoutlocation\v!middle\endcsname + {\settrue\c_page_layouts_location_is_set + \settrue\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill \hss + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\vss} + +\defcsname\??layoutlocation\empty\endcsname + {\setfalse\c_page_layouts_location_is_set % default also signal to scrn_ + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_right_fill \hss + \let\v_page_target_bottom_fill\hss} + +\defcsname\??layoutlocation\v!doublesided\endcsname + {\settrue\c_page_target_print_doublesided} + +\defcsname\??layoutlocation\v!singlesided\endcsname + {\setfalse\c_page_target_print_doublesided} \def\page_target_check_centering_indeed#1% - % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi} {\begincsname\??layoutlocation#1\endcsname} \protected\def\page_target_check_centering @@ -967,13 +997,6 @@ \installlayoutalternative\v!default{\page_boxes_construct_content_default} \installlayoutalternative\v!normal {\page_boxes_construct_content_default} -% \def\page_boxes_construct_content % targetbox flusher box -% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname -% \layoutparameter\c!alternative -% \else -% \v!normal -% \fi\endcsname} - \def\page_boxes_construct_content % targetbox flusher box {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname \expandafter\lastnamedcs @@ -1031,9 +1054,9 @@ \global\d_page_adapts_height\footerheight \fi \fi -% + % \global\d_page_adapts_delta-\dimexpr\adaptlayoutparameter\c!top\relax -% + % \global\advance\textheight \d_page_adapts_height \global\advance\footerheight-\d_page_adapts_height \showmessage\m!layouts1{\the\dimexpr\d_page_adapts_height,\the\realpageno}% @@ -1044,14 +1067,6 @@ \glet\page_adapts_push\relax \glet\page_adapts_pop\page_adapts_pop_indeed} -% \def\page_adapts_check -% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname} -% -% \def\page_adapts_reset -% {\ifcsname\??pageadaptations\the\realpageno\endcsname -% \global\undefinevalue{\??pageadaptations\the\realpageno}% -% \fi} - \def\page_adapts_check {\begincsname\??pageadaptations\the\realpageno\endcsname} diff --git a/tex/context/base/mkxl/page-otr.mklx b/tex/context/base/mkxl/page-otr.mklx index b24fa62e3..adca25eb5 100644 --- a/tex/context/base/mkxl/page-otr.mklx +++ b/tex/context/base/mkxl/page-otr.mklx @@ -86,10 +86,9 @@ \let\page_otr_specifics_preset\page_otr_specifics_preset_traced \to \t_page_otr_tracers -%D We have a couple of output routines and the default one is -%D the single column routine. Then there is a multicolumn variant -%D that can be used mixed, and a columnset variant that is more -%D exclusive. +%D We have a couple of output routines and the default one is the single column +%D routine. Then there is a multicolumn variant that can be used mixed, and a +%D columnset variant that is more exclusive. \installcorenamespace{otrtriggers} @@ -176,26 +175,6 @@ #content\relax \the\everyafteroutput}} -% Just as fuzzy (and in 'one' we are okay with \aftergroup anyway): -% -% \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi -% \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi -% -% \def\page_otr_set_engine_output_routine#content% -% {\the\everybeforeoutputgroup -% \global\output -% {\inotrtrue -% \the\everybeforeoutput -% #content\relax -% \the\everyafteroutput -% \aftergroup\the\aftergroup\everyafteroutputgroup}} -% -% \appendtoks -% \ifnum\c_page_postponed_mode=\plusone -% \page_postponed_blocks_flush % and then not in \page_otr_construct_and_shipout -% \fi -% \to \everyafteroutputgroup - \page_otr_set_engine_output_routine\page_otr_triggered_output_routine \installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead @@ -261,16 +240,14 @@ \penalty\c_page_otr_super_penalty \resetpagebreak} -%D For those who've read the plain \TEX\ book, we provide the next -%D macro: +%D For those who've read the plain \TEX\ book, we provide the next macro: \permanent\protected\def\bye {\writestatus\m!system{Sorry, you're not done yet, so no goodbye!}} -%D We define a few constants because that (1) provides some checking -%D and (2) is handier when aligning definitions (checks nicer). Most -%D routines will use ard codes names but sometimes we want to adapt, -%D which is why we have these: +%D We define a few constants because that (1) provides some checking and (2) is +%D handier when aligning definitions (checks nicer). Most routines will use ard +%D codes names but sometimes we want to adapt, which is why we have these: \definesystemconstant{page_otr_command_routine} \definesystemconstant{page_otr_command_package_contents} diff --git a/tex/context/base/mkxl/scrn-wid.mklx b/tex/context/base/mkxl/scrn-wid.mklx index 724bdb807..b35047d94 100644 --- a/tex/context/base/mkxl/scrn-wid.mklx +++ b/tex/context/base/mkxl/scrn-wid.mklx @@ -652,6 +652,12 @@ \let\m_scrn_rendering_page\!!zerocount +%D \starttyping +%D \definerenderingwindow[soundplace][width=0pt, height=0pt] +%D \useexternalrendering[mainsound][audio/mp3][sound.mp3][embed=yes] +%D \placerenderingwindow[soundplace][mainsound] +%D \stoptyping + \installcorenamespace{renderingwindow} \installframedcommandhandler \??renderingwindow {renderingwindow} \??renderingwindow diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl index 0a378d500..95be0a352 100644 --- a/tex/context/base/mkxl/spac-hor.mkxl +++ b/tex/context/base/mkxl/spac-hor.mkxl @@ -810,8 +810,8 @@ \permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} \permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} -\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\permanent\advance\leftskip \leftskipadaption } -\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\permanent\advance\rightskip\rightskipadaption} +\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\frozen\advance\leftskip \leftskipadaption } +\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\frozen\advance\rightskip\rightskipadaption} \permanent\protected\def\forgetbothskips {\leftskip\zeropoint diff --git a/tex/context/base/mkxl/spac-ver.lmt b/tex/context/base/mkxl/spac-ver.lmt index 1af5096fb..cae0f1d78 100644 --- a/tex/context/base/mkxl/spac-ver.lmt +++ b/tex/context/base/mkxl/spac-ver.lmt @@ -687,19 +687,19 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut] return h, d, ch, cd, lines, extra end -local categories = { - [0] = "discard", - [1] = "largest", - [2] = "force", - [3] = "penalty", - [4] = "add", - [5] = "disable", - [6] = "nowhite", - [7] = "goback", - [8] = "packed", - [9] = "overlay", - [10] = "enable", - [11] = "notopskip", +local categories = { [0] = + "discard", + "largest", + "force", + "penalty", + "add", + "disable", + "nowhite", + "goback", + "packed", + "overlay", + "enable", + "notopskip", } categories = allocate(table.swapped(categories,categories)) diff --git a/tex/context/base/mkxl/strc-des.mklx b/tex/context/base/mkxl/strc-des.mklx index 835c6807e..9f9119466 100644 --- a/tex/context/base/mkxl/strc-des.mklx +++ b/tex/context/base/mkxl/strc-des.mklx @@ -58,6 +58,7 @@ %\s!catcodes=, \c!title=\v!yes, %\c!text=, + \c!define=\v!yes, ] \appendtoks @@ -67,9 +68,11 @@ \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]% \fi % We can combine these but in tracing (or errors) using a different caller is nicer. - \frozen\protected\instance\edefcsname \currentdescription\endcsname{\nameddescription[\currentdescription]}% - \frozen\protected\instance\edefcsname\e!start\currentdescription\endcsname{\startnameddescription[\currentdescription]}% - \frozen\protected\instance \defcsname \e!stop\currentdescription\endcsname{\stopnameddescription}% + \ifcstok{\descriptionparameter\c!define}\v!yes + \frozen\protected\instance\edefcsname \currentdescription\endcsname{\nameddescription[\currentdescription]}% + \frozen\protected\instance\edefcsname\e!start\currentdescription\endcsname{\startnameddescription[\currentdescription]}% + \frozen\protected\instance \defcsname \e!stop\currentdescription\endcsname{\stopnameddescription}% + \fi \to \everydefinedescription \let\p_strc_constructions_title \empty diff --git a/tex/context/base/mkxl/strc-enu.mklx b/tex/context/base/mkxl/strc-enu.mklx index a6ba99ce7..fd98b11f3 100644 --- a/tex/context/base/mkxl/strc-enu.mklx +++ b/tex/context/base/mkxl/strc-enu.mklx @@ -120,7 +120,8 @@ \c!number=\v!yes, % else description \c!start=0, \c!state=\v!start, - \c!levels=4] + \c!levels=4, + \c!define=\v!yes] % to be considered: % @@ -129,17 +130,21 @@ % with push/pop (also at definition time) \protected\def\strc_define_commands_enumeration#tag#level#parent% - {\doifelsenothing{#parent} - {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}% - \edefcsname\??enumeration#tag:\s!parent\endcsname{\??enumeration}}% - {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}% - \edefcsname\??enumeration#tag:\s!parent\endcsname{\??enumeration#parent}}% - \frozen\protected\instance\edefcsname\e!next #tag\endcsname{\strc_enumerations_next{#tag}{\number#level}}% obsolete - \frozen\protected\instance\edefcsname\c!reset#tag\endcsname{\strc_enumerations_reset{#tag}{\number#level}}% obsolete - %frozen\protected\instance\edefcsname\c!set #tag\endcsname{\strc_enumerations_set{#tag}{\number#level}}% obsolete - \frozen\protected\instance\edefcsname #tag\endcsname{\namedenumeration[#tag]}% - \frozen\protected\instance\edefcsname\e!start#tag\endcsname{\startnamedenumeration[#tag]}% - \frozen\protected\instance \defcsname\e!stop #tag\endcsname{\stopnamedenumeration}} + {\iftok{#parent}\emptytoks + \normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}% + \edefcsname\??enumeration#tag:\s!parent\endcsname{\??enumeration}% + \else + \normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}% + \edefcsname\??enumeration#tag:\s!parent\endcsname{\??enumeration#parent}% + \fi + \ifcstok{\enumerationparameter\c!define}\v!yes + \frozen\protected\instance\edefcsname\e!next #tag\endcsname{\strc_enumerations_next{#tag}{\number#level}}% obsolete + \frozen\protected\instance\edefcsname\c!reset#tag\endcsname{\strc_enumerations_reset{#tag}{\number#level}}% obsolete + %frozen\protected\instance\edefcsname\c!set #tag\endcsname{\strc_enumerations_set{#tag}{\number#level}}% obsolete + \frozen\protected\instance\edefcsname #tag\endcsname{\namedenumeration[#tag]}% + \frozen\protected\instance\edefcsname\e!start#tag\endcsname{\startnamedenumeration[#tag]}% + \frozen\protected\instance \defcsname\e!stop #tag\endcsname{\stopnamedenumeration}% + \fi} \let\m_strc_enumeration_sub\empty diff --git a/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx index ad62a52e5..1f0491cf1 100644 --- a/tex/context/base/mkxl/strc-ref.mklx +++ b/tex/context/base/mkxl/strc-ref.mklx @@ -1234,20 +1234,20 @@ \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing \the\rightreferencetoks} -\letvalue{\??referencinginteraction\v!all}\strc_references_interaction_all +\letcsname\??referencinginteraction\v!all\endcsname\strc_references_interaction_all -\setvalue{\??referencinginteraction\v!label}% +\defcsname\??referencinginteraction\v!label\endcsname {\leftofreference \the\leftreferencetoks \the\rightreferencetoks \rightofreference} -\setvalue{\??referencinginteraction\v!text}% +\defcsname\??referencinginteraction\v!text\endcsname {\leftofreference \currentreferencecontent \rightofreference} -\setvalue{\??referencinginteraction\v!symbol}% +\defcsname\??referencinginteraction\v!symbol\endcsname {\referencesymbol} \permanent\def\referencesequence diff --git a/tex/context/base/mkxl/strc-reg.lmt b/tex/context/base/mkxl/strc-reg.lmt index 6e26f6f37..ccb43bc28 100644 --- a/tex/context/base/mkxl/strc-reg.lmt +++ b/tex/context/base/mkxl/strc-reg.lmt @@ -497,7 +497,22 @@ local function preprocessentries(rawdata) if not ok and etk == "" then entries[k] = nil else - entries[k] = { etk or "", ktk ~= "" and ktk or false, ptk ~= "" and ptk or false } + if not etk then + etk = "" + end + -- we save some space by pruning + if ptk == "" then + ptk = nil + end + -- we save even more space by pruning + if ktk == "" then + if ptk then + ktk = false + else + ktk = nil + end + end + entries[k] = { etk, ktk, ptk } ok = true end end @@ -563,6 +578,7 @@ local function storeregister(rawdata) -- metadata, references, entries -- local data = notsaved and collected[name] or tobesaved[name] local entries = data.entries + -- internalreferences[internal] = rawdata preprocessentries(rawdata) entries[#entries+1] = rawdata diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl index 796c3663a..87660df49 100644 --- a/tex/context/base/mkxl/supp-box.mkxl +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -2437,6 +2437,7 @@ %D \getboxfromcache{foo}{\recurselevel}\zerocount %D \fi %D } +%D % \startMPcode draw rawtexbox("category","name") ; \stopMPcode %D \resetboxesincache{foo} %D \stoptyping diff --git a/tex/context/base/mkxl/syst-aux.lmt b/tex/context/base/mkxl/syst-aux.lmt index 726fd4d32..eeb1c5aac 100644 --- a/tex/context/base/mkxl/syst-aux.lmt +++ b/tex/context/base/mkxl/syst-aux.lmt @@ -648,14 +648,14 @@ implement { -- name = "hascommonargumentcondition", -- actions = hascommonargumentcondition, -- arguments = "2 strings", --- arguments = { "argument", "argument" }, +-- arguments = "2 arguments", -- } implement { name = "doifelseinset", actions = doifelseinset, arguments = "2 strings", --- arguments = { "argument", "argument" }, +-- arguments = "2 arguments", } implement { diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl index 1f58b42a1..f9b40c963 100644 --- a/tex/context/base/mkxl/syst-ini.mkxl +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -1389,10 +1389,12 @@ \permanent\protected\def\newlocaltoks #1{\setnewlocaltoks #1\emptytoks } \permanent\protected\def\newlocalbox #1{\setnewlocalbox #1\emptybox } -%D Let's be detailed: grouplevel:inputlevel: +%D Let's be detailed: grouplevel:inputlevel:catcodetable (bits 1 2 4) \tracinglevels\plusthree +\permanent\protected\def\tracingcatcodes{\tracinglevels\plusseven} + %D We just report duplicate patterns being ignored: \tracinghyphenation\plusone diff --git a/tex/context/base/mkxl/tabl-ntb.mkxl b/tex/context/base/mkxl/tabl-ntb.mkxl index 418164daa..67fc39a89 100644 --- a/tex/context/base/mkxl/tabl-ntb.mkxl +++ b/tex/context/base/mkxl/tabl-ntb.mkxl @@ -1437,14 +1437,14 @@ {\global\advance\c_tabl_ntb_col\plusone \kern\d_tabl_ntb_columndistance} -\setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2% +\defcsname\??naturaltablecell\the\c_tabl_ntb_none\endcsname#1#2% {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax \ifnum\scratchcounter>\zerocount \etoksapp\t_tabl_ntb_row {\tabl_ntb_span{\the\scratchcounter}}% \fi} -\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2% +\defcsname\??naturaltablecell\the\c_tabl_ntb_cell\endcsname#1#2% {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax \ifnum\scratchcounter>\zerocount diff --git a/tex/context/base/mkxl/tabl-tab.mkxl b/tex/context/base/mkxl/tabl-tab.mkxl index e63492984..95d263ecd 100644 --- a/tex/context/base/mkxl/tabl-tab.mkxl +++ b/tex/context/base/mkxl/tabl-tab.mkxl @@ -1429,7 +1429,7 @@ \tolerant\def\tabl_table_define_template[#1]#*[#2]#*[#3]#*[#4]% {\ifarguments\or\else - \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}% + \gdefcsname\??tabletemplate#1\endcsname{\tabl_table_use_template{#2}{#3}{#4}}% \fi \egroup} @@ -1657,9 +1657,6 @@ \newconditional\hassometablehead \newconditional\hassometabletail -% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} -% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} - \permanent\protected\def\settablehead{\dodoubleempty\tabl_table_set_head} % todo: use pickup \permanent\protected\def\settabletail{\dodoubleempty\tabl_table_set_tail} % todo: use pickup diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl index e22fb946c..c48c384f2 100644 --- a/tex/context/base/mkxl/tabl-tbl.mkxl +++ b/tex/context/base/mkxl/tabl-tbl.mkxl @@ -700,9 +700,9 @@ % % \installcorenamespace{tabulatewidth} % -% \setvalue{\??tabulatewidth\v!fit }{\c_tabl_tabulate_modus\plusthree} -% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak} -% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape} +% \defcsname\??tabulatewidth\v!fit \endcsname{\c_tabl_tabulate_modus\plusthree} +% \defcsname\??tabulatewidth\v!fixed\endcsname{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak} +% \defcsname\??tabulatewidth\v!auto \endcsname{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape} % % \def\tabl_tabulate_set_width_step#1% % {\ifcsname\??tabulatewidth#1\endcsname diff --git a/tex/context/base/mkxl/tabl-xtb.mklx b/tex/context/base/mkxl/tabl-xtb.mklx index ba144c322..5aad01884 100644 --- a/tex/context/base/mkxl/tabl-xtb.mklx +++ b/tex/context/base/mkxl/tabl-xtb.mklx @@ -209,8 +209,8 @@ %D We can also define xtables. \appendtoks - \permanent\setuevalue{\e!start\currentxtable}{\tabl_x_start_named[\currentxtable]}% - \permanent\setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}% + \permanent\protected\edefcsname\e!start\currentxtable\endcsname{\tabl_x_start_named[\currentxtable]}% + \permanent\protected\edefcsname\e!stop \currentxtable\endcsname{\tabl_x_stop_named}% \to \everydefinextable \protected\def\tabl_x_start_named[#tag]#spacer[#settings]% diff --git a/tex/context/base/mkxl/util-pck.lmt b/tex/context/base/mkxl/util-pck.lmt new file mode 100644 index 000000000..fff2d280a --- /dev/null +++ b/tex/context/base/mkxl/util-pck.lmt @@ -0,0 +1,176 @@ +if not modules then modules = { } end modules ['util-pck'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- moved from core-uti + +local next, tostring, type = next, tostring, type +local sort, concat = table.sort, table.concat +local format = string.format +local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash + +utilities = utilities or { } +utilities.packers = utilities.packers or { } +local packers = utilities.packers +packers.version = 1.01 + +-- local fmt_kv <const> = "%s=%q" +-- local fmt_kt <const> = "%s={%q}" + +-- local function hashed(t) +-- local s, ns = { }, 0 +-- for k, v in next, t do +-- ns = ns + 1 +-- if type(v) == "table" then +-- s[ns] = format(fmt_kt,k,hashed(v)) +-- else +-- s[ns] = format(fmt_kv,k,v) +-- end +-- end +-- sort(s) +-- return concat(s,",") +-- end + +local function hashed(t) --local function tabstr_normal(t) + local s = { } + local n = 0 + for k, v in next, t do + n = n + 1 + if type(v) == "table" then + s[n] = k .. ">" .. hashed(v) + elseif v == true then + s[n] = k .. "+" -- "=true" + elseif v then + s[n] = k .. "=" .. v + else + s[n] = k .. "-" -- "=false" + end + end + if n == 0 then + return "" + elseif n == 1 then + return s[1] + else + sort(s) -- costly but needed (occasional wrong hit otherwise) + return concat(s,",") + end +end + +local function simplehashed(t) + local s = { } + local n = 0 + for k, v in next, t do + n = n + 1 + -- s[n] = format(fmt_kv,k,v) + s[n] = k .. "=" .. v + end + sort(s) + return concat(s,",") +end + +packers.hashed = hashed +packers.simplehashed = simplehashed + +-- In luatex < 0.74 (lua 5.1) a next chain was the same for each run so no sort was needed, +-- but in the latest greatest versions (lua 5.2) we really need to sort the keys in order +-- not to get endless runs due to a difference in tuc files. + +local function pack(t,keys,skip,hash,index) + if t then + local sk = #t > 0 and sortedkeys(t) or sortedhashkeys(t) + for i=1,#sk do + local k = sk[i] + if not skip or not skip[k] then + local v = t[k] + if type(v) == "table" then + pack(v,keys,skip,hash,index) + if keys[k] then + local h = hashed(v) + local i = hash[h] + if not i then + i = #index + 1 + index[i] = v + hash[h] = i + end + t[k] = i + end + end + end + end + end +end + +local function unpack(t,keys,skip,index) + if t then + for k, v in next, t do + if keys[k] and type(v) == "number" then + local iv = index[v] + if iv then + v = iv + t[k] = v + end + end + if type(v) == "table" and (not skip or not skip[k]) then + unpack(v,keys,skip,index) + end + end + end +end + +function packers.new(keys,version,skip) + return { + version = version or packers.version, + keys = tohash(keys), + skip = tohash(skip), + hash = { }, + index = { }, + } +end + +function packers.pack(t,p,shared) + if shared then + pack(t,p.keys,p.skip,p.hash,p.index) + elseif not t.packer then + pack(t,p.keys,p.skip,p.hash,p.index) + if #p.index > 0 then + t.packer = { + version = p.version or packers.version, + keys = p.keys, + skip = p.skip, + index = p.index, + } + end + p.hash = { } + p.index = { } + end +end + +function packers.unpack(t,p,shared) + if shared then + if p then + unpack(t,p.keys,p.skip,p.index) + end + else + local tp = t.packer + if tp then + if tp.version == (p and p.version or packers.version) then + unpack(t,tp.keys,tp.skip,tp.index) + else + return false + end + t.packer = nil + end + end + return true +end + +function packers.strip(p) + p.hash = nil +end + +-- We could have a packer.serialize where we first flush the shared table +-- and then use inline a reference . This saves an unpack. diff --git a/tex/context/interface/mkii/keys-ro.xml b/tex/context/interface/mkii/keys-ro.xml index e53fbb198..158a8b8ac 100644 --- a/tex/context/interface/mkii/keys-ro.xml +++ b/tex/context/interface/mkii/keys-ro.xml @@ -154,6 +154,7 @@ <cd:variable name='commands' value='comenzi'/> <cd:variable name='comment' value='comentariu'/> <cd:variable name='component' value='componenta'/> + <cd:variable name='compress' value='compress'/> <cd:variable name='compressseparator' value='compressseparator'/> <cd:variable name='compressstopper' value='compressstopper'/> <cd:variable name='concept' value='concept'/> diff --git a/tex/context/modules/mkiv/s-fonts-emoji.mkiv b/tex/context/modules/mkiv/s-fonts-emoji.mkiv index 1f303d569..096b90263 100644 --- a/tex/context/modules/mkiv/s-fonts-emoji.mkiv +++ b/tex/context/modules/mkiv/s-fonts-emoji.mkiv @@ -293,39 +293,64 @@ end \start -\definedfont[seguiemj*seguiemj-cl] +\definedfont[file:seguiemj.any*default,seguiemj-cl] -\ShowEmojiSnippets - [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] +% \ShowEmojiSnippets +% [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] -\ShowEmojiSnippetsOverlay - [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] +% \ShowEmojiSnippetsOverlay +% [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] -\ShowEmojiGlyphs - [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] +% \ShowEmojiGlyphs +% [family man light skin tone woman dark skin tone girl medium skin tone boy medium skin tone] -\page +% \page -\ShowEmoji[^man] +% \ShowEmoji[^man] -\page +% \ShowEmoji[backhand index pointing down] +% \ShowEmoji[backhand index pointing up] -\definecolor[emoji-base][r=.4] -\definecolor[emoji-gray][s=.5,t=.5,a=1] +\startTEXpage +[\char8205\char128104]=\char988828\par +[\char8205\char128105]=\char988851\par +[\char8205\char983484]=\char988834\par +[\char8205\char983485]=\char988835\par +[\char8205\char983486]=\char988836\par +[\char8205\char983487]=\char988837\par +[\char8205\char983488]=\char988838\par +[\char8205\char983495]=\char988858\par +[\char8205\char983496]=\char988859\par +[\char8205\char983497]=\char988860\par +[\char8205\char983498]=\char988861\par +[\char8205\char983499]=\char988862\par +\stopTEXpage -\definefontcolorpalette - [emoji-gray] - [emoji-base,emoji-gray] -\definefontfeature[seguiemj-cl][ccmp=yes,dist=yes,colr=emoji-gray] -\definedfont[seguiemj*seguiemj-cl] -\ShowEmoji -\page -\ShowEmojiPalettes[1] + + +% \page + +% \definecolor[emoji-base][r=.4] +% \definecolor[emoji-gray][s=.5,t=.5,a=1] + +% \definefontcolorpalette +% [emoji-gray] +% [emoji-base,emoji-gray] + +% \definefontfeature[seguiemj-cl][ccmp=yes,dist=yes,colr=emoji-gray] + +% \definedfont[seguiemj*seguiemj-cl] + +% \ShowEmoji + +% \page + +% \ShowEmojiPalettes[1] \stop diff --git a/tex/context/modules/mkiv/s-fonts-features.lua b/tex/context/modules/mkiv/s-fonts-features.lua index 34268c171..eb64e4c8f 100644 --- a/tex/context/modules/mkiv/s-fonts-features.lua +++ b/tex/context/modules/mkiv/s-fonts-features.lua @@ -200,6 +200,8 @@ function moduledata.fonts.features.showfeatureset(specification) end end +-- The next one looks a bit like the collector in font-oup.lua. + local function collectligatures(tfmdata) local sequences = tfmdata.resources.sequences @@ -207,18 +209,28 @@ local function collectligatures(tfmdata) return end + -- Mostly the same as s-fonts-tables so we should make a helper. + local series = { } local stack = { } local max = 0 + local function add(v) + local n = #stack + if n > max then + max = n + end + series[#series+1] = { v, unpack(stack) } + end + local function make(tree) for k, v in sortedhash(tree) do if k == "ligature" then - local n = #stack - if n > max then - max = n - end - series[#series+1] = { v, unpack(stack) } + add(v) + elseif tonumber(v) then + insert(stack,k) + add(v) + remove(stack) else insert(stack,k) make(v) diff --git a/tex/context/modules/mkiv/s-fonts-tables.lua b/tex/context/modules/mkiv/s-fonts-tables.lua index c9aa7b801..65725594b 100644 --- a/tex/context/modules/mkiv/s-fonts-tables.lua +++ b/tex/context/modules/mkiv/s-fonts-tables.lua @@ -678,18 +678,28 @@ end local function collectligatures(steps) + -- Mostly the same as s-fonts-features so we should make a helper. + local series = { } local stack = { } local max = 0 + local function add(v) + local n = #stack + if n > max then + max = n + end + series[#series+1] = { v, unpack(stack) } + end + local function make(tree) for k, v in sortedhash(tree) do if k == "ligature" then - local n = #stack - if n > max then - max = n - end - series[#series+1] = { v, unpack(stack) } + add(v) + elseif tonumber(v) then + insert(stack,k) + add(v) + remove(stack) else insert(stack,k) make(v) diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index d874bda0f..e764e950c 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-08-10 12:37 +-- merge date : 2021-08-19 19:40 do -- begin closure to overcome local limits and interference @@ -11298,15 +11298,15 @@ local weights={ [900]="black", } local widths={ - [1]="ultracondensed", - [2]="extracondensed", - [3]="condensed", - [4]="semicondensed", - [5]="normal", - [6]="semiexpanded", - [7]="expanded", - [8]="extraexpanded", - [9]="ultraexpanded", + "ultracondensed", + "extracondensed", + "condensed", + "semicondensed", + "normal", + "semiexpanded", + "expanded", + "extraexpanded", + "ultraexpanded", } setmetatableindex(weights,function(t,k) local r=floor((k+50)/100)*100 @@ -11316,30 +11316,28 @@ end) setmetatableindex(widths,function(t,k) return "normal" end) -local panoseweights={ - [ 0]="normal", - [ 1]="normal", - [ 2]="verylight", - [ 3]="light", - [ 4]="thin", - [ 5]="book", - [ 6]="medium", - [ 7]="demi", - [ 8]="bold", - [ 9]="heavy", - [10]="black", +local panoseweights={ [0]="normal", + "normal", + "verylight", + "light", + "thin", + "book", + "medium", + "demi", + "bold", + "heavy", + "black", } -local panosewidths={ - [ 0]="normal", - [ 1]="normal", - [ 2]="normal", - [ 3]="normal", - [ 4]="normal", - [ 5]="expanded", - [ 6]="condensed", - [ 7]="veryexpanded", - [ 8]="verycondensed", - [ 9]="monospaced", +local panosewidths={ [0]="normal", + "normal", + "normal", + "normal", + "normal", + "expanded", + "condensed", + "veryexpanded", + "verycondensed", + "monospaced", } local helpers={} readers.helpers=helpers @@ -12883,6 +12881,9 @@ end function readers.compact(fontdata) report("the %a helper is not yet implemented","compact") end +function readers.condense(fontdata) + report("the %a helper is not yet implemented","condense") +end local extenders={} function readers.registerextender(extender) extenders[#extenders+1]=extender @@ -15333,6 +15334,12 @@ local function applyaxis(glyph,shape,deltas,dowidth) else local n1=dpoints[d1] local n3=dpoints[d3] + if n1>nofpoints then + n1=nofpoints + end + if n3>nofpoints then + n3=nofpoints + end local p1=points[n1] local p3=points[n3] local p1x=p1[1] @@ -20926,7 +20933,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.118 +otf.version=3.119 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) otf.pngcache=containers.define("fonts","png",otf.version,true) @@ -21061,6 +21068,9 @@ function otf.load(filename,sub,instance) if cleanup==0 then checkmemory(used,threshold,tracememory) end + if context then + otfreaders.condense(data) + end otfreaders.pack(data) report_otf("loading done") report_otf("saving %a in cache",filename) @@ -21746,49 +21756,60 @@ end local function makefake(tfmdata,name,present) local private=getprivate(tfmdata) local character={ intermediate=true,ligatures={} } - resources.unicodes[name]=private + tfmdata.resources.unicodes[name]=private tfmdata.characters[private]=character tfmdata.descriptions[private]={ name=name } present[name]=private return character end local function make_1(present,tree,name) - for k,v in next,tree do - if k=="ligature" then - present[name]=v + if tonumber(tree) then + present[name]=v + else + for k,v in next,tree do + if k=="ligature" then + present[name]=v + else + make_1(present,v,name.."_"..k) + end + end + end +end +local function make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v) + local character=characters[preceding] + if not character then + if trace_baseinit then + report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) + end + character=makefake(tfmdata,name,present) + end + local ligatures=character.ligatures + if ligatures then + ligatures[unicode]={ char=v } + else + character.ligatures={ [unicode]={ char=v } } + end + if done then + local d=done[name] + if not d then + done[name]={ "dummy",v } else - make_1(present,v,name.."_"..k) + d[#d+1]=v end end end local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done) - for k,v in next,tree do - if k=="ligature" then - local character=characters[preceding] - if not character then - if trace_baseinit then - report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding) - end - character=makefake(tfmdata,name,present) - end - local ligatures=character.ligatures - if ligatures then - ligatures[unicode]={ char=v } + if tonumber(tree) then + make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,tree) + else + for k,v in next,tree do + if k=="ligature" then + make_3(present,tfmdata,characters,tree,name,preceding,unicode,done,v) else - character.ligatures={ [unicode]={ char=v } } + local code=present[name] or unicode + local name=name.."_"..k + make_2(present,tfmdata,characters,v,name,code,k,done) end - if done then - local d=done[name] - if not d then - done[name]={ "dummy",v } - else - d[#d+1]=v - end - end - else - local code=present[name] or unicode - local name=name.."_"..k - make_2(present,tfmdata,characters,v,name,code,k,done) end end end @@ -24514,6 +24535,10 @@ function readers.getcomponents(fontdata) local function traverse(p,k,v) if k=="ligature" then collected[v]={ unpack(l) } + elseif tonumber(v) then + insert(l,k) + collected[v]={ unpack(l) } + remove(l) else insert(l,k) for k,vv in next,v do @@ -24674,7 +24699,6 @@ local function tabstr_flat(t) end end local function tabstr_mixed(t) - local s={} local n=#t if n==0 then return "" @@ -24688,6 +24712,7 @@ local function tabstr_mixed(t) return tostring(k) end else + local s={} for i=1,n do local k=t[i] if k==true then @@ -26011,6 +26036,85 @@ function readers.compact(data) end end end +if CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 then + local done=0 + local function condense_1(k,v,t) + if type(v)=="table" then + local u=false + local l=false + for k,v in next,v do + if k=="ligature" then + l=v + if u then + break + end + elseif u then + break + else + u=true + end + end + if l and not u then + t[k]=l + done=done+1 + end + if u then + for k,vv in next,v do + if k~="ligature" then + condense_1(k,vv,v) + end + end + end + end + end + local function condensesteps_1(lookup) + done=0 + if lookup.type=="gsub_ligature" then + local steps=lookup.steps + if steps then + for i=1,#steps do + local step=steps[i] + local coverage=step.coverage + if coverage then + for k,v in next,coverage do + if condense_1(k,v,coverage) then + coverage[k]=v.ligature + done=done+1 + end + end + end + end + end + end + return done + end + function readers.condense(data) + if not data or data.condensed then + return + else + data.condensed=true + end + local resources=data.resources + local condensed=0 + local function condense(what) + local lookups=resources[what] + if lookups then + for i=1,#lookups do + condensed=condensed+condensesteps_1(lookups[i]) + end + elseif trace_optimizations then + report_optimizations("no lookups in %a",what) + end + end + condense("sequences") + condense("sublookups") + if trace_optimizations then + if condensed>0 then + report_optimizations("%i ligatures condensed",condensed) + end + end + end +end local function mergesteps(t,k) if k=="merged" then local merged={} @@ -27263,7 +27367,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip while current do local char=ischar(current,currentfont) if char then - local lg=ligature[char] + local lg=not tonumber(ligature) and ligature[char] if lg then stop=current ligature=lg @@ -27276,14 +27380,14 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip end end if stop then - local lig=ligature.ligature - if lig then + local ligature=tonumber(ligature) or ligature.ligature + if ligature then if trace_ligatures then local stopchar=getchar(stop) - head,start=markstoligature(head,start,stop,lig) + head,start=markstoligature(head,start,stop,ligature) logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start))) else - head,start=markstoligature(head,start,stop,lig) + head,start=markstoligature(head,start,stop,ligature) end return head,start,true,false else @@ -27298,7 +27402,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip if skiphash and skiphash[char] then current=getnext(current) else - local lg=ligature[char] + local lg=not tonumber(ligature) and ligature[char] if lg then if marks[char] then hasmarks=true @@ -27324,20 +27428,20 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip local match if replace then local char=ischar(replace,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match=true end end if not match and pre then local char=ischar(pre,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match=true end end if not match and not pre or not replace then local n=getnext(discfound) local char=ischar(n,currentfont) - if char and ligature[char] then + if char and (not tonumber(ligature) and ligature[char]) then match=true end end @@ -27380,21 +27484,21 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip return head,start,true,true end end - local lig=ligature.ligature - if lig then + local ligature=tonumber(ligature) or ligature.ligature + if ligature then if stop then if trace_ligatures then local stopchar=getchar(stop) - head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) + head,start=toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(ligature)) else - head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) + head,start=toligature(head,start,stop,ligature,dataset,sequence,skiphash,false,hasmarks) end else resetinjection(start) - setchar(start,lig) + setchar(start,ligature) if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) + logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(ligature)) end end return head,start,true,false @@ -27868,7 +27972,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup if skiphash and skiphash[schar] then current=getnext(current) else - local lg=ligatures[schar] + local lg=not tonumber(ligatures) and ligatures[schar] if lg then ligatures=lg last=current @@ -27887,7 +27991,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup end end end - local ligature=ligatures.ligature + local ligature=tonumber(ligatures) or ligatures.ligature if ligature then if chainindex then stop=last @@ -28299,7 +28403,7 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) local chainproc=chainprocs[chainkind] if chainproc then local ok - head,start,ok=chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash) + head,start,ok=chainproc(head,start,last,dataset,sequence,chainstep,rlmode,skiphash,1) if ok then done=true end @@ -28716,6 +28820,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s local ck=contexts[k] local seq=ck[3] local f=ck[4] +local last=start if not startchar or not seq[f][startchar] then goto next end @@ -28724,7 +28829,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s else local l=ck[5] local current=start - local last=start if l>f then local discfound local n=f+1 @@ -29508,7 +29612,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) while s do local char=ischar(s,font) if char then - local lg=lookupmatch[char] + local lg=not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d=1 @@ -29538,7 +29642,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) break end end - if l and l.ligature then + if l and (tonumber(l) or l.ligature) then lastd=d end else @@ -29663,7 +29767,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) while s do local char=ischar(s) if char then - local lg=lookupmatch[char] + local lg=not tonumber(lookupmatch) and lookupmatch[char] if lg then if sstop then d=1 @@ -29693,7 +29797,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) break end end - if l and l.ligature then + if l and (tonumber(l) or l.ligature) then lastd=d end end @@ -31665,7 +31769,7 @@ local function initializedevanagi(tfmdata) local h=coverage[k] if h then for k,v in next,h do - found=v and v.ligature + found=v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found]=true break @@ -31682,7 +31786,7 @@ local function initializedevanagi(tfmdata) end else for k,v in next,r do - found=v and v.ligature + found=v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found]=true break @@ -31730,7 +31834,7 @@ local function initializedevanagi(tfmdata) for k,v in next,halant do local h=r[k] if h then - reph=h.ligature or false + reph=tonumber(h) or h.ligature or false break end end @@ -31747,7 +31851,7 @@ local function initializedevanagi(tfmdata) for k,v in next,halant do local h=r[k] if h then - reph=h.ligature or false + reph=tonumber(h) or h.ligature or false break end end @@ -31791,7 +31895,7 @@ local function initializedevanagi(tfmdata) local h=coverage[k] if h then for k,v in next,h do - found=v and v.ligature + found=v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found]=true break @@ -31808,7 +31912,7 @@ local function initializedevanagi(tfmdata) end else for k,v in next,h do - found=v and v.ligature + found=v and (tonumber(v) or v.ligature) if found then pre_base_reordering_consonants[found]=true break |