From 5c6357cdb820b4f628d036ba7b2248f221d50c0b Mon Sep 17 00:00:00 2001 From: Luigi Scarso Date: Fri, 22 Feb 2019 23:11:47 +0000 Subject: ConTeXt version 2019.02.22 19:35 git-svn-id: svn://tug.org/texlive/trunk@50086 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/context/base/mkiv/anch-bck.mkvi | 24 +- .../texmf-dist/tex/context/base/mkiv/anch-pgr.lua | 140 +- .../texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv | 14 +- .../texmf-dist/tex/context/base/mkiv/anch-pos.lua | 166 +- .../texmf-dist/tex/context/base/mkiv/anch-pos.mkiv | 18 +- .../texmf-dist/tex/context/base/mkiv/anch-snc.lua | 271 + .../texmf-dist/tex/context/base/mkiv/anch-snc.mkiv | 272 +- .../texmf-dist/tex/context/base/mkiv/anch-tab.mkiv | 17 +- .../texmf-dist/tex/context/base/mkiv/attr-col.lua | 48 +- .../texmf-dist/tex/context/base/mkiv/attr-ini.lua | 5 +- .../texmf-dist/tex/context/base/mkiv/attr-ini.mkiv | 36 +- .../texmf-dist/tex/context/base/mkiv/back-exp.lua | 936 ++-- .../texmf-dist/tex/context/base/mkiv/back-exp.mkiv | 28 +- .../texmf-dist/tex/context/base/mkiv/back-ini.lua | 221 +- .../texmf-dist/tex/context/base/mkiv/back-ini.mkiv | 116 +- .../texmf-dist/tex/context/base/mkiv/back-pdf.lua | 301 +- .../texmf-dist/tex/context/base/mkiv/back-pdf.mkiv | 188 +- .../texmf-dist/tex/context/base/mkiv/back-pdp.lua | 453 ++ .../texmf-dist/tex/context/base/mkiv/back-res.lua | 44 + .../texmf-dist/tex/context/base/mkiv/back-swf.mkiv | 101 +- .../texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv | 6 +- .../texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv | 2 +- .../tex/context/base/mkiv/buff-imp-default.mkiv | 10 +- .../texmf-dist/tex/context/base/mkiv/buff-ini.lua | 25 +- .../texmf-dist/tex/context/base/mkiv/buff-ini.mkiv | 46 +- .../texmf-dist/tex/context/base/mkiv/buff-ver.lua | 23 +- .../texmf-dist/tex/context/base/mkiv/buff-ver.mkiv | 19 +- .../texmf-dist/tex/context/base/mkiv/catc-ini.mkiv | 161 +- .../texmf-dist/tex/context/base/mkiv/char-act.mkiv | 47 +- .../texmf-dist/tex/context/base/mkiv/char-def.lua | 5239 +++++++++++++++++++- .../texmf-dist/tex/context/base/mkiv/char-emj.lua | 2566 ++++++---- .../texmf-dist/tex/context/base/mkiv/char-ini.lua | 60 +- .../texmf-dist/tex/context/base/mkiv/char-ini.mkiv | 16 +- .../texmf-dist/tex/context/base/mkiv/char-tex.lua | 33 +- .../texmf-dist/tex/context/base/mkiv/char-utf.lua | 13 +- .../texmf-dist/tex/context/base/mkiv/chem-str.lua | 4 - .../texmf-dist/tex/context/base/mkiv/chem-str.mkiv | 12 +- .../texmf-dist/tex/context/base/mkiv/cldf-bas.lua | 155 +- .../texmf-dist/tex/context/base/mkiv/cldf-ini.lua | 658 ++- .../texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv | 8 +- .../texmf-dist/tex/context/base/mkiv/cldf-int.lua | 5 +- .../texmf-dist/tex/context/base/mkiv/cldf-scn.lua | 7 +- .../texmf-dist/tex/context/base/mkiv/cldf-ver.lua | 87 +- .../tex/context/base/mkiv/colo-imp-crayola.mkiv | 10 +- .../tex/context/base/mkiv/colo-imp-svg.mkiv | 164 + .../texmf-dist/tex/context/base/mkiv/colo-ini.lua | 66 +- .../texmf-dist/tex/context/base/mkiv/colo-ini.mkiv | 19 +- .../texmf-dist/tex/context/base/mkiv/colo-run.lua | 2 +- .../texmf-dist/tex/context/base/mkiv/cont-log.mkiv | 40 +- .../texmf-dist/tex/context/base/mkiv/cont-new.mkiv | 18 +- .../texmf-dist/tex/context/base/mkiv/cont-run.lua | 48 +- .../texmf-dist/tex/context/base/mkiv/cont-run.mkiv | 20 +- .../texmf-dist/tex/context/base/mkiv/context.mkiv | 62 +- .../texmf-dist/tex/context/base/mkiv/core-con.lua | 393 +- .../texmf-dist/tex/context/base/mkiv/core-con.mkiv | 212 +- .../texmf-dist/tex/context/base/mkiv/core-dat.lua | 62 +- .../texmf-dist/tex/context/base/mkiv/core-dat.mkiv | 33 +- .../texmf-dist/tex/context/base/mkiv/core-def.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/core-env.lua | 67 +- .../texmf-dist/tex/context/base/mkiv/core-env.mkiv | 46 +- .../texmf-dist/tex/context/base/mkiv/core-lmt.lua | 34 + .../texmf-dist/tex/context/base/mkiv/core-lmt.mkiv | 32 + .../texmf-dist/tex/context/base/mkiv/core-sys.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/core-two.lua | 93 +- .../texmf-dist/tex/context/base/mkiv/core-two.mkiv | 8 +- .../texmf-dist/tex/context/base/mkiv/core-uti.lua | 23 +- .../texmf-dist/tex/context/base/mkiv/data-aux.lua | 2 +- .../texmf-dist/tex/context/base/mkiv/data-pre.lua | 26 +- .../texmf-dist/tex/context/base/mkiv/data-res.lua | 6 +- .../texmf-dist/tex/context/base/mkiv/data-tex.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/data-tre.lua | 5 +- .../texmf-dist/tex/context/base/mkiv/data-use.lua | 6 +- .../texmf-dist/tex/context/base/mkiv/data-zip.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/driv-ini.lua | 194 + .../texmf-dist/tex/context/base/mkiv/driv-ini.mkiv | 25 + .../tex/context/base/mkiv/export-example.css | 37 +- .../texmf-dist/tex/context/base/mkiv/file-job.lua | 3 - .../texmf-dist/tex/context/base/mkiv/file-job.mkvi | 19 +- .../texmf-dist/tex/context/base/mkiv/file-mod.mkvi | 32 +- .../texmf-dist/tex/context/base/mkiv/font-aux.lua | 1 + .../texmf-dist/tex/context/base/mkiv/font-cff.lua | 554 ++- .../texmf-dist/tex/context/base/mkiv/font-cft.lua | 10 + .../texmf-dist/tex/context/base/mkiv/font-chk.lua | 94 +- .../texmf-dist/tex/context/base/mkiv/font-col.lua | 191 +- .../texmf-dist/tex/context/base/mkiv/font-col.mkvi | 5 + .../texmf-dist/tex/context/base/mkiv/font-con.lua | 179 +- .../texmf-dist/tex/context/base/mkiv/font-ctx.lua | 585 ++- .../texmf-dist/tex/context/base/mkiv/font-def.lua | 120 +- .../texmf-dist/tex/context/base/mkiv/font-dsp.lua | 736 +-- .../texmf-dist/tex/context/base/mkiv/font-emp.mkvi | 22 +- .../texmf-dist/tex/context/base/mkiv/font-enh.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/font-ext.lua | 1856 ------- .../texmf-dist/tex/context/base/mkiv/font-fbk.lua | 272 +- .../texmf-dist/tex/context/base/mkiv/font-fea.mkvi | 10 +- .../texmf-dist/tex/context/base/mkiv/font-fil.mkvi | 33 +- .../texmf-dist/tex/context/base/mkiv/font-gbn.lua | 262 - .../texmf-dist/tex/context/base/mkiv/font-gds.mkvi | 2 +- .../texmf-dist/tex/context/base/mkiv/font-hsh.lua | 101 +- .../tex/context/base/mkiv/font-imp-dimensions.lua | 115 + .../tex/context/base/mkiv/font-imp-effects.lua | 414 ++ .../tex/context/base/mkiv/font-imp-italics.lua | 147 + .../tex/context/base/mkiv/font-imp-ligatures.lua | 136 + .../tex/context/base/mkiv/font-imp-math.lua | 81 + .../tex/context/base/mkiv/font-imp-notused.lua | 168 + .../tex/context/base/mkiv/font-imp-properties.lua | 130 + .../tex/context/base/mkiv/font-imp-quality.lua | 527 ++ .../tex/context/base/mkiv/font-imp-reorder.lua | 174 + .../tex/context/base/mkiv/font-imp-tex.lua | 144 + .../tex/context/base/mkiv/font-imp-tracing.lua | 281 ++ .../tex/context/base/mkiv/font-imp-unicode.lua | 82 + .../texmf-dist/tex/context/base/mkiv/font-ini.lua | 47 +- .../texmf-dist/tex/context/base/mkiv/font-ini.mkvi | 99 +- .../texmf-dist/tex/context/base/mkiv/font-lib.mkvi | 43 +- .../texmf-dist/tex/context/base/mkiv/font-map.lua | 160 +- .../texmf-dist/tex/context/base/mkiv/font-mat.mkvi | 30 +- .../texmf-dist/tex/context/base/mkiv/font-mis.lua | 14 +- .../texmf-dist/tex/context/base/mkiv/font-mps.lua | 131 +- .../texmf-dist/tex/context/base/mkiv/font-nod.lua | 187 +- .../texmf-dist/tex/context/base/mkiv/font-ocl.lua | 349 +- .../texmf-dist/tex/context/base/mkiv/font-one.lua | 15 +- .../texmf-dist/tex/context/base/mkiv/font-onr.lua | 79 +- .../texmf-dist/tex/context/base/mkiv/font-osd.lua | 121 +- .../texmf-dist/tex/context/base/mkiv/font-ota.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/font-otc.lua | 322 +- .../texmf-dist/tex/context/base/mkiv/font-otj.lua | 110 +- .../texmf-dist/tex/context/base/mkiv/font-otl.lua | 41 +- .../texmf-dist/tex/context/base/mkiv/font-oto.lua | 69 +- .../texmf-dist/tex/context/base/mkiv/font-otr.lua | 275 +- .../texmf-dist/tex/context/base/mkiv/font-ots.lua | 500 +- .../texmf-dist/tex/context/base/mkiv/font-ott.lua | 50 +- .../texmf-dist/tex/context/base/mkiv/font-oup.lua | 644 ++- .../texmf-dist/tex/context/base/mkiv/font-pre.mkiv | 49 +- .../texmf-dist/tex/context/base/mkiv/font-prv.lua | 78 + .../texmf-dist/tex/context/base/mkiv/font-sel.lua | 149 +- .../texmf-dist/tex/context/base/mkiv/font-set.mkvi | 6 +- .../texmf-dist/tex/context/base/mkiv/font-shp.lua | 128 +- .../texmf-dist/tex/context/base/mkiv/font-sol.lua | 128 +- .../texmf-dist/tex/context/base/mkiv/font-sty.mkvi | 25 +- .../texmf-dist/tex/context/base/mkiv/font-sym.mkvi | 2 +- .../texmf-dist/tex/context/base/mkiv/font-syn.lua | 5 +- .../texmf-dist/tex/context/base/mkiv/font-tfm.lua | 448 +- .../texmf-dist/tex/context/base/mkiv/font-tra.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/font-ttf.lua | 465 +- .../texmf-dist/tex/context/base/mkiv/font-var.mkvi | 2 + .../texmf-dist/tex/context/base/mkiv/font-vfc.lua | 123 + .../texmf-dist/tex/context/base/mkiv/font-vir.lua | 23 +- .../texmf-dist/tex/context/base/mkiv/font-web.lua | 20 +- .../texmf-dist/tex/context/base/mkiv/font-xtx.lua | 97 - .../texmf-dist/tex/context/base/mkiv/good-ctx.lua | 84 +- .../texmf-dist/tex/context/base/mkiv/grph-epd.lua | 20 +- .../texmf-dist/tex/context/base/mkiv/grph-inc.lua | 286 +- .../texmf-dist/tex/context/base/mkiv/grph-inc.mkiv | 101 +- .../texmf-dist/tex/context/base/mkiv/grph-mem.lua | 164 +- .../texmf-dist/tex/context/base/mkiv/grph-pat.lua | 4 +- .../texmf-dist/tex/context/base/mkiv/grph-rul.lua | 149 +- .../texmf-dist/tex/context/base/mkiv/grph-swf.lua | 3 +- .../texmf-dist/tex/context/base/mkiv/grph-trf.mkiv | 39 +- .../tex/context/base/mkiv/java-imp-exa.mkiv | 395 -- .../tex/context/base/mkiv/java-imp-example.mkiv | 398 ++ .../tex/context/base/mkiv/java-imp-fields.mkiv | 648 +++ .../tex/context/base/mkiv/java-imp-fil.mkiv | 52 - .../tex/context/base/mkiv/java-imp-fld.mkiv | 625 --- .../tex/context/base/mkiv/java-imp-highlight.mkiv | 34 + .../tex/context/base/mkiv/java-imp-print.mkiv | 52 + .../tex/context/base/mkiv/java-imp-rhh.mkiv | 34 - .../tex/context/base/mkiv/java-imp-steps.mkiv | 123 + .../tex/context/base/mkiv/java-imp-stp.mkiv | 123 - .../context/base/mkiv/java-imp-videoplayer.mkiv | 82 + .../tex/context/base/mkiv/java-imp-vplayer.mkiv | 105 + .../texmf-dist/tex/context/base/mkiv/java-ini.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/java-ini.mkiv | 17 +- .../texmf-dist/tex/context/base/mkiv/l-bit32.lua | 10 +- Master/texmf-dist/tex/context/base/mkiv/l-dir.lua | 82 +- Master/texmf-dist/tex/context/base/mkiv/l-file.lua | 38 +- Master/texmf-dist/tex/context/base/mkiv/l-lpeg.lua | 195 +- Master/texmf-dist/tex/context/base/mkiv/l-lua.lua | 40 +- .../tex/context/base/mkiv/l-macro-imp-optimize.lua | 29 +- .../texmf-dist/tex/context/base/mkiv/l-macro.lua | 95 +- .../texmf-dist/tex/context/base/mkiv/l-number.lua | 23 +- Master/texmf-dist/tex/context/base/mkiv/l-os.lua | 132 +- .../texmf-dist/tex/context/base/mkiv/l-package.lua | 4 + .../texmf-dist/tex/context/base/mkiv/l-sandbox.lua | 3 + Master/texmf-dist/tex/context/base/mkiv/l-sha.lua | 27 + .../texmf-dist/tex/context/base/mkiv/l-table.lua | 132 +- .../texmf-dist/tex/context/base/mkiv/l-unicode.lua | 228 +- .../texmf-dist/tex/context/base/mkiv/lang-def.lua | 9 + .../texmf-dist/tex/context/base/mkiv/lang-def.mkiv | 44 +- .../texmf-dist/tex/context/base/mkiv/lang-dis.lua | 107 +- .../texmf-dist/tex/context/base/mkiv/lang-exp.lua | 36 +- .../texmf-dist/tex/context/base/mkiv/lang-hyp.lua | 68 +- .../texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv | 9 +- .../texmf-dist/tex/context/base/mkiv/lang-ini.mkiv | 270 +- .../texmf-dist/tex/context/base/mkiv/lang-lab.mkiv | 12 +- .../texmf-dist/tex/context/base/mkiv/lang-mis.mkiv | 156 +- .../texmf-dist/tex/context/base/mkiv/lang-rep.lua | 7 +- .../texmf-dist/tex/context/base/mkiv/lang-spa.mkiv | 18 +- .../texmf-dist/tex/context/base/mkiv/lang-txt.lua | 102 +- .../texmf-dist/tex/context/base/mkiv/lang-url.lua | 22 +- .../texmf-dist/tex/context/base/mkiv/lang-wrd.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/lpdf-ano.lua | 276 +- .../texmf-dist/tex/context/base/mkiv/lpdf-aux.lua | 152 + .../texmf-dist/tex/context/base/mkiv/lpdf-col.lua | 47 +- .../texmf-dist/tex/context/base/mkiv/lpdf-epa.lua | 783 ++- .../texmf-dist/tex/context/base/mkiv/lpdf-epd.lua | 518 +- .../texmf-dist/tex/context/base/mkiv/lpdf-fld.lua | 180 +- .../texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua | 21 +- .../texmf-dist/tex/context/base/mkiv/lpdf-fnt.lua | 202 + .../texmf-dist/tex/context/base/mkiv/lpdf-grp.lua | 72 +- .../texmf-dist/tex/context/base/mkiv/lpdf-ini.lua | 1297 +++-- .../texmf-dist/tex/context/base/mkiv/lpdf-mis.lua | 126 +- .../texmf-dist/tex/context/base/mkiv/lpdf-nod.lua | 214 +- .../texmf-dist/tex/context/base/mkiv/lpdf-pda.xml | 85 +- .../texmf-dist/tex/context/base/mkiv/lpdf-pde.lua | 1157 +++++ .../texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml | 1 + .../texmf-dist/tex/context/base/mkiv/lpdf-pua.xml | 41 +- .../texmf-dist/tex/context/base/mkiv/lpdf-ren.lua | 12 +- .../texmf-dist/tex/context/base/mkiv/lpdf-res.lua | 26 +- .../texmf-dist/tex/context/base/mkiv/lpdf-swf.lua | 46 +- .../texmf-dist/tex/context/base/mkiv/lpdf-tag.lua | 244 +- .../texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua | 26 +- .../texmf-dist/tex/context/base/mkiv/lpdf-wid.lua | 40 +- .../texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua | 75 +- .../texmf-dist/tex/context/base/mkiv/luat-bas.mkiv | 2 + .../texmf-dist/tex/context/base/mkiv/luat-cbk.lua | 6 + .../texmf-dist/tex/context/base/mkiv/luat-cnf.lua | 4 +- .../texmf-dist/tex/context/base/mkiv/luat-cod.lua | 64 +- .../texmf-dist/tex/context/base/mkiv/luat-env.lua | 24 +- .../texmf-dist/tex/context/base/mkiv/luat-fio.lua | 4 + .../texmf-dist/tex/context/base/mkiv/luat-fmt.lua | 14 +- .../texmf-dist/tex/context/base/mkiv/luat-ini.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/luat-ini.mkiv | 127 +- .../texmf-dist/tex/context/base/mkiv/luat-lib.mkiv | 16 +- .../texmf-dist/tex/context/base/mkiv/luat-run.lua | 111 +- .../texmf-dist/tex/context/base/mkiv/luat-soc.lua | 11 - .../texmf-dist/tex/context/base/mkiv/luat-soc.mkiv | 52 + .../texmf-dist/tex/context/base/mkiv/luat-sto.lua | 2 +- .../texmf-dist/tex/context/base/mkiv/luat-usr.lua | 3 - .../texmf-dist/tex/context/base/mkiv/luat-usr.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/lxml-aux.lua | 25 +- .../texmf-dist/tex/context/base/mkiv/lxml-css.lua | 137 +- .../texmf-dist/tex/context/base/mkiv/lxml-inf.lua | 3 +- .../texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv | 21 +- .../texmf-dist/tex/context/base/mkiv/lxml-lpt.lua | 276 +- .../texmf-dist/tex/context/base/mkiv/lxml-tex.lua | 426 +- .../tex/context/base/mkiv/m-fonts-plugins.mkiv | 5 +- .../texmf-dist/tex/context/base/mkiv/math-act.lua | 44 +- .../texmf-dist/tex/context/base/mkiv/math-ali.mkiv | 29 +- .../texmf-dist/tex/context/base/mkiv/math-arr.mkiv | 57 +- .../texmf-dist/tex/context/base/mkiv/math-dim.lua | 3 +- .../texmf-dist/tex/context/base/mkiv/math-dir.lua | 30 +- .../texmf-dist/tex/context/base/mkiv/math-ext.lua | 27 +- .../texmf-dist/tex/context/base/mkiv/math-fbk.lua | 201 +- .../texmf-dist/tex/context/base/mkiv/math-fen.mkiv | 120 +- .../texmf-dist/tex/context/base/mkiv/math-frc.lua | 4 +- .../texmf-dist/tex/context/base/mkiv/math-frc.mkiv | 42 +- .../texmf-dist/tex/context/base/mkiv/math-inc.lua | 87 + .../texmf-dist/tex/context/base/mkiv/math-inc.mkiv | 69 + .../texmf-dist/tex/context/base/mkiv/math-ini.lua | 9 +- .../texmf-dist/tex/context/base/mkiv/math-ini.mkiv | 146 +- .../texmf-dist/tex/context/base/mkiv/math-noa.lua | 742 +-- .../texmf-dist/tex/context/base/mkiv/math-pln.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/math-spa.lua | 37 +- .../texmf-dist/tex/context/base/mkiv/math-stc.mkvi | 14 +- .../texmf-dist/tex/context/base/mkiv/math-tag.lua | 437 +- .../texmf-dist/tex/context/base/mkiv/math-vfu.lua | 344 +- .../texmf-dist/tex/context/base/mkiv/meta-blb.lua | 322 ++ .../texmf-dist/tex/context/base/mkiv/meta-blb.mkiv | 56 + .../texmf-dist/tex/context/base/mkiv/meta-fnt.lua | 24 +- .../tex/context/base/mkiv/meta-imp-dum.mkiv | 4 +- .../tex/context/base/mkiv/meta-imp-mat.mkiv | 38 +- .../tex/context/base/mkiv/meta-imp-txt.mkiv | 76 +- .../texmf-dist/tex/context/base/mkiv/meta-ini.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/meta-ini.mkiv | 57 +- .../texmf-dist/tex/context/base/mkiv/meta-nod.lua | 81 + .../texmf-dist/tex/context/base/mkiv/meta-nod.mkiv | 31 +- .../texmf-dist/tex/context/base/mkiv/meta-pdf.lua | 76 +- .../texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv | 24 +- .../texmf-dist/tex/context/base/mkiv/meta-tex.lua | 6 +- .../texmf-dist/tex/context/base/mkiv/metatex.tex | 30 - .../texmf-dist/tex/context/base/mkiv/mlib-ctx.lua | 87 +- .../texmf-dist/tex/context/base/mkiv/mlib-int.lua | 191 +- .../texmf-dist/tex/context/base/mkiv/mlib-lua.lua | 1175 +++-- .../texmf-dist/tex/context/base/mkiv/mlib-pdf.lua | 598 ++- .../texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv | 30 +- .../texmf-dist/tex/context/base/mkiv/mlib-pps.lua | 1151 ++--- .../texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv | 35 +- .../texmf-dist/tex/context/base/mkiv/mlib-run.lua | 279 +- .../tex/context/base/mkiv/mtx-context-domotica.tex | 31 +- .../tex/context/base/mkiv/mtx-context-fonts.tex | 98 + .../tex/context/base/mkiv/mtx-context-listing.tex | 4 +- .../tex/context/base/mkiv/mtx-context-xml.tex | 5 + .../texmf-dist/tex/context/base/mkiv/mult-aux.mkiv | 562 ++- .../texmf-dist/tex/context/base/mkiv/mult-def.lua | 33 +- .../texmf-dist/tex/context/base/mkiv/mult-fun.lua | 34 +- .../texmf-dist/tex/context/base/mkiv/mult-ini.lua | 16 + .../texmf-dist/tex/context/base/mkiv/mult-ini.mkiv | 15 +- .../texmf-dist/tex/context/base/mkiv/mult-low.lua | 58 +- .../texmf-dist/tex/context/base/mkiv/mult-prm.lua | 32 +- .../texmf-dist/tex/context/base/mkiv/mult-prm.mkiv | 3 +- .../texmf-dist/tex/context/base/mkiv/mult-sys.mkiv | 2 + .../texmf-dist/tex/context/base/mkiv/node-acc.lua | 72 +- .../texmf-dist/tex/context/base/mkiv/node-aux.lua | 198 +- .../texmf-dist/tex/context/base/mkiv/node-bck.lua | 378 +- .../texmf-dist/tex/context/base/mkiv/node-bck.mkiv | 21 +- .../texmf-dist/tex/context/base/mkiv/node-dir.lua | 359 +- .../texmf-dist/tex/context/base/mkiv/node-fin.lua | 472 +- .../texmf-dist/tex/context/base/mkiv/node-fin.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/node-fnt.lua | 545 +- .../texmf-dist/tex/context/base/mkiv/node-ini.lua | 146 +- .../texmf-dist/tex/context/base/mkiv/node-ini.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/node-ltp.lua | 3261 ++++++------ .../texmf-dist/tex/context/base/mkiv/node-met.lua | 172 +- .../texmf-dist/tex/context/base/mkiv/node-mig.lua | 6 +- .../texmf-dist/tex/context/base/mkiv/node-nut.lua | 327 +- .../texmf-dist/tex/context/base/mkiv/node-par.lua | 48 + .../texmf-dist/tex/context/base/mkiv/node-ppt.lua | 173 +- .../texmf-dist/tex/context/base/mkiv/node-pro.lua | 137 +- .../texmf-dist/tex/context/base/mkiv/node-ref.lua | 291 +- .../texmf-dist/tex/context/base/mkiv/node-res.lua | 329 +- .../texmf-dist/tex/context/base/mkiv/node-rul.lua | 374 +- .../texmf-dist/tex/context/base/mkiv/node-rul.mkiv | 39 +- .../texmf-dist/tex/context/base/mkiv/node-scn.lua | 31 +- .../texmf-dist/tex/context/base/mkiv/node-ser.lua | 8 +- .../texmf-dist/tex/context/base/mkiv/node-shp.lua | 86 +- .../texmf-dist/tex/context/base/mkiv/node-syn.lua | 109 +- .../texmf-dist/tex/context/base/mkiv/node-tex.lua | 45 +- .../texmf-dist/tex/context/base/mkiv/node-tra.lua | 256 +- .../texmf-dist/tex/context/base/mkiv/node-tsk.lua | 609 ++- .../texmf-dist/tex/context/base/mkiv/node-tst.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/pack-bar.mkiv | 6 +- .../texmf-dist/tex/context/base/mkiv/pack-bck.mkvi | 48 +- .../texmf-dist/tex/context/base/mkiv/pack-box.mkiv | 1 + .../texmf-dist/tex/context/base/mkiv/pack-com.mkiv | 18 +- .../texmf-dist/tex/context/base/mkiv/pack-cut.mkiv | 78 +- .../texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv | 86 +- .../texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv | 83 +- .../texmf-dist/tex/context/base/mkiv/pack-obj.lua | 43 +- .../texmf-dist/tex/context/base/mkiv/pack-obj.mkiv | 14 +- .../texmf-dist/tex/context/base/mkiv/pack-rul.lua | 159 +- .../texmf-dist/tex/context/base/mkiv/pack-rul.mkiv | 190 +- .../texmf-dist/tex/context/base/mkiv/page-bck.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/page-box.mkvi | 23 +- .../texmf-dist/tex/context/base/mkiv/page-cst.lua | 161 +- .../texmf-dist/tex/context/base/mkiv/page-cst.mkiv | 5 +- .../texmf-dist/tex/context/base/mkiv/page-ffl.mkiv | 39 +- .../texmf-dist/tex/context/base/mkiv/page-flt.mkiv | 10 +- .../texmf-dist/tex/context/base/mkiv/page-imp.mkiv | 92 +- .../texmf-dist/tex/context/base/mkiv/page-inf.mkiv | 8 +- .../texmf-dist/tex/context/base/mkiv/page-ini.lua | 43 +- .../texmf-dist/tex/context/base/mkiv/page-ini.mkiv | 7 +- .../texmf-dist/tex/context/base/mkiv/page-inj.mkvi | 2 +- .../texmf-dist/tex/context/base/mkiv/page-lay.mkiv | 157 +- .../texmf-dist/tex/context/base/mkiv/page-lin.lua | 44 +- .../texmf-dist/tex/context/base/mkiv/page-lin.mkvi | 10 +- .../texmf-dist/tex/context/base/mkiv/page-mix.lua | 19 - .../texmf-dist/tex/context/base/mkiv/page-mix.mkiv | 27 +- .../texmf-dist/tex/context/base/mkiv/page-mul.mkiv | 36 +- .../texmf-dist/tex/context/base/mkiv/page-one.mkiv | 63 +- .../texmf-dist/tex/context/base/mkiv/page-otr.mkvi | 14 +- .../texmf-dist/tex/context/base/mkiv/page-pcl.mkiv | 79 +- .../texmf-dist/tex/context/base/mkiv/page-run.mkiv | 7 +- .../texmf-dist/tex/context/base/mkiv/page-sel.mkvi | 4 +- .../texmf-dist/tex/context/base/mkiv/page-set.mkiv | 67 +- .../texmf-dist/tex/context/base/mkiv/page-sid.mkiv | 153 +- .../texmf-dist/tex/context/base/mkiv/page-smp.mkiv | 59 + .../texmf-dist/tex/context/base/mkiv/page-spr.mkiv | 35 +- .../texmf-dist/tex/context/base/mkiv/page-str.lua | 73 +- .../texmf-dist/tex/context/base/mkiv/page-str.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/page-txt.mkvi | 33 +- .../texmf-dist/tex/context/base/mkiv/publ-aut.lua | 48 +- .../texmf-dist/tex/context/base/mkiv/publ-dat.lua | 123 +- .../tex/context/base/mkiv/publ-imp-apa.mkvi | 87 +- .../tex/context/base/mkiv/publ-imp-cite.mkvi | 3 - .../texmf-dist/tex/context/base/mkiv/publ-inc.lua | 26 + .../texmf-dist/tex/context/base/mkiv/publ-inc.mkiv | 63 + .../texmf-dist/tex/context/base/mkiv/publ-ini.lua | 43 +- .../texmf-dist/tex/context/base/mkiv/publ-ini.mkiv | 75 +- .../texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi | 2 +- .../texmf-dist/tex/context/base/mkiv/scrn-but.mkvi | 19 +- .../texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi | 106 +- .../texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi | 2 +- .../texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi | 20 +- .../texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi | 18 +- .../texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi | 97 +- .../texmf-dist/tex/context/base/mkiv/scrp-cjk.lua | 107 +- .../texmf-dist/tex/context/base/mkiv/scrp-eth.lua | 86 +- .../texmf-dist/tex/context/base/mkiv/scrp-ini.lua | 247 +- .../texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv | 23 +- .../texmf-dist/tex/context/base/mkiv/scrp-tib.lua | 81 + .../texmf-dist/tex/context/base/mkiv/sort-ini.lua | 29 +- .../texmf-dist/tex/context/base/mkiv/sort-lan.lua | 46 +- .../texmf-dist/tex/context/base/mkiv/spac-adj.lua | 67 - .../texmf-dist/tex/context/base/mkiv/spac-adj.mkiv | 51 - .../texmf-dist/tex/context/base/mkiv/spac-ali.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/spac-ali.mkiv | 134 +- .../texmf-dist/tex/context/base/mkiv/spac-chr.lua | 100 +- .../texmf-dist/tex/context/base/mkiv/spac-chr.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/spac-flr.mkiv | 34 +- .../texmf-dist/tex/context/base/mkiv/spac-grd.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/spac-hor.mkiv | 56 +- .../texmf-dist/tex/context/base/mkiv/spac-lin.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/spac-pag.mkiv | 5 +- .../texmf-dist/tex/context/base/mkiv/spac-par.mkiv | 14 +- .../texmf-dist/tex/context/base/mkiv/spac-prf.lua | 27 +- .../texmf-dist/tex/context/base/mkiv/spac-ver.lua | 421 +- .../texmf-dist/tex/context/base/mkiv/spac-ver.mkiv | 186 +- .../tex/context/base/mkiv/status-files.pdf | Bin 26054 -> 26589 bytes .../tex/context/base/mkiv/status-lua.pdf | Bin 255106 -> 268348 bytes .../texmf-dist/tex/context/base/mkiv/strc-blk.lua | 92 +- .../texmf-dist/tex/context/base/mkiv/strc-blk.mkiv | 128 +- .../texmf-dist/tex/context/base/mkiv/strc-con.mkvi | 18 +- .../texmf-dist/tex/context/base/mkiv/strc-def.mkiv | 11 + .../texmf-dist/tex/context/base/mkiv/strc-doc.lua | 138 +- .../texmf-dist/tex/context/base/mkiv/strc-doc.mkiv | 27 +- .../texmf-dist/tex/context/base/mkiv/strc-flt.lua | 34 + .../texmf-dist/tex/context/base/mkiv/strc-flt.mkvi | 312 +- .../texmf-dist/tex/context/base/mkiv/strc-itm.mkvi | 4 +- .../texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi | 6 +- .../texmf-dist/tex/context/base/mkiv/strc-lst.lua | 37 +- .../texmf-dist/tex/context/base/mkiv/strc-lst.mkvi | 17 +- .../texmf-dist/tex/context/base/mkiv/strc-mar.lua | 180 +- .../texmf-dist/tex/context/base/mkiv/strc-mat.mkiv | 16 +- .../texmf-dist/tex/context/base/mkiv/strc-not.lua | 39 +- .../texmf-dist/tex/context/base/mkiv/strc-not.mkvi | 55 +- .../texmf-dist/tex/context/base/mkiv/strc-num.lua | 27 +- .../texmf-dist/tex/context/base/mkiv/strc-num.mkiv | 16 +- .../texmf-dist/tex/context/base/mkiv/strc-pag.lua | 16 +- .../texmf-dist/tex/context/base/mkiv/strc-pag.mkiv | 29 +- .../texmf-dist/tex/context/base/mkiv/strc-ref.lua | 102 +- .../texmf-dist/tex/context/base/mkiv/strc-ref.mkvi | 502 +- .../texmf-dist/tex/context/base/mkiv/strc-reg.lua | 407 +- .../texmf-dist/tex/context/base/mkiv/strc-reg.mkiv | 232 +- .../texmf-dist/tex/context/base/mkiv/strc-ren.mkiv | 46 +- .../texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/strc-sec.mkiv | 107 +- .../texmf-dist/tex/context/base/mkiv/strc-syn.mkiv | 4 +- .../texmf-dist/tex/context/base/mkiv/strc-tag.lua | 106 +- .../texmf-dist/tex/context/base/mkiv/strc-tag.mkiv | 108 +- .../texmf-dist/tex/context/base/mkiv/strc-usr.lua | 29 + .../texmf-dist/tex/context/base/mkiv/strc-usr.mkiv | 180 + .../texmf-dist/tex/context/base/mkiv/supp-box.lua | 236 +- .../texmf-dist/tex/context/base/mkiv/supp-box.mkiv | 182 +- .../texmf-dist/tex/context/base/mkiv/supp-dir.mkiv | 56 +- .../texmf-dist/tex/context/base/mkiv/supp-mat.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/symb-emj.lua | 27 +- .../context/base/mkiv/symb-imp-fontawesome.mkiv | 1505 +++--- .../tex/context/base/mkiv/symb-imp-mis.mkiv | 23 +- .../tex/context/base/mkiv/symb-imp-mvs.mkiv | 18 +- .../texmf-dist/tex/context/base/mkiv/symb-ini.mkiv | 76 +- .../texmf-dist/tex/context/base/mkiv/symb-run.mkiv | 62 +- .../texmf-dist/tex/context/base/mkiv/syst-aux.lua | 133 +- .../texmf-dist/tex/context/base/mkiv/syst-aux.mkiv | 1521 ++++-- .../texmf-dist/tex/context/base/mkiv/syst-cmp.lua | 8 + .../texmf-dist/tex/context/base/mkiv/syst-cmp.mkiv | 22 + .../texmf-dist/tex/context/base/mkiv/syst-ini.mkiv | 643 ++- .../texmf-dist/tex/context/base/mkiv/syst-lua.lua | 11 +- .../texmf-dist/tex/context/base/mkiv/syst-lua.mkiv | 36 + .../texmf-dist/tex/context/base/mkiv/syst-rtp.mkiv | 18 + .../texmf-dist/tex/context/base/mkiv/tabl-com.mkiv | 64 +- .../texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv | 8 +- .../texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv | 100 +- .../texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv | 38 +- .../texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv | 463 +- .../texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv | 29 + .../texmf-dist/tex/context/base/mkiv/tabl-xtb.lua | 13 +- .../texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi | 149 +- .../texmf-dist/tex/context/base/mkiv/task-ini.lua | 345 +- .../texmf-dist/tex/context/base/mkiv/toks-aux.mkiv | 51 + .../texmf-dist/tex/context/base/mkiv/toks-ini.lua | 115 +- .../texmf-dist/tex/context/base/mkiv/toks-ini.mkiv | 5 - .../texmf-dist/tex/context/base/mkiv/toks-scn.lua | 70 +- .../texmf-dist/tex/context/base/mkiv/toks-scn.mkiv | 22 + .../texmf-dist/tex/context/base/mkiv/trac-deb.lua | 41 +- .../texmf-dist/tex/context/base/mkiv/trac-inf.lua | 42 +- .../texmf-dist/tex/context/base/mkiv/trac-jus.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/trac-log.lua | 63 +- .../texmf-dist/tex/context/base/mkiv/trac-par.lua | 29 +- .../texmf-dist/tex/context/base/mkiv/trac-set.lua | 17 + .../texmf-dist/tex/context/base/mkiv/trac-vis.lua | 366 +- .../texmf-dist/tex/context/base/mkiv/trac-vis.mkiv | 7 +- .../texmf-dist/tex/context/base/mkiv/type-ini.mkvi | 90 +- .../texmf-dist/tex/context/base/mkiv/type-set.mkiv | 2 + .../texmf-dist/tex/context/base/mkiv/typo-bld.lua | 61 +- .../texmf-dist/tex/context/base/mkiv/typo-brk.lua | 30 +- .../texmf-dist/tex/context/base/mkiv/typo-cap.lua | 173 +- .../texmf-dist/tex/context/base/mkiv/typo-cap.mkiv | 62 +- .../texmf-dist/tex/context/base/mkiv/typo-chr.lua | 205 +- .../texmf-dist/tex/context/base/mkiv/typo-chr.mkiv | 19 + .../texmf-dist/tex/context/base/mkiv/typo-cln.lua | 12 +- .../texmf-dist/tex/context/base/mkiv/typo-del.mkiv | 118 +- .../texmf-dist/tex/context/base/mkiv/typo-dha.lua | 58 +- .../texmf-dist/tex/context/base/mkiv/typo-dig.lua | 20 +- .../texmf-dist/tex/context/base/mkiv/typo-dir.lua | 17 +- .../texmf-dist/tex/context/base/mkiv/typo-dir.mkiv | 190 +- .../texmf-dist/tex/context/base/mkiv/typo-drp.lua | 45 +- .../texmf-dist/tex/context/base/mkiv/typo-drp.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/typo-dua.lua | 144 +- .../texmf-dist/tex/context/base/mkiv/typo-dub.lua | 271 +- .../texmf-dist/tex/context/base/mkiv/typo-duc.lua | 278 +- .../texmf-dist/tex/context/base/mkiv/typo-fkr.lua | 17 +- .../texmf-dist/tex/context/base/mkiv/typo-fln.lua | 64 +- .../texmf-dist/tex/context/base/mkiv/typo-fln.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/typo-itc.lua | 69 +- .../texmf-dist/tex/context/base/mkiv/typo-krn.lua | 314 +- .../texmf-dist/tex/context/base/mkiv/typo-lin.lua | 93 +- .../texmf-dist/tex/context/base/mkiv/typo-mar.lua | 83 +- .../texmf-dist/tex/context/base/mkiv/typo-mar.mkiv | 12 + .../texmf-dist/tex/context/base/mkiv/typo-pag.lua | 5 +- .../texmf-dist/tex/context/base/mkiv/typo-par.mkiv | 2 +- .../texmf-dist/tex/context/base/mkiv/typo-pnc.lua | 21 +- .../texmf-dist/tex/context/base/mkiv/typo-rep.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/typo-rub.lua | 42 +- .../texmf-dist/tex/context/base/mkiv/typo-rub.mkiv | 9 + .../texmf-dist/tex/context/base/mkiv/typo-scr.mkiv | 6 +- .../texmf-dist/tex/context/base/mkiv/typo-spa.lua | 12 +- .../texmf-dist/tex/context/base/mkiv/typo-sus.lua | 9 +- .../texmf-dist/tex/context/base/mkiv/typo-tal.lua | 37 +- .../texmf-dist/tex/context/base/mkiv/typo-wrp.lua | 85 +- .../texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv | 9 +- .../texmf-dist/tex/context/base/mkiv/util-deb.lua | 83 +- .../texmf-dist/tex/context/base/mkiv/util-env.lua | 45 +- .../texmf-dist/tex/context/base/mkiv/util-evo.lua | 109 +- .../texmf-dist/tex/context/base/mkiv/util-fil.lua | 66 +- .../texmf-dist/tex/context/base/mkiv/util-fmt.lua | 11 +- .../texmf-dist/tex/context/base/mkiv/util-jsn.lua | 95 +- .../texmf-dist/tex/context/base/mkiv/util-lib.lua | 62 +- .../texmf-dist/tex/context/base/mkiv/util-lua.lua | 7 +- .../texmf-dist/tex/context/base/mkiv/util-mrg.lua | 1 + .../texmf-dist/tex/context/base/mkiv/util-prs.lua | 35 +- .../texmf-dist/tex/context/base/mkiv/util-sac.lua | 113 +- .../texmf-dist/tex/context/base/mkiv/util-seq.lua | 370 +- .../texmf-dist/tex/context/base/mkiv/util-sha.lua | 35 +- .../tex/context/base/mkiv/util-soc-imp-copas.lua | 931 ++++ .../tex/context/base/mkiv/util-soc-imp-ftp.lua | 402 ++ .../tex/context/base/mkiv/util-soc-imp-headers.lua | 145 + .../tex/context/base/mkiv/util-soc-imp-http.lua | 436 ++ .../tex/context/base/mkiv/util-soc-imp-ltn12.lua | 387 ++ .../tex/context/base/mkiv/util-soc-imp-mime.lua | 104 + .../tex/context/base/mkiv/util-soc-imp-reset.lua | 13 + .../tex/context/base/mkiv/util-soc-imp-smtp.lua | 267 + .../tex/context/base/mkiv/util-soc-imp-socket.lua | 193 + .../tex/context/base/mkiv/util-soc-imp-tp.lua | 144 + .../tex/context/base/mkiv/util-soc-imp-url.lua | 268 + .../texmf-dist/tex/context/base/mkiv/util-soc.lua | 32 + .../tex/context/base/mkiv/util-sql-imp-ffi.lua | 590 ++- .../tex/context/base/mkiv/util-sql-imp-library.lua | 8 +- .../tex/context/base/mkiv/util-sql-imp-sqlite.lua | 13 +- .../tex/context/base/mkiv/util-sql-logins.lua | 12 +- .../tex/context/base/mkiv/util-sql-users.lua | 10 +- .../texmf-dist/tex/context/base/mkiv/util-sta.lua | 14 +- .../texmf-dist/tex/context/base/mkiv/util-sto.lua | 13 + .../texmf-dist/tex/context/base/mkiv/util-str.lua | 526 +- .../texmf-dist/tex/context/base/mkiv/util-tab.lua | 54 +- .../texmf-dist/tex/context/base/mkiv/util-you.lua | 1 - 554 files changed, 50854 insertions(+), 27176 deletions(-) create mode 100644 Master/texmf-dist/tex/context/base/mkiv/anch-snc.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/back-pdp.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/back-res.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/colo-imp-svg.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/core-lmt.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/core-lmt.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/driv-ini.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/driv-ini.mkiv delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-ext.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-dimensions.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-effects.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-italics.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-ligatures.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-math.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-notused.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-properties.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-quality.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-reorder.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-tex.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-tracing.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-imp-unicode.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-prv.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-vfc.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-example.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-fields.mkiv delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-highlight.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-print.mkiv delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-steps.mkiv delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-stp.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-videoplayer.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/java-imp-vplayer.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/l-sha.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/lpdf-aux.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/lpdf-fnt.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/luat-soc.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/math-inc.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/math-inc.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/meta-blb.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/meta-blb.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/meta-nod.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/metatex.tex create mode 100644 Master/texmf-dist/tex/context/base/mkiv/mtx-context-fonts.tex create mode 100644 Master/texmf-dist/tex/context/base/mkiv/node-par.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/page-smp.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/publ-inc.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/publ-inc.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/scrp-tib.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua delete mode 100644 Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/strc-usr.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/strc-usr.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/syst-cmp.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/syst-cmp.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/syst-rtp.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/toks-aux.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/toks-scn.mkiv create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-copas.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ftp.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-headers.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-http.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ltn12.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-mime.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-reset.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-smtp.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-socket.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-tp.lua create mode 100644 Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-url.lua (limited to 'Master/texmf-dist/tex/context/base/mkiv') diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi b/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi index 348ea0ad1e2..96dd0cdf54a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-bck.mkvi @@ -47,7 +47,7 @@ \unexpanded\def\anch_backgrounds_text_initialize {\doifelsepositionsused\enableparpositions\donothing - \global\let\anch_backgrounds_text_initialize\relax} + \glet\anch_backgrounds_text_initialize\relax} \appendtoks \anch_backgrounds_text_initialize @@ -352,7 +352,7 @@ {\ifproductionrun \enabletextarearegistration \enablehiddenbackground - \global\let\checkpositionoverlays\relax + \glet\checkpositionoverlays\relax \fi} % shape handling @@ -453,55 +453,55 @@ \strc_floats_mark_as_free \plustwo \zeropoint - \d_page_sides_leftskip + \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftedge \strc_floats_mark_as_free \plustwo \zeropoint - \d_page_sides_leftskip + \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftmargin \strc_floats_mark_as_free \plustwo \zeropoint - \d_page_sides_leftskip + \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftside \strc_floats_mark_as_free \plustwo - \d_page_sides_leftskip - \d_strc_floats_margin + \d_page_sides_leftskip % maybe too + \d_page_sides_margin \d_page_sides_topskip \d_page_sides_bottomskip \or % rightside \strc_floats_mark_as_free \plusthree - \d_strc_floats_margin - \d_page_sides_rightskip + \d_page_sides_margin + \d_page_sides_rightskip % maybe too \d_page_sides_topskip \d_page_sides_bottomskip \or % rightmargin \strc_floats_mark_as_free \plusthree - \d_page_sides_rightskip + \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip \or % rightedge \strc_floats_mark_as_free \plusthree - \d_page_sides_rightskip + \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip \or % cutspace \strc_floats_mark_as_free \plusthree - \d_page_sides_rightskip + \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua index ca5a5a8af15..14afa3967ae 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.lua @@ -56,13 +56,10 @@ graphics.backgrounds = backgrounds -- -- -- local texsetattribute = tex.setattribute -local pdfgetpos = pdf.getpos -- why not a generic name ! local a_textbackground = attributes.private("textbackground") local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local new_latelua = nuts.pool.latelua local new_rule = nuts.pool.rule @@ -82,11 +79,12 @@ local localpar_code = nodecodes.localpar local insert_before = nuts.insert_before local insert_after = nuts.insert_after -local processranges = nodes.processranges +local processranges = nuts.processranges local unsetvalue = attributes.unsetvalue local jobpositions = job.positions +local getpos = jobpositions.getpos local data = { } local realpage = 1 @@ -96,10 +94,17 @@ local enabled = false -- Freeing the data is somewhat tricky as we can have backgrounds spanning -- many pages but for an arbitrary background shape that is not so common. -local function check(a,index,depth,d,where,ht,dp) +local function check(specification) + local a = specification.attribute + local index = specification.index + local depth = specification.depth + local d = specification.data + local where = specification.where + local ht = specification.ht + local dp = specification.dp -- this is not yet r2l ready local w = d.shapes[realpage] - local x, y = pdfgetpos() + local x, y = getpos() if trace_ranges then report_shapes("attribute %i, index %i, depth %i, location %s, position (%p,%p)", a,index,depth,where,x,y) @@ -109,7 +114,7 @@ local function check(a,index,depth,d,where,ht,dp) n = n + 1 d.index = index d.depth = depth --- w[n] = { x, x, y, ht, dp } + -- w[n] = { x, x, y, ht, dp } w[n] = { y, ht, dp, x, x } else local wn = w[n] @@ -150,13 +155,13 @@ local function flush(head,f,l,a,parent,depth) local ix = index local ht = getheight(parent) local dp = getdepth(parent) - local ln = new_latelua(function() check(a,ix,depth,d,"l",ht,dp) end) - local rn = new_latelua(function() check(a,ix,depth,d,"r",ht,dp) end) + local ln = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "l", ht = ht, dp = dp } + local rn = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "r", ht = ht, dp = dp } if trace_ranges then ln = new_hlist(setlink(new_rule(65536,65536*4,0),new_kern(-65536),ln)) rn = new_hlist(setlink(new_rule(65536,0,65536*4),new_kern(-65536),rn)) end - if getid(f) == localpar_code then -- we need to clean this mess + if getid(f) == localpar_code and getsubtype(f) == 0 then -- we need to clean this mess insert_after(head,f,ln) else head, f = insert_before(head,f,ln) @@ -213,10 +218,8 @@ end nodes.handlers.textbackgrounds = function(head,where,parent) -- we have hlistdir and local dir -- todo enable action in register - head = tonut(head) index = index + 1 - local head, done = processranges(a_textbackground,flush,head,parent) - return tonode(head), done + return processranges(a_textbackground,flush,head,parent) end interfaces.implement { @@ -228,6 +231,8 @@ interfaces.implement { -- optimized already but we can assume a cycle i.e. prune the last point and then -- even less code .. we could merge some loops but his is more robust +-- use idiv here + local function topairs(t,n) local r = { } for i=1,n do @@ -237,7 +242,7 @@ local function topairs(t,n) return concat(r," ") end -local eps = 65536 / 4 -- 2 +local eps = 65536 / 4 local pps = eps local nps = - pps @@ -509,7 +514,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld) -- use height of b and depth of e, maybe check for weird border -- cases here if fh then - local lsf, rsf = ls[1], rs[1] + local lsf = ls[1] + local rsf = rs[1] if lsf[2] < fh then lsf[2] = fh end @@ -518,7 +524,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld) end end if fd then - local lsl, rsl = ls[n], rs[n] + local lsl = ls[n] + local rsl = rs[n] if lsl[2] > fd then lsl[2] = fd end @@ -535,12 +542,18 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld) end local function singlepart(b,e,p,realpage,r,left,right) - local bx, by = b.x, b.y - local ex, ey = e.x, e.y - local rx, ry = r.x, r.y - local bh, bd = by + b.h, by - b.d - local eh, ed = ey + e.h, ey - e.d - local rh, rd = ry + r.h, ry - r.d + local bx = b.x + local by = b.y + local ex = e.x + local ey = e.y + local rx = r.x + local ry = r.y + local bh = by + b.h + local bd = by - b.d + local eh = ey + e.h + local ed = ey - e.d + local rh = ry + r.h + local rd = ry - r.d local rw = rx + r.w if left then rx = rx + left @@ -593,10 +606,14 @@ local function singlepart(b,e,p,realpage,r,left,right) end local function firstpart(b,e,p,realpage,r,left,right) - local bx, by = b.x, b.y - local rx, ry = r.x, r.y - local bh, bd = by + b.h, by - b.d - local rh, rd = ry + r.h, ry - r.d + local bx = b.x + local by = b.y + local rx = r.x + local ry = r.y + local bh = by + b.h + local bd = by - b.d + local rh = ry + r.h + local rd = ry - r.d local rw = rx + r.w if left then rx = rx + left @@ -630,8 +647,10 @@ local function firstpart(b,e,p,realpage,r,left,right) end local function middlepart(b,e,p,realpage,r,left,right) - local rx, ry = r.x, r.y - local rh, rd = ry + r.h, ry - r.d + local rx = r.x + local ry = r.y + local rh = ry + r.h + local rd = ry - r.d local rw = rx + r.w if left then rx = rx + left @@ -654,10 +673,14 @@ local function middlepart(b,e,p,realpage,r,left,right) end local function lastpart(b,e,p,realpage,r,left,right) - local ex, ey = e.x, e.y - local rx, ry = r.x, r.y - local eh, ed = ey + e.h, ey - e.d - local rh, rd = ry + r.h, ry - r.d + local ex = e.x + local ey = e.y + local rx = r.x + local ry = r.y + local eh = ey + e.h + local ed = ey - e.d + local rh = ry + r.h + local rd = ry - r.d local rw = rx + r.w if left then rx = rx + left @@ -740,7 +763,7 @@ local function calculatemultipar(tag) local bp = b.p -- page if trace_shapes then report_shapes("tag %a, left %p, right %p, par %s, page %s, column %s", - left,right,bn or "-",bp or "-",bc or "-") + tag,left,right,bn or "-",bp or "-",bc or "-") end -- if bindex == eindex then @@ -844,8 +867,10 @@ local function freemultipar(pagedata,frees) -- ,k local areas = { } data.areas = areas - local f_1, n_1 = { }, 0 - local f_2, n_2 = { }, 0 + local f_1 = { } + local n_1 = 0 + local f_2 = { } + local n_2 = 0 for i=1,#frees do local f = frees[i] local k = f.k @@ -908,14 +933,18 @@ local function freemultipar(pagedata,frees) -- ,k -- we can collect the coordinates first local function check_two(area,frees) - local ul = area[1] - local ur = area[2] - local lr = area[3] - local ll = area[4] - local ulx, uly = ul[1], ul[2] - local urx, ury = ur[1], ur[2] - local lrx, lry = lr[1], lr[2] - local llx, lly = ll[1], ll[2] + local ul = area[1] + local ur = area[2] + local lr = area[3] + local ll = area[4] + local ulx = ul[1] + local uly = ul[2] + local urx = ur[1] + local ury = ur[2] + local lrx = lr[1] + local lry = lr[2] + local llx = ll[1] + local lly = ll[2] local temp = { } local n = 0 @@ -1108,12 +1137,16 @@ local function fetchmultipar(n,anchor,page) report_graphics("fetching %a at page %s using anchor %a containing %s multipars", n,page,anchor,nofmultipars) end - local x, y = a.x, a.y - local w, h, d = a.w, a.h, a.d - local bpos = data.bpos - local bh, bd = bpos.h, bpos.d - local result = { false } -- slot 1 will be set later - local n = 0 + local x = a.x + local y = a.y + local w = a.w + local h = a.h + local d = a.d + local bpos = data.bpos + local bh = bpos.h + local bd = bpos.d + local result = { false } -- slot 1 will be set later + local n = 0 for i=1,nofmultipars do local data = pagedata[i] local location = data.location @@ -1178,7 +1211,8 @@ implement { if type(tags) == "string" then tags = utilities.parsers.settings_to_array(tags) end - local list, nofboxes = { }, 0 + local list = { } + local nofboxes = 0 for i=1,#tags do local tag= tags[i] local c = collected[tag] @@ -1187,7 +1221,11 @@ implement { if r then r = collected[r] if r then - local rx, ry, rw, rh, rd = r.x, r.y, r.w, r.h, r.d + local rx = r.x + local ry = r.y + local rw = r.w + local rh = r.h + local rd = r.d local cx = c.x - rx local cy = c.y local cw = cx + c.w diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv index e49d18b8f6c..7fa378cd14f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pgr.mkiv @@ -66,7 +66,7 @@ \def\anch_positions_action_indeed_yes % we need a way to figure out if we have actions {\begingroup - \setbox\scratchbox\hbox + \setbox\scratchbox\hbox % \hpack {\anch_positions_trace_action_yes \the\everyinsertpositionaction \the\everypositionaction @@ -130,12 +130,12 @@ \else \c_anch_page_width \paperwidth \c_anch_page_height\paperheight - \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hbox{\box#1}\fi + \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi \fi \else \c_anch_page_width \paperwidth \c_anch_page_height\paperheight - \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hbox{\box#1}\fi + \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi \fi \fi\fi} @@ -157,7 +157,7 @@ \endgroup} \def\anch_positions_place_anchors_nop - {\vskip\textheight} + {\vkern\textheight} %D \macros %D {positionoverlay,startpositionoverlay} @@ -243,7 +243,7 @@ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used \the\everyinsertpositionaction \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid - \setbox\scratchbox\hbox to \d_overlay_width + \setbox\scratchbox\hbox to \d_overlay_width % \hpack {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% \ht\scratchbox\d_overlay_height \dp\scratchbox\zeropoint @@ -275,7 +275,7 @@ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used \the\everyinsertpositionaction \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid - \setbox\scratchbox\hbox to \d_overlay_width + \setbox\scratchbox\hbox to \d_overlay_width % \hpack {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}% \ht\scratchbox\d_overlay_height \dp\scratchbox\zeropoint @@ -366,7 +366,7 @@ \anch_positions_meta_graphic_prepare \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments - \setbox\b_anch_positions_graphic\hbox + \setbox\b_anch_positions_graphic\hbox % \hpack {\ignorespaces\csname#1#2\endcsname\removelastspace}% \smashbox\b_anch_positions_graphic \box\b_anch_positions_graphic diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua index e5f58c36ce4..ade99279201 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.lua @@ -20,8 +20,12 @@ more efficient.

-- this is one of the first modules using scanners and we need to replace -- it by implement and friends +-- 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) + local tostring, next, rawget, rawset, setmetatable, tonumber = tostring, next, rawget, rawset, setmetatable, tonumber -local sort, sortedhash, sortedkeys = table.sort, table.sortedhash, table.sortedkeys +local sort = table.sort local format, gmatch = string.format, string.gmatch local rawget = rawget local lpegmatch = lpeg.match @@ -40,7 +44,8 @@ local scanners = interfaces.scanners local commands = commands local context = context -local ctxnode = context.nodes.flush + +local ctx_latelua = context.latelua local tex = tex local texgetcount = tex.getcount @@ -63,12 +68,12 @@ local getbox = nuts.getbox local getid = nuts.getid local getwhd = nuts.getwhd ------ hlist_code = nodes.listcodes.hlist +local hlist_code = nodes.nodecodes.hlist local find_tail = nuts.tail +local hpack = nuts.hpack local new_latelua = nuts.pool.latelua -local new_latelua_node = nodes.pool.latelua local variables = interfaces.variables local v_text = variables.text @@ -236,7 +241,6 @@ end -- t[#t+1] = data -- end -- --- -- -- local pages = structures.pages.collected -- if pages then -- local last = nil @@ -326,9 +330,19 @@ local nofpages = nil -- beware ... we're not sparse here as lua will reserve slots for the nilled -local getpos = function() getpos = backends.codeinjections.getpos return getpos () end -local gethpos = function() gethpos = backends.codeinjections.gethpos return gethpos() end -local getvpos = function() getvpos = backends.codeinjections.getvpos return getvpos() end +local getpos, gethpos, getvpos + +function jobpositions.registerhandlers(t) + getpos = t and t.getpos or function() return 0, 0 end + gethpos = t and t.gethpos or function() return 0 end + getvpos = t and t.getvpos or function() return 0 end +end + +function jobpositions.getpos () return getpos () end +function jobpositions.gethpos() return gethpos() end +function jobpositions.getvpos() return getvpos() end + +jobpositions.registerhandlers() local function setall(name,p,x,y,w,h,d,extra) tobesaved[name] = { @@ -386,9 +400,28 @@ end -- analyze some files (with lots if margindata) and then when one key optionally -- use that one instead of a table (so, a 3rd / 4th argument: key, e.g. "x") -local function set(name,index,val) -- ,key - local data = enhance(val or index) - if val then +local function set(name,index,value) -- ,key + local data = enhance(value or index) + if value then + container = tobesaved[name] + if not container then + tobesaved[name] = { + [index] = data + } + else + container[index] = data + end + else + tobesaved[name] = data + end +end + +local function setspec(specification) + local name = specification.name + local index = specification.index + local value = specification.value + local data = enhance(value or index) + if value then container = tobesaved[name] if not container then tobesaved[name] = { @@ -411,16 +444,11 @@ local function get(id,index) end end -------------.setdim = setdim -jobpositions.setall = setall -jobpositions.set = set -jobpositions.get = get - --- scanners.setpos = setall - --- trackers.enable("tokens.compi*") - --- something weird: the compiler fails us here +------------.setdim = setdim +jobpositions.setall = setall +jobpositions.set = set +jobpositions.setspec = setspec +jobpositions.get = get scanners.dosaveposition = compilescanner { actions = setall, -- name p x y @@ -442,7 +470,8 @@ scanners.dosavepositionplus = compilescanner { -- not much gain in keeping stack (inc/dec instead of insert/remove) -local function b_column(tag) +local function b_column(specification) + local tag = specification.tag local x = gethpos() tobesaved[tag] = { r = true, @@ -453,7 +482,7 @@ local function b_column(tag) column = tag end -local function e_column(tag) +local function e_column() local t = tobesaved[column] if not t then -- something's wrong @@ -479,7 +508,7 @@ scanners.bposcolumnregistered = function() -- tag local tag = scanstring() insert(columns,tag) column = tag - ctxnode(new_latelua_node(function() b_column(tag) end)) + ctx_latelua { action = b_column, tag = tag } end scanners.eposcolumn = function() @@ -488,38 +517,42 @@ scanners.eposcolumn = function() end scanners.eposcolumnregistered = function() - ctxnode(new_latelua_node(e_column)) + ctx_latelua { action = e_column } remove(columns) column = columns[#columns] end -- regions -local function b_region(tag) +local function b_region(specification) + local tag = specification.tag or specification local last = tobesaved[tag] local x, y = getpos() last.x = x ~= 0 and x or nil last.y = y ~= 0 and y or nil last.p = texgetcount("realpageno") - insert(regions,tag) + insert(regions,tag) -- todo: fast stack region = tag end -local function e_region(correct) +local function e_region(specification) local last = tobesaved[region] local y = getvpos() - if correct then + local x, y = getpos() + if specification.correct then local h = (last.y or 0) - y last.h = h ~= 0 and h or nil end last.y = y ~= 0 and y or nil - remove(regions) + remove(regions) -- todo: fast stack region = regions[#regions] end jobpositions.b_region = b_region jobpositions.e_region = e_region +local lastregion + local function setregionbox(n,tag,k,lo,ro,to,bo) -- kind if not tag or tag == "" then nofregions = nofregions + 1 @@ -527,34 +560,34 @@ local function setregionbox(n,tag,k,lo,ro,to,bo) -- kind end local box = getbox(n) local w, h, d = getwhd(box) - local x, y = getpos() -- hm, makes no sense here tobesaved[tag] = { - -- p = texgetcount("realpageno"), -- we copy them - x = x ~= 0 and x or nil, -- was true - y = y ~= 0 and y or nil, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - k = k ~= 0 and k or nil, + -- p = texgetcount("realpageno"), -- we copy them + x = 0, + y = 0, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + k = k ~= 0 and k or nil, lo = lo ~= 0 and lo or nil, ro = ro ~= 0 and ro or nil, to = to ~= 0 and to or nil, bo = bo ~= 0 and bo or nil, } + lastregion = tag return tag, box end local function markregionbox(n,tag,correct,...) -- correct needs checking local tag, box = setregionbox(n,tag,...) -- todo: check if tostring is needed with formatter - local push = new_latelua(function() b_region(tag) end) - local pop = new_latelua(function() e_region(correct) end) + local push = new_latelua { action = b_region, tag = tag } + local pop = new_latelua { action = e_region, correct = correct } -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end local head = getlist(box) - -- no : + -- no, this fails with \framed[region=...] .. needs thinking -- if getid(box) ~= hlist_code then -- -- report("mark region box assumes a hlist, fix this for %a",tag) - -- head = nuts.hpack(head) + -- head = hpack(head) -- end if head then local tail = find_tail(head) @@ -584,7 +617,7 @@ end local nofparagraphs = 0 -scanners.parpos = function() -- todo: relate to localpar (so this is an intermediate variant) +scanners.parpos = function() nofparagraphs = nofparagraphs + 1 texsetcount("global","c_anch_positions_paragraph",nofparagraphs) local box = getbox("strutbox") @@ -623,14 +656,14 @@ scanners.parpos = function() -- todo: relate to localpar (so this is an intermed if parshape and #parshape > 0 then t.ps = parshape end - local tag = f_p_tag(nofparagraphs) - tobesaved[tag] = t - ctxnode(new_latelua_node(function() enhance(tobesaved[tag]) end)) + local name = f_p_tag(nofparagraphs) + tobesaved[name] = t + ctx_latelua { action = enhance, specification = t } end scanners.dosetposition = function() -- name local name = scanstring() - tobesaved[name] = { + local spec = { p = true, c = column, r = true, @@ -639,15 +672,15 @@ scanners.dosetposition = function() -- name n = nofparagraphs > 0 and nofparagraphs or nil, r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end scanners.dosetpositionwhd = function() -- name w h d extra local name = scanstring() - local w = scandimen() - local h = scandimen() - local d = scandimen() - tobesaved[name] = { + local w = scandimen() + local h = scandimen() + local d = scandimen() + local spec = { p = true, c = column, r = true, @@ -659,14 +692,14 @@ scanners.dosetpositionwhd = function() -- name w h d extra n = nofparagraphs > 0 and nofparagraphs or nil, r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end scanners.dosetpositionbox = function() -- name box local name = scanstring() local box = getbox(scaninteger()) local w, h, d = getwhd(box) - tobesaved[name] = { + local spec = { p = true, c = column, r = true, @@ -678,15 +711,15 @@ scanners.dosetpositionbox = function() -- name box n = nofparagraphs > 0 and nofparagraphs or nil, r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end scanners.dosetpositionplus = function() -- name w h d extra local name = scanstring() - local w = scandimen() - local h = scandimen() - local d = scandimen() - tobesaved[name] = { + local w = scandimen() + local h = scandimen() + local d = scandimen() + local spec = { p = true, c = column, r = true, @@ -699,14 +732,14 @@ scanners.dosetpositionplus = function() -- name w h d extra e = scanstring(), r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end scanners.dosetpositionstrut = function() -- name local name = scanstring() local box = getbox("strutbox") local w, h, d = getwhd(box) - tobesaved[name] = { + local spec = { p = true, c = column, r = true, @@ -717,7 +750,7 @@ scanners.dosetpositionstrut = function() -- name n = nofparagraphs > 0 and nofparagraphs or nil, r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end scanners.dosetpositionstrutkind = function() -- name @@ -725,7 +758,7 @@ scanners.dosetpositionstrutkind = function() -- name local kind = scaninteger() local box = getbox("strutbox") local w, h, d = getwhd(box) - tobesaved[name] = { + local spec = { k = kind, p = true, c = column, @@ -737,7 +770,7 @@ scanners.dosetpositionstrutkind = function() -- name n = nofparagraphs > 0 and nofparagraphs or nil, r2l = texgetcount("inlinelefttoright") == 1 or nil, } - ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end)) + ctx_latelua { action = enhance, specification = spec } end function jobpositions.getreserved(tag,n) @@ -1377,6 +1410,11 @@ scanners.markregionboxtaggedkind = function() -- box tag kind scaninteger(),scandimen(),scandimen(),scandimen(),scandimen()) end +scanners.reservedautoregiontag = function() + nofregions = nofregions + 1 + context(f_region(nofregions)) +end + -- statistics (at least for the moment, when testing) -- statistics.register("positions", function() diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv index ab199eb1eee..fbebb5f173b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-pos.mkiv @@ -155,7 +155,7 @@ \def\anch_positions_set_data_indeed#1#2#3#4% {\anch_positions_initialize - \hbox + \hbox % \hpack {\edef\currentposition{#1}% \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr \anch_positions_trace_left @@ -177,7 +177,7 @@ \def\anch_positions_set_box_finish#1% {\anch_positions_initialize - \hbox to \wd\nextbox + \hbox to \wd\nextbox % \hpack {\edef\currentposition{#1}% \dosetpositionbox\currentposition\nextbox \anch_positions_trace_left @@ -198,7 +198,7 @@ \def\anch_positions_set_strut_yes#1% {\anch_positions_initialize - \hbox to \zeropoint + \hbox to \zeropoint % \hpack {\edef\currentposition{#1}% \dosetpositionstrut\currentposition \anch_positions_trace_left @@ -215,7 +215,7 @@ \def\anch_positions_set_strut_kind_yes#1#2% {\anch_positions_initialize - \hbox to \zeropoint + \hbox to \zeropoint % \hpack {\edef\currentposition{#1}% \dosetpositionstrutkind\currentposition{#2}% \anch_positions_trace_left @@ -235,7 +235,7 @@ \def\anch_positions_set_plus_indeed#1#2#3#4#5% {\anch_positions_initialize - \hbox % just package + \hbox % \hpack {\edef\currentposition{#1}% \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr \anch_positions_trace_right @@ -257,7 +257,7 @@ \def\anch_positions_set_plus_yes_finish#1#2% {\anch_positions_initialize - \hbox to \nextboxwd + \hbox to \nextboxwd % \hpack {\edef\currentposition{#1}% \dosetpositionplus\currentposition{\wd\nextbox}{\ht\nextbox}{\dp\nextbox}{#2}% \anch_positions_trace_right @@ -296,7 +296,7 @@ {\clf_markregionbox#1\relax} \unexpanded\def\anch_mark_flow_box#1% will be extended / renamed - {\hbox\bgroup + {\hpack\bgroup % \hpack \global\advance\c_anch_text\plusone \clf_markregionboxtagged#1{textarea:\the\c_anch_text}% \box#1% @@ -330,6 +330,8 @@ #6\relax % bottomoffset \fi} +\def\reservedautoregiontag{\clf_reservedautoregiontag} + %D We can copy a position with: %D %D \starttyping @@ -393,7 +395,7 @@ {\the\t_anch_positions_tracers} \unexpanded\def\enableparpositions % global - {\global\let\registerparoptions\doregisterparoptions + {\glet\registerparoptions\doregisterparoptions \global\positioningtrue} \let\disableparpositions\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-snc.lua b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.lua new file mode 100644 index 00000000000..8006f3bd674 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.lua @@ -0,0 +1,271 @@ +if not modules then modules = { } end modules ['anch-snc'] = { + version = 1.001, + comment = "companion to anch-snc.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + + +function mp.xxOverlayRegion() + local r = tokens.getters.macro("m_overlay_region") + mp.quoted('"'.. r .. '"') +-- mp.print('"'.. r .. '"') +end + +-- use factors as in mlib-int.lua + +local tonumber, next, setmetatable = tonumber, next, setmetatable +local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy +local match, find = string.match, string.find +local lpegmatch = lpeg.match + +local setmetatableindex = table.setmetatableindex + +local factor = number.dimenfactors.bp +local mpprint = mp.print +local mpnumeric = mp.numeric +local mppoints = mp.points +local texgetdimen = tex.getdimen + +local p_number = lpeg.patterns.cardinal/tonumber +local p_space = lpeg.patterns.whitespace^0 +local p_tag = lpeg.P("syncpos:") * p_number * lpeg.P(":") * p_number +local p_option = p_number -- for now + * ((lpeg.P(",") * p_space * lpeg.P("reset") * lpeg.Cc(true)) + lpeg.Cc(false)) + +local list = { } +local colors = setmetatableindex("table") + +local kinds = { + above = 1, + continue = 2, + nothing = 3, + normal = 4, + 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 mp.sync_collect(category,realpage,useregion) + local all = allentries[category] + local m = 0 + local n = #all + list = { } + if useregion then + -- successive can be optimized when we sort by region + local start = 1 + local done = false + local last, rtop, rbot + for i=start,n do + local pos = all[i] + local p = pos.p + local r = pos.r + if r == useregion then + if not done then + local region = job.positions.collected[r] + list.region = region + list.page = region + rtop = (region.y or 0) + (region.h or 0) + rbot = (region.y or 0) - (region.d or 0) + last = { kind = "nothing", top = rtop, bottom = 0, task = 0 } + m = m + 1 ; list[m] = last + done = true + end + local top = pos.y + pos.h + last.bottom = top + local task, reset = lpegmatch(p_option,pos.e) + last = { kind = "normal", top = top, bottom = 0, task = task } + m = m + 1 ; list[m] = last + end + end + if done then + last.bottom = rbot + end + else + local start = all.start or 1 + local done = false + local last, rtop, rbot, ptop, pbot + for i=start,n do + local pos = all[i] + 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 + list.region = region + list.page = page + rtop = (region.y or 0) + (region.h or 0) + rbot = (region.y or 0) - (region.d or 0) + ptop = (page .y or 0) + (page .h or 0) + pbot = (page .y or 0) - (page .d or 0) + last = { kind = "above", top = ptop, bottom = rtop, task = 0 } + m = m + 1 ; list[m] = last + if i > 1 then + local task, reset = lpegmatch(p_option,all[i-1].e) + last = { kind = "continue", top = rtop, bottom = 0, task = task } + m = m + 1 ; list[m] = last + else + last = { kind = "nothing", top = rtop, bottom = 0, task = 0 } + m = m + 1 ; list[m] = last + end + done = true + end + local top = pos.y + pos.h + last.bottom = top + local task, reset = lpegmatch(p_option,pos.e) + if reset then + local l = list[2] + l.kind = "nothing" + l.task = 0 + end + last = { kind = "normal", top = top, bottom = 0, task = task } + m = m + 1 ; list[m] = last + elseif p > realpage then + all.start = i -- tricky, only for page + break + end + end + if done then + last.bottom = rbot + last = { kind = "below", top = rbot, bottom = pbot, task = 0 } + m = m + 1 ; list[m] = last + lastdone[category] = { + { kind = "above", top = ptop, bottom = rtop, task = 0 }, + { kind = "continue", top = rtop, bottom = rbot, task = list[#list-1].task }, -- lasttask + { kind = "below", top = rbot, bottom = pbot, task = 0 }, + region = list.region, + page = list.page, + } + else + local l = lastdone[category] + if l then + list = copy(l) -- inefficient, mayb emetatable for region/page + m = 3 + end + end + end + mpnumeric(m) +end + +function mp.sync_extend() + local n = #list + if n > 0 then + for i=1,n do + local l = list[i] + local k = l.kind + if k == "nothing" then + local ll = list[i+1] + if ll and ll.kind == "normal" then + ll.top = l.top + remove(list,i) + n = #list + break + end + end + end + end + mpnumeric(n) +end + +function mp.sync_prune() + local n = #list + if n > 0 then + if list[1].kind == "above" then + remove(list,1) + end + if list[1].kind == "nothing" then + remove(list,1) + end + if list[#list].kind == "below" then + remove(list,#list) + end + n = #list + end + mpnumeric(n) +end + +function mp.sync_collapse() + local n = #list + if n > 0 then + local m = 0 + local p = nil + for i=1,n do + local l = list[i] + local t = l.task + if p == t then + list[m].bottom = l.bottom + else + m = m + 1 + list[m] = l + end + p = t + end + for i=n,m+1,-1 do + list[i] = nil + end + n = m + end + mpnumeric(n) +end + +function mp.sync_set_color(category,n,v) + colors[category][n] = v +end + +function mp.sync_get_color(category,n) + mpprint(colors[category][n]) +end + +-- function mp.sync_get_size () mpnumeric(#list) end +-- function mp.sync_get_top (n) mppoints (list[n].top) end +-- function mp.sync_get_bottom(n) mppoints (list[n].bottom) end +-- function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end +-- function mp.sync_get_task (n) mpnumeric(list[n].task) end + +-- function mp.sync_get_x() mppoints(list.page.x or 0) end +-- function mp.sync_get_y() mppoints(list.page.y or 0) end +-- function mp.sync_get_w() mppoints(list.page.w or 0) end +-- function mp.sync_get_h() mppoints(list.page.h or 0) end +-- function mp.sync_get_d() mppoints(list.page.d or 0) end + +function mp.sync_get_size () mpnumeric(#list) end +function mp.sync_get_top (n) mpnumeric(list[n].top * factor) end +function mp.sync_get_bottom(n) mpnumeric(list[n].bottom * factor) end +function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end +function mp.sync_get_task (n) mpnumeric(list[n].task) end + +function mp.sync_get_x() mpnumeric((list.page.x or 0)*factor) end +function mp.sync_get_y() mpnumeric((list.page.y or 0)*factor) end +function mp.sync_get_w() mpnumeric((list.page.w or 0)*factor) end +function mp.sync_get_h() mpnumeric((list.page.h or 0)*factor) end +function mp.sync_get_d() mpnumeric((list.page.d or 0)*factor) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv index 3e99da8a64f..5f0246155e8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-snc.mkiv @@ -1,6 +1,6 @@ %D \module %D [ file=anch-snc, -%D version=2003.12.01, +%D version=2003.12.01, % actually 1999 so real old %D title=\CONTEXT\ Anchoring Macros, %D subtitle=Synchronization, %D author=Hans Hagen, @@ -11,151 +11,42 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% this can be optimized (will do when used again) +%D The original is in the mkii file. It does more at the \TEX\ end and +%D has some more magic. If we really need that I'll add it. After all, +%D in mkiv we can do things different. + +%D TODO: bleed : + left , minus right oro check if it touches page ... autobleed \writestatus{loading}{ConTeXt Anchoring Macros / Synchronization} +\registerctxluafile{anch-snc}{} + \unprotect -\ifx\s!num \undefined \def\s!num {num} \fi -\ifx\s!set \undefined \def\s!set {set} \fi -\ifx\s!reset \undefined \def\s!reset {reset} \fi -\ifx\s!preset \undefined \def\s!preset {preset} \fi -\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi +\ifx\??syncposcounter\undefined \installcorenamespace{syncposcounter} \fi +\ifx\s!syncpos \undefined \def\s!syncpos {syncpos} \fi + +\let\c_sync_n\relax \unexpanded\def\definesyncpositions[#1]% - {\ifcsname\s!num:\s!syncpos:#1\endcsname \else - \global\let\flushsyncpositions\doflushsyncpositions % only when used - \global\let\flushsyncresets \doflushsyncresets - \global\let\flushsyncpresets \doflushsyncpresets - \expandafter\newcount\csname\s!num:\s!syncpos:#1\endcsname - \doglobal\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions - \doglobal\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions -% to be tested: -% \doglobal\expandafter\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions -% \doglobal\expandafter\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions - \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}% - \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}% + {\ifcsname\??syncposcounter:#1\endcsname \else + \expandafter\newcount\csname\??syncposcounter:#1\endcsname \fi} -\def\syncposition - {\dodoubleempty\dosyncposition} - -\def\dosyncposition[#1][#2]% - {\letgvalue{\s!reset :\s!syncpos:#1}\relax - \letgvalue{\s!preset:\s!syncpos:#1}\relax - \dontleavehmode - \dodosyncposition{#1}{#2}\s!set - \ignorespaces} - -\def\doifelselastsyncposition#1#2% - {\doifelse{\lastsyncclass\lastsyncposition}{#1#2}} - -\let\doiflastsyncpositionelse\doifelselastsyncposition +\unexpanded\def\syncposition + {\dodoubleempty\anch_sync_position} -\def\dodosyncposition#1#2#3% - {\letgvalue{\s!reset:\s!syncpos:#1}\relax - \letgvalue{\s!preset:\s!syncpos:#1}\relax - \ifcsname\s!syncpos:#1\endcsname - \global\advance\csname\s!num:\s!syncpos:#1\endcsname\plusone - \setsyncpositions{#1}% - % option: geen w/h, alleen p 0 0 0 data - \setpositionplus{\s!syncpos:#1:\the\csname\s!num:\s!syncpos:#1\endcsname}{#2}\hpack{\strut}% +\def\anch_sync_position[#1][#2]% we could actually use par positions + {\dontleavehmode + \ifcsname\??syncposcounter:#1\endcsname + \let\c_sync_n\lastnamedcs + \global\advance\c_sync_n\plusone + \enabletextarearegistration + \setpositionplus{\s!syncpos:#1:\the\c_sync_n}{#2}\hpack{\strut}% \else \strut - \fi} - -\def\setsyncpositions#1% - {\enabletextarearegistration - \getvalue {\s!set:\s!syncpos:#1}% - \letgvalue{\s!set:\s!syncpos:#1}\relax} - -\def\dosetsyncpositions#1% - {\startnointerference % removing out of sync can best be done in mp - \!!dimena\maxdimen - \!!counta\zerocount - \!!countc\zerocount - \doloop - {\doifelseposition{\s!syncpos:#1:\recurselevel} - {\!!dimenb\MPy{\s!syncpos:#1:\recurselevel}\relax - \!!countb\MPp{\s!syncpos:#1:\recurselevel}\relax - \ifnum\!!countb=\!!counta % same page - \ifdim\!!dimenb>\!!dimena - \donefalse % out of order nodes - \else - \donetrue % nodes in order - \fi - \else - \donetrue % different page - \fi - \ifdone - \!!counta\!!countb - \!!dimena\!!dimenb - \advance\!!countc\plusone - \edef\!!stringa{[#1][\the\!!countc]:=}% - \edef\!!stringc{\s!syncpos:#1:\the\!!countc}% - \edef\!!stringd{\MPplus\!!stringc{1}{0}}% - \setxvalue{\s!syncpos:#1}% - {\getsyncpositions{#1}% - sync_p \!!stringa \MPp \!!stringc ; - sync_xy\!!stringa \MPxy\!!stringc ; - sync_w \!!stringa \MPw \!!stringc ; - sync_h \!!stringa \MPh \!!stringc ; - sync_d \!!stringa \MPd \!!stringc ; - \ifx\!!stringd\empty \else sync_t \!!stringa \MPplus\!!stringc{1}{0} ; \fi}% - \fi} - {\setxvalue{\s!syncpos:#1}% - {\getsyncpositions{#1}% - sync_n[#1] := \the\!!countc ;} - \exitloop}}% - \stopnointerference} - -\def\getsyncpositions#1% - {\getvalue{\s!syncpos:#1}} - -\newtoks\resetsyncpositions -\newtoks\presetsyncpositions - -\def\resyncposition {\dodoubleargument\doresyncposition} -\def\presyncposition{\dodoubleargument\dopresyncposition} - -\def\dodoresyncposition #1#2{\dodosyncposition{#1}{#2}\s!reset} -\def\dodopresyncposition#1#2{\dodosyncposition{#1}{#2}\s!preset} - -\def\doresyncposition [#1][#2]{\setxvalue{\s!reset :\s!syncpos:#1}{\noexpand\dodoresyncposition{#1}{#2}}} -\def\dopresyncposition[#1][#2]{\setxvalue{\s!preset:\s!syncpos:#1}{\noexpand\dodopresyncposition{#1}{#2}}} - -\let\flushsyncpositions\relax - -\def\doflushsyncpositions % this order ! - {\begingroup - \the\presetsyncpositions - \the\resetsyncpositions - \endgroup} - -\def\flushsyncxxsets#1% - {\begingroup - \setbox\scratchbox\hbox{\the#1}% - \ifvoid\scratchbox\else - \prewordbreak - %\let\prewordbreak\relax % only once - \smashbox\scratchbox - \box\scratchbox \fi - \endgroup} - -\let\flushsyncresets \relax -\let\flushsyncpresets\relax - -\def\doflushsyncresets {\flushsyncxxsets\resetsyncpositions } -\def\doflushsyncpresets{\flushsyncxxsets\presetsyncpositions} - -% \appendtoks \flushsyncpositions \to \everypar -% \appendtoks \flushsyncpositions \to \everyheadstart - -% \explicitneverypar -> in grid snapper, eerst testen -% -% \appendtoks \flushsyncpositions \to \neverypar + \ignorespaces} \protect @@ -163,41 +54,106 @@ \starttext +% \setuppapersize[A4][A3] + +\setuplayout[location=middle] + \setupbodyfont[dejavu] \definesyncpositions[1] +\definesyncpositions[2] + +% \enabletrackers[metapost.lua] + +\startMPdefinitions + input "mp-asnc.mpiv" ; + + SetSyncColor(1,0,"magenta") ; + SetSyncColor(1,1,"red") ; + SetSyncColor(1,2,"green") ; + SetSyncColor(1,3,"blue") ; + SetSyncColor(1,4,"yellow") ; + + SetSyncColor(2,0,"magenta") ; + SetSyncColor(2,1,"red") ; + SetSyncColor(2,2,"green") ; + SetSyncColor(2,3,"blue") ; + SetSyncColor(2,4,"yellow") ; +\stopMPdefinitions + +\startuseMPgraphic{sync1} + StartPage ; + StartSync(1) ; + SyncHOffset := 0 ; + SyncWidth := BackSpace - LeftMarginDistance; + CollectSyncDataPage ; + % ExtendSyncPaths ; % to top of text area + PruneSyncPaths ; % clip top / bottom + CollapseSyncPaths ; + MakeSyncPaths ; + % DrawSyncPaths ; + FillSyncPaths ; + StopSync ; + clip currentpicture to Page ; + setbounds currentpicture to Page ; + StopPage ; +\stopuseMPgraphic -\startuseMPgraphic{sync} - StartPage ; - \getsyncpositions{1} ; - SyncThreshold := 2LineHeight ; - SyncLeftOffset := -.5LeftMarginDistance ; - % SetSyncThreshold(1,3,3LineHeight) ; - SyncWidth := - (BackSpace + SyncLeftOffset) ; - SetSyncColor(1,1,\MPcolor{red}) ; - SetSyncColor(1,2,\MPcolor{green}) ; - SetSyncColor(1,3,\MPcolor{blue}) ; - SetSyncColor(1,4,\MPcolor{yellow}) ; - PrepareSyncTasks(1,true,true,false) ; - for i = 1 upto NOfSyncPaths : - fill SyncPaths[i] - withcolor TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]]) ; - endfor ; - setbounds currentpicture to Page ; - StopPage ; +\startuseMPgraphic{sync2} + StartSync(2) ; + SyncHOffset := -1cm ; + SyncWidth := 1cm ; + CollectSyncDataRegion(OverlayRegion) ; + ExtendSyncPaths ; % to top of text area + MakeSyncPaths ; + FillSyncPaths ; + StopSync ; + clip currentpicture to OverlayBox leftenlarged 1cm; + setbounds currentpicture to OverlayBox ; \stopuseMPgraphic -\defineoverlay[tempoverlay][\useMPgraphic{sync}] +\defineoverlay[tempoverlay1][\useMPgraphic{sync1}] +\defineoverlay[tempoverlay2][\useMPgraphic{sync2}] + +\setupbackgrounds[page][background=tempoverlay1] + +\framed[region=yes,background=tempoverlay2,width=14cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} + + +\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=16cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} + +\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=10cm,align=normal]{ + \syncposition[2][1]\samplefile{ward}\endgraf + \syncposition[2][2]\samplefile{ward}\endgraf + \syncposition[2][3]\samplefile{ward}\endgraf +} -\setupbackgrounds[page][background=tempoverlay] -\dorecurse {10} { +\dorecurse {100} { +% \dorecurse {1} { + \startchapter[title={Test #1}] + \syncposition[1][1,reset]\dorecurse{20}{\samplefile{ward}\endgraf} + \syncposition[1][2]\dorecurse {4}{\samplefile{ward}\endgraf} + \syncposition[1][3]\dorecurse {7}{\samplefile{ward}\endgraf} + \syncposition[1][4]\dorecurse {3}{\samplefile{ward}\endgraf} + \stopchapter +} +\dorecurse {100} { +% \dorecurse {1} { \startchapter[title={Test #1}] - \syncposition[1][1] \dorecurse{10}{\input ward \endgraf} - \syncposition[1][2] \dorecurse {4}{\input ward \endgraf} - \syncposition[1][3] \dorecurse {7}{\input ward \endgraf} - \syncposition[1][4] \dorecurse {3}{\input ward \endgraf} + \syncposition[1][1]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][2]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][3]\dorecurse{1}{\samplefile{ward}\endgraf} + \syncposition[1][4]\dorecurse{1}{\samplefile{ward}\endgraf} \stopchapter } diff --git a/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv index afa87c7b272..67afb22f7cb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/anch-tab.mkiv @@ -84,8 +84,8 @@ \newcount \noftabpositions \newtoks \posXCtoks -\def\anch_tabulate_bpos{\bpos} -\def\anch_tabulate_epos{\epos} +\unexpanded\def\anch_tabulate_bpos{\bpos} +\unexpanded\def\anch_tabulate_epos{\epos} \installcorenamespace{positiontables} @@ -134,15 +134,18 @@ {\anch_tables_append_GSC[#1:#1]} \def\anch_tables_append_GSC[#1:#2:#3]% - {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC} +% {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC} + {\gtoksapp\posXCtoks{\anch_tables_process_GSC[#1:#2]}\NC} \def\anch_tables_process_GSC[#1:#2]% {\remappositionframed{#2}{\tbPOSprefix#1}% \anch_tabulate_bpos{\tbPOSprefix#1}% - \doglobal\appendtoks\@EA\anch_tabulate_epos\@EA{\tbPOSprefix#1}\to\posXCtoks} + \doglobal\appendtoks\expandafter\anch_tabulate_epos\expandafter{\tbPOSprefix#1}\to\posXCtoks} +% \xtoksapp\posXCtoks{\anch_tabulate_epos{\tbPOSprefix#1}}} \def\anch_tables_indeed_GFC[#1]% {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC} +% {\gtoksapp\posXCtoks{\anch_tables_delayed_GFC[#1]}\NC} \def\anch_tables_delayed_GFC[#1]% {\processcommalist[#1]\anch_tables_step_GFC} @@ -156,9 +159,11 @@ \def\anch_tables_indeed_GTC[#1]% {\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC} +% {\gtoksapp\posXCtoks{\anch_tables_delayed_GTC[#1]}\NC} \def\anch_tables_delayed_GTC[#1]% {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks} +% {\gtoksapp\posXCtoks{\anch_tables_process_GTC[#1]}\NC} \def\anch_tables_process_GTC[#1]% {\processcommalist[#1]\anch_tables_step_GTC} @@ -207,10 +212,10 @@ \let\anch_tabulate_flush_epos\relax -\def\anch_tabulate_bpos_indeed +\unexpanded\def\anch_tabulate_bpos_indeed {\bpos} -\def\anch_tabulate_epos_indeed#1% +\unexpanded\def\anch_tabulate_epos_indeed#1% {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column \epos{#1}% \glet\anch_tabulate_flush_epos\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua index 28e63b1770f..5ea72c7e3b3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/attr-col.lua @@ -114,12 +114,16 @@ local data = colors.data local values = colors.values local registered = colors.registered +local cmykrgbmode = 0 -- only for testing, already defined colors are not affected + local numbers = attributes.numbers local list = attributes.list registerstorage("attributes/colors/values", values, "attributes.colors.values") registerstorage("attributes/colors/registered", registered, "attributes.colors.registered") +directives.register("colors.cmykrgbmode", function(v) cmykrgbmode = tonumber(v) or 0 end) + local f_colors = { rgb = formatters["r:%s:%s:%s"], cmyk = formatters["c:%s:%s:%s:%s"], @@ -148,8 +152,11 @@ end local function cmyktorgb(c,m,y,k) if not c then return 0, 0, 0, 1 + elseif cmykrgbmode == 1 then + local d = 1.0 - k + return 1.0 - min(1.0,c*d+k), 1.0 - min(1.0,m*d+k), 1.0 - min(1.0,y*d+k) else - return 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k) + return 1.0 - min(1.0,c +k), 1.0 - min(1.0,m +k), 1.0 - min(1.0,y +k) end end @@ -295,7 +302,7 @@ function colors.spot(parent,f,d,p) local v = values[n] if v then -- the via cmyk hack is dirty, but it scales better - local c, m, y, k = p*v[6], p*v[7], p*v[8], p*v[8] + local c, m, y, k = p*v[6], p*v[7], p*v[8], p*v[9] local r, g, b = cmyktorgb(c,m,y,k) local s = cmyktogray(c,m,y,k) return { 5, s, r, g, b, c, m, y, k, parent, f, d, p } @@ -318,7 +325,7 @@ function colors.spot(parent,f,d,p) c = c + p*v[6] m = m + p*v[7] y = y + p*v[8] - k = k + p*v[8] + k = k + p*v[9] done = true end end @@ -361,10 +368,14 @@ local function reviver(data,n) local gray = graycolor(v[2]) d = { gray, gray, gray, gray } elseif model == 3 then - local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) + local gray = graycolor(v[2]) + local rgb = rgbcolor(v[3],v[4],v[5]) + local cmyk = cmykcolor(v[6],v[7],v[8],v[9]) d = { rgb, gray, rgb, cmyk } elseif model == 4 then - local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) + local gray = graycolor(v[2]) + local rgb = rgbcolor(v[3],v[4],v[5]) + local cmyk = cmykcolor(v[6],v[7],v[8],v[9]) d = { cmyk, gray, rgb, cmyk } elseif model == 5 then local spot = spotcolor(v[10],v[11],v[12],v[13]) @@ -406,10 +417,29 @@ function colors.setmodel(name,weightgray) weightgray = true end end - colors.model = name -- global, not useful that way - colors.default = models[name] or 1 -- global - colors.weightgray = weightgray -- global - return colors.default + local default = models[name] or 1 + + colors.model = name -- global, not useful that way + colors.default = default -- global + colors.weightgray = weightgray -- global + + -- avoid selective checking is no need for it + + local forced = colors.forced + + if forced == nil then + -- unset + colors.forced = default + elseif forced == false then + -- assumed mixed + elseif forced ~= default then + -- probably mixed + colors.forced = false + else + -- stil the same + end + + return default end function colors.register(name, colorspace, ...) -- passing 9 vars is faster (but not called that often) diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua index 67faa9fc0a9..dd971afc149 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.lua @@ -62,7 +62,7 @@ ranges of numbers for them. Of course a the end a private attri accessible too, so a private attribute can have a public appearance.

--ldx]]-- -sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127 -- very private (can become 15) +sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 15 -- very private sharedstorage.attributes_last_public = sharedstorage.attributes_last_public or 1024 -- less private function attributes.private(name) -- at the lua end (hidden from user) @@ -114,7 +114,8 @@ local function showlist(what,list) local a = list.next local i = 0 while a do - local number, value = a.number, a.value + local number = a.number + local value = a.value i = i + 1 report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number]) a = a.next diff --git a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv index d537cebfa5d..3792b1c6370 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/attr-ini.mkiv @@ -24,6 +24,7 @@ \installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd) \installcorenamespace{attributeid} % the internal number \installcorenamespace{attributestack} % the attribute specific stack +\installcorenamespace{attributepickup} \unexpanded\def\pushattribute#1% {\global\advance\csname\??attributestack\string#1\endcsname\plusone @@ -40,12 +41,15 @@ \newtoks \t_attr_list_global \newtoks \t_attr_list_local +\newtoks \t_attr_list_pickup \newtoks \t_attr_list_nomath \ifdefined \s!global \else \def\s!global {global} \fi % for metatex % or hard check later \ifdefined \s!public \else \def\s!public {public} \fi % for metatex % or hard check later \ifdefined \s!private \else \def\s!private {private} \fi % for metatex % or hard check later \ifdefined \s!attribute \else \def\s!attribute{attribute} \fi % for metatex % or hard check later +\ifdefined \s!pickup \else \def\s!pickup {pickup} \fi % for metatex % or hard check later +\ifdefined \s!forget \else \def\s!forget {forget} \fi % for metatex % or hard check later \unexpanded\def\defineattribute {\dodoubleempty\attr_basics_define} \unexpanded\def\definesystemattribute{\dodoubleempty\attr_basics_define_system} @@ -53,6 +57,8 @@ \def\attr_basics_define {\attr_basics_define_indeed\s!public} \def\attr_basics_define_system{\attr_basics_define_indeed\s!private} + % here public means 'visible' so it's not to be confused with 'public' at the lua end + \def\attr_basics_define_indeed#1[#2][#3]% {\ifcsname\??attributecount#2\endcsname\else \scratchcounter\clf_defineattribute{#2}{#1}\relax @@ -62,15 +68,33 @@ \csname\??attributeid#2\endcsname\scratchcounter % some attributes are always global \doifelseinset\s!global{#3}% - {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_global}% - {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_local }% + {\etoksapp\t_attr_list_global{\csname\??attributecount#2\endcsname\attributeunsetvalue}}% + {\etoksapp\t_attr_list_local {\csname\??attributecount#2\endcsname\attributeunsetvalue}}% \doifinset\s!nomath{#3}% - {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_nomath}% - % here public means 'visible' so it's not to be confused with 'public' at the lua end + {\etoksapp\t_attr_list_nomath{\csname\??attributecount#2\endcsname\attributeunsetvalue}}% \doifinset\s!public{#3}% {\expandafter\let\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}% + \doifinset\s!pickup{#3}% + {\expandafter\newconstant\csname\??attributepickup#2\endcsname + \csname\??attributepickup#2\endcsname\attributeunsetvalue + \etoksapp\t_attr_list_pickup{\csname\??attributecount#2\endcsname\csname\??attributepickup#2\endcsname}% + \ifcsname#2\s!attribute\endcsname + \expandafter\edef\csname\s!pickup#2\s!attribute\endcsname + {\csname\??attributepickup#2\endcsname\csname\??attributecount#2\endcsname}% + \expandafter\edef\csname\s!forget#2\s!attribute\endcsname + {\csname\??attributepickup#2\endcsname\attributeunsetvalue}% + \fi}% \fi} +\unexpanded\def\pickupattributes + {\the\t_attr_list_pickup\relax} + +% \unexpanded\def\pickupattribute#1% +% {\csname\??attributecount#1\endcsname\csname\??attributepickup#1\endcsname} + +% \unexpanded\def\pickupattributelater#1% +% {\csname\??attributepickup#1\endcsname\csname\??attributecount#1\endcsname} + \unexpanded\def\newattribute#1% {\attr_basics_define_indeed\s!public[\csstring#1][]% \expandafter\let\expandafter#1\csname\??attributeid\csstring#1\endcsname} @@ -84,8 +108,8 @@ \let\dompattribute\gobbletwoarguments -\unexpanded\def\resetglobalattributes{\the\t_attr_list_global} -\unexpanded\def\resetlocalattributes {\the\t_attr_list_local } +\unexpanded\def\resetglobalattributes{\the\t_attr_list_global\attribute\zerocount\zerocount} +\unexpanded\def\resetlocalattributes {\the\t_attr_list_local \attribute\zerocount\zerocount} \let\resetallattributes\resetlocalattributes diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua b/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua index b18679fa234..f5035d3cfab 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/back-exp.lua @@ -37,7 +37,7 @@ local next, type, tonumber = next, type, tonumber local sub, gsub = string.sub, string.gsub local validstring = string.valid local lpegmatch = lpeg.match -local utfchar, utfvalues = utf.char, utf.values +local utfchar, utfvalues, utflen = utf.char, utf.values, utf.len local concat, insert, remove, merge, sort = table.concat, table.insert, table.remove, table.merge, table.sort local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys local formatters = string.formatters @@ -46,6 +46,7 @@ local replacetemplate = utilities.templates.replace local trace_export = false trackers.register ("export.trace", function(v) trace_export = v end) local trace_spacing = false trackers.register ("export.trace.spacing", function(v) trace_spacing = v end) +local trace_detail = false trackers.register ("export.trace.detail", function(v) trace_detail = v end) local less_state = false directives.register("export.lessstate", function(v) less_state = v end) local show_comment = true directives.register("export.comment", function(v) show_comment = v end) @@ -67,6 +68,7 @@ local attributes = attributes local variables = interfaces.variables local v_yes = variables.yes local v_no = variables.no +local v_xml = variables.xml local v_hidden = variables.hidden local implement = interfaces.implement @@ -82,56 +84,8 @@ local fontchar = fonts.hashes.characters local fontquads = fonts.hashes.quads local languagenames = languages.numbers -local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes -local listcodes = nodes.listcodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local disc_code = nodecodes.disc - -local userskip_code = skipcodes.userskip -local rightskip_code = skipcodes.rightskip -local parfillskip_code = skipcodes.parfillskip -local spaceskip_code = skipcodes.spaceskip -local xspaceskip_code = skipcodes.xspaceskip - -local line_code = listcodes.line - local texgetcount = tex.getcount -local privateattribute = attributes.private -local a_characters = privateattribute('characters') -local a_exportstatus = privateattribute('exportstatus') -local a_tagged = privateattribute('tagged') -local a_taggedpar = privateattribute("taggedpar") -local a_image = privateattribute('image') -local a_reference = privateattribute('reference') -local a_textblock = privateattribute("textblock") - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getsubtype = nuts.getsubtype -local getfont = nuts.getfont -local getdisc = nuts.getdisc -local getcomponents = nuts.getcomponents -local getlist = nuts.getlist -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -- maybe use properties -local isglyph = nuts.isglyph -local getkern = nuts.getkern -local getwidth = nuts.getwidth - - -local traverse_id = nuts.traverse_id -local traverse_nodes = nuts.traverse - local references = structures.references local structurestags = structures.tags local taglist = structurestags.taglist @@ -167,7 +121,7 @@ local currentparagraph = nil local noftextblocks = 0 -local hyphencode = 0xAD +----- hyphencode = 0xAD local hyphen = utfchar(0xAD) -- todo: also emdash etc local tagsplitter = structurestags.patterns.splitter ----- colonsplitter = lpeg.splitat(":") @@ -554,6 +508,8 @@ do local fields = { "title", "subtitle", "author", "keywords", "url", "version" } + local ignoredelements = false + local function checkdocument(root) local data = root.data if data then @@ -580,6 +536,9 @@ do elseif tg == "ignore" then di.element = "" checkdocument(di) + elseif ignoredelements and ignoredelements[tg] then + di.element = "" + checkdocument(di) else checkdocument(di) -- new, else no noexport handling end @@ -609,6 +568,64 @@ do checkdocument(di) end + implement { + name = "ignoretagsinexport", + arguments = "string", + actions = function(list) + for tag in string.gmatch(list,"[a-z]+") do + if ignoredelements then + ignoredelements[tag] = true + else + ignoredelements = { [tag] = true } + end + end + end, + } + +end + +do + + local marginanchors = { } + local margincontent = { } + + implement { + name = "settagmargintext", + arguments = "integer", + actions = function(n) + marginanchors[locatedtag("margintext")] = n + end + } + + implement { + name = "settagmarginanchor", + arguments = "integer", + actions = function(n) + marginanchors[locatedtag("marginanchor")] = n + end + } + + function checks.margintext(di) + local i = marginanchors[di.fulltag] + margincontent[i] = di + end + + function checks.marginanchor(di) + local i = marginanchors[di.fulltag] + local d = margincontent[i] + -- + di.attribute = d.attribute + di.data = d.data + di.detail = d.detail + di.element = d.element + di.fulltag = d.fulltag + di.nature = d.nature + di.samepar = true + di.tg = d.tg + -- + d.skip = "ignore" + end + end do @@ -922,7 +939,8 @@ evaluators.special = function(di,var) end end -local referencehash = { } +local referencehash = { } +local destinationhash = { } do @@ -1040,10 +1058,37 @@ do end end + local function reference(di,element,n,fulltag) + local destination = destinationhash[fulltag] + if destination then + local d = structures.references.internals[destination] + if d then + addreference(di,d.references) + return true + else + return false + end + else + local data = di.data + if data then + for i=1,#data do + local di = data[i] + if di then + local fulltag = di.fulltag + if fulltag and reference(di,element,n,fulltag) then + return true + end + end + end + end + end + end + extras.adddestination = adddestination extras.addreference = addreference extras.link = link + extras.reference = reference end @@ -1243,22 +1288,21 @@ do } end if ndata == 0 then -root.skip = "comment" -- get rid of weird artefacts -root.nota = "weird" + root.skip = "comment" -- get rid of weird artefacts + root.nota = "weird" return elseif ndata == 1 then local d = data[1] if not d or d == "" then -root.skip = "comment" + root.skip = "comment" return elseif d.content then return else -- if ndata == 1 then local tg = d.tg --- if automathrows and roottg == "mrow" then -if automathrows and (roottg == "mrow" or roottg == "mtext") then + if automathrows and (roottg == "mrow" or roottg == "mtext") then -- maybe just always ! check spec first --- or we can have chesks.* for each as we then can flatten + -- or we can have chesks.* for each as we then can flatten if no_mrow[tg] then root.skip = "comment" end @@ -1670,10 +1714,10 @@ if automathrows and (roottg == "mrow" or roottg == "mtext") then end function checks.mrow(di) --- local d = di.data --- if d then --- checked(d) --- end + -- local d = di.data + -- if d then + -- checked(d) + -- end end -- we can move more checks here @@ -1758,6 +1802,25 @@ if automathrows and (roottg == "mrow" or roottg == "mtext") then end +do + + local registered = { } + + function structurestags.setformulacontent(n) + registered[locatedtag("formulacontent")] = { + n = n, + } + end + + function extras.formulacontent(di,element,n,fulltag) + local r = registered[fulltag] + if r then + setattribute(di,"n",r.n) + end + end + +end + do local registered = structures.sections.registered @@ -1861,7 +1924,7 @@ do end end - local function ignorebreaks(di,element,n,fulltag) + function extras.registerpages(di,element,n,fulltag) -- ignorebreaks local data = di.data for i=1,#data do local d = data[i] @@ -1871,7 +1934,7 @@ do end end - local function ignorespaces(di,element,n,fulltag) + function extras.registerseparator(di,element,n,fulltag) -- ignorespaces local data = di.data for i=1,#data do local d = data[i] @@ -1882,9 +1945,6 @@ do end end - extras.registerpages = ignorebreaks - extras.registerseparator = ignorespaces - end do @@ -1991,6 +2051,41 @@ do end +do + + local usedpublications = { } + local tagsindatasets = setmetatableindex("table") + local serialize = false + + function structurestags.setpublication(dataset,tag,rendering) + usedpublications[locatedtag("publication")] = { + dataset = dataset, + tag = tag, + rendering = rendering + } + tagsindatasets[dataset][tag] = true + if not serialize then + structures.tags.registerextradata("btx",function() + local t = { ""} + for dataset, used in sortedhash(tagsindatasets) do + t[#t+1] = publications.converttoxml(dataset,true,false,true,false,true,true) + end + t[#t+1] = "" + return concat(t,"\n") + end) + end + end + + function extras.publication(di,element,n,fulltag) + local hash = usedpublications[fulltag] + if hash then + setattribute(di,"dataset",hash.dataset) + setattribute(di,"tag",hash.tag) + end + end + +end + -- flusher do @@ -1998,7 +2093,7 @@ do local f_detail = formatters[' detail="%s"'] local f_chain = formatters[' chain="%s"'] local f_index = formatters[' n="%s"'] - local f_spacing = formatters['%s'] + local f_spacing = formatters['%s'] local f_empty_inline = formatters["<%s/>"] local f_empty_mixed = formatters["%w<%s/>\n"] @@ -2062,7 +2157,7 @@ do local depth = 0 local inline = 0 - local function emptytag(result,embedded,element,nature,di) -- currently only break but at some point + local function emptytag(result,element,nature,di) -- currently only break but at some point local a = di.attributes -- we might add detail etc if a then -- happens seldom if nature == "display" then @@ -2111,7 +2206,7 @@ do end end - local function begintag(result,embedded,element,nature,di,skip) + local function begintag(result,element,nature,di,skip) local index = di.n local fulltag = di.fulltag local specification = specifications[fulltag] or { } -- we can have a dummy @@ -2135,12 +2230,6 @@ do -- ignore else - -- if embedded then - -- if element == "math" then - -- embedded[f_tagid(element,index)] = #result+1 - -- end - -- end - local n = 0 local r = { } -- delay this if detail then @@ -2160,6 +2249,7 @@ do n = n + 1 r[n] = f_index(index) end + -- local extra = extras[element] if extra then extra(di,element,index,fulltag) @@ -2181,8 +2271,14 @@ do end local a = di.attributes if a then + if trace_spacing then + a.p = di.parnumber or 0 + end n = n + 1 r[n] = attributes(a) + elseif trace_spacing then + n = n + 1 + r[n] = attributes { p = di.parnumber or 0 } end if n == 0 then if nature == "inline" or inline > 0 then @@ -2249,7 +2345,7 @@ do end end - local function endtag(result,embedded,element,nature,di,skip) + local function endtag(result,element,nature,di,skip) if skip == "comment" then if show_comment then if nature == "display" and (inline == 0 or inline == 1) then @@ -2280,18 +2376,10 @@ do inline = inline - 1 result[#result+1] = f_end_inline(namespaced[element]) end - - -- if embedded then - -- if element == "math" then - -- local id = f_tagid(element,di.n) -- index) - -- local tx = concat(result,"",embedded[id],#result) - -- embedded[id] = "" .. "\n" .. tx - -- end - -- end end end - local function flushtree(result,embedded,data,nature) + local function flushtree(result,data,nature) local nofdata = #data for i=1,nofdata do local di = data[i] @@ -2323,23 +2411,23 @@ do if not element then -- skip elseif element == "break" then -- or element == "pagebreak" - emptytag(result,embedded,element,nature,di) + emptytag(result,element,nature,di) elseif element == "" or di.skip == "ignore" then -- skip else if di.before then - flushtree(result,embedded,di.before,nature) + flushtree(result,di.before,nature) end local natu = di.nature local skip = di.skip if di.breaknode then - emptytag(result,embedded,"break","display",di) + emptytag(result,"break","display",di) end - begintag(result,embedded,element,natu,di,skip) - flushtree(result,embedded,di.data,natu) - endtag(result,embedded,element,natu,di,skip) + begintag(result,element,natu,di,skip) + flushtree(result,di.data,natu) + endtag(result,element,natu,di,skip) if di.after then - flushtree(result,embedded,di.after,nature) + flushtree(result,di.after,nature) end end end @@ -2360,19 +2448,25 @@ do local di = data[i] if not di then -- skip + elseif di.skip == "ignore" then + -- skip (new) elseif di.content then - local parnumber = di.parnumber - if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then - nofnewdata = nofnewdata + 1 - if trace_spacing then - newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber } - else - newdata[nofnewdata] = makebreaknode() + if di.samepar then + prevparnumber = false + else + local parnumber = di.parnumber + if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then + nofnewdata = nofnewdata + 1 + if trace_spacing then + newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber } + else + newdata[nofnewdata] = makebreaknode() + end end + prevelement = nil + prevparnumber = parnumber end - prevelement = nil prevnature = "inline" - prevparnumber = parnumber nofnewdata = nofnewdata + 1 newdata[nofnewdata] = di elseif not di.collapsed then @@ -2383,39 +2477,51 @@ do end prevelement = element prevnature = "display" + nofnewdata = nofnewdata + 1 + newdata[nofnewdata] = di elseif element == "" or di.skip == "ignore" then -- skip + else + if di.samepar then + prevnature = "inline" + prevparnumber = false + else + local nature = di.nature + local parnumber = di.parnumber + if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then + nofnewdata = nofnewdata + 1 + if trace_spacing then + newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber } + else + newdata[nofnewdata] = makebreaknode() + end + end + prevnature = nature + prevparnumber = parnumber + end + prevelement = element + breaktree(di,tree,element) + nofnewdata = nofnewdata + 1 + newdata[nofnewdata] = di + end + else + if di.samepar then + prevnature = "inline" + prevparnumber = false else local nature = di.nature local parnumber = di.parnumber if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then nofnewdata = nofnewdata + 1 if trace_spacing then - newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber } + newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber } else newdata[nofnewdata] = makebreaknode() end end prevnature = nature prevparnumber = parnumber - prevelement = element - breaktree(di,tree,element) - end - nofnewdata = nofnewdata + 1 - newdata[nofnewdata] = di - else - local nature = di.nature - local parnumber = di.parnumber - if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then - nofnewdata = nofnewdata + 1 - if trace_spacing then - newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber } - else - newdata[nofnewdata] = makebreaknode() - end end - prevnature = nature - prevparnumber = parnumber nofnewdata = nofnewdata + 1 newdata[nofnewdata] = di end @@ -2447,6 +2553,8 @@ do local cd = currentdata[j] if not cd or cd == "" then -- skip + elseif cd.skip == "ignore" then + -- skip elseif cd.content then if not currentpar then -- add space ? @@ -2593,9 +2701,9 @@ local function pop() currentdepth = currentdepth - 1 if trace_export then if top then - report_export("%w",currentdepth,top) + report_export("%w",currentdepth,tree.tg) else - report_export("",top) + report_export("",tree.tg) end end else @@ -2701,7 +2809,7 @@ local function pushcontent(oldparagraph,newparagraph) local nd = #td td[nd+1] = { parnumber = oldparagraph or currentparagraph, content = content } if trace_export then - report_export("%w",currentdepth,#content) + report_export("%w",currentdepth,utflen(content)) report_export("%w%s",currentdepth,(gsub(content,"\n","\\n"))) report_export("%w",currentdepth) end @@ -2746,27 +2854,119 @@ end -- inserts ? -local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute) - local p - for n in traverse_nodes(head) do - local c, id = isglyph(n) -- 14: image, 8: literal (mp) - if c then - local at = getattr(n,a_tagged) or pat - if not at then - -- we need to tag the pagebody stuff as being valid skippable - -- - -- report_export("skipping character: %C (no attribute)",n.char) +local collectresults do -- too many locals otherwise + + local nodecodes = nodes.nodecodes + local gluecodes = nodes.gluecodes + local listcodes = nodes.listcodes + local whatsitcodes = nodes.whatsitcodes + + local subtypes = nodes.subtypes + + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local glyph_code = nodecodes.glyph + local glue_code = nodecodes.glue + local kern_code = nodecodes.kern + local disc_code = nodecodes.disc + local whatsit_code = nodecodes.whatsit + local localpar_code = nodecodes.localpar + + local userskip_code = gluecodes.userskip + local rightskip_code = gluecodes.rightskip + local parfillskip_code = gluecodes.parfillskip + local spaceskip_code = gluecodes.spaceskip + local xspaceskip_code = gluecodes.xspaceskip + + local linelist_code = listcodes.line + + local userdefinedwhatsit_code = whatsitcodes.userdefined + + local privateattribute = attributes.private + local a_image = privateattribute('image') + local a_reference = privateattribute('reference') + local a_destination = privateattribute('destination') + local a_characters = privateattribute('characters') + local a_exportstatus = privateattribute('exportstatus') + local a_tagged = privateattribute('tagged') + local a_taggedpar = privateattribute("taggedpar") + local a_textblock = privateattribute("textblock") + + local inline_mark = nodes.pool.userids["margins.inline"] + + local nuts = nodes.nuts + + local getnext = nuts.getnext + local getdisc = nuts.getdisc + local getlist = nuts.getlist + local getid = nuts.getid + local getattr = nuts.getattr + local setattr = nuts.setattr -- maybe use properties + local isglyph = nuts.isglyph + local getkern = nuts.getkern + local getwidth = nuts.getwidth + + local nexthlist = nuts.traversers.hlist + local nextnode = nuts.traversers.node + + local function addtomaybe(maybewrong,c,case) + if trace_export then + report_export("%w",currentdepth,c,case) + else + local s = formatters["%C"](c) + if maybewrong then + maybewrong[#maybewrong+1] = s else - -- we could add tonunicodes for ligatures (todo) - local components = getcomponents(n) - if components and (not characterdata[c] or overloads[c]) then -- we loose data - collectresults(components,nil,at) -- this assumes that components have the same attribute as the glyph ... we should be more tolerant (see math) + maybewrong = { s } + end + return maybewrong + end + end + + local function showmaybe(maybewrong) + if not trace_export then + report_export("fuzzy paragraph: % t",maybewrong) + end + end + + local function showdetail(n,id,subtype) + local a = getattr(n,a_tagged) + local t = taglist[a] + local c = nodecodes[id] + local s = subtypes[id][subtype] + if a and t then + report_export("node %a, subtype %a, tag %a, element %a, tree '% t'",c,s,a,t.tagname,t.taglist) + else + report_export("node %a, subtype %a, untagged",c,s) + end + end + + local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute) + local p + local localparagraph + local maybewrong + local pid + for n, id, subtype in nextnode, head do + if trace_detail then + showdetail(n,id,subtype) + end + if id == glyph_code then + local c, f = isglyph(n) + local at = getattr(n,a_tagged) or pat + if not at then + -- we need to tag the pagebody stuff as being valid skippable + -- + -- report_export("skipping character: %C (no attribute)",n.char) else if last ~= at then local tl = taglist[at] + local ap = getattr(n,a_taggedpar) or pap + if localparagraph and (not ap or ap < localparagraph) then + maybewrong = addtomaybe(maybewrong,c,1) + end pushcontent() - currentnesting = tl - currentparagraph = getattr(n,a_taggedpar) or pap + currentnesting = tl + currentparagraph = ap currentattribute = at last = at pushentry(currentnesting) @@ -2780,6 +2980,11 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c local t = tl.taglist referencehash[t[#t]] = r -- fulltag end + local d = getattr(n,a_destination) + if d then + local t = tl.taglist + destinationhash[t[#t]] = d -- fulltag + end -- elseif last then -- we can consider tagging the pars (lines) in the parbuilder but then we loose some @@ -2792,12 +2997,15 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c currentattribute = last currentparagraph = ap end + if localparagraph and (not ap or ap < localparagraph) then + maybewrong = addtomaybe(maybewrong,c,2) + end if trace_export then - report_export("%w",currentdepth,c,last) + report_export("%w",currentdepth,c,last) end else if trace_export then - report_export("%w",currentdepth,c,at) + report_export("%w",currentdepth,c,at) end end local s = getattr(n,a_exportstatus) @@ -2820,7 +3028,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c currentcontent[nofcurrentcontent] = " " end else - local fc = fontchar[getfont(n)] + local fc = fontchar[f] if fc then fc = fc and fc[c] if fc then @@ -2851,63 +3059,60 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c end end end - end - elseif id == disc_code then -- probably too late - local pre, post, replace = getdisc(n) - if keephyphens then - if pre and not getnext(pre) and isglyph(pre) == hyphencode then - nofcurrentcontent = nofcurrentcontent + 1 - currentcontent[nofcurrentcontent] = hyphen + elseif id == disc_code then -- probably too late + local pre, post, replace = getdisc(n) + if keephyphens then + if pre and not getnext(pre) and isglyph(pre) == 0xAD then -- hyphencode then + nofcurrentcontent = nofcurrentcontent + 1 + currentcontent[nofcurrentcontent] = hyphen + end end - end - if replace then - collectresults(replace,nil) - end - elseif id == glue_code then - -- we need to distinguish between hskips and vskips - local ca = getattr(n,a_characters) - if ca == 0 then - -- skip this one ... already converted special character (node-acc) - elseif ca then - local a = getattr(n,a_tagged) or pat - if a then - local c = specialspaces[ca] - if last ~= a then - local tl = taglist[a] - if trace_export then - report_export("%w",currentdepth,ca,a) - end - pushcontent() - currentnesting = tl - currentparagraph = getattr(n,a_taggedpar) or pap - currentattribute = a - last = a - pushentry(currentnesting) - -- no reference check (see above) - elseif last then - local ap = getattr(n,a_taggedpar) or pap - if ap ~= currentparagraph then - pushcontent(currentparagraph,ap) + if replace then + collectresults(replace,nil) + end + elseif id == glue_code then + -- we need to distinguish between hskips and vskips + local ca = getattr(n,a_characters) + if ca == 0 then + -- skip this one ... already converted special character (node-acc) + elseif ca then + local a = getattr(n,a_tagged) or pat + if a then + local c = specialspaces[ca] + if last ~= a then + local tl = taglist[a] + if trace_export then + report_export("%w",currentdepth,ca,a) + end + pushcontent() + currentnesting = tl + currentparagraph = getattr(n,a_taggedpar) or pap + currentattribute = a + last = a pushentry(currentnesting) - currentattribute = last - currentparagraph = ap - end - if trace_export then - report_export("%w",currentdepth,ca,last) + -- no reference check (see above) + elseif last then + local ap = getattr(n,a_taggedpar) or pap + if ap ~= currentparagraph then + pushcontent(currentparagraph,ap) + pushentry(currentnesting) + currentattribute = last + currentparagraph = ap + end + if trace_export then + report_export("%w",currentdepth,ca,last) + end end + -- if somespace[currentcontent[nofcurrentcontent]] then + -- if trace_export then + -- report_export("%w",currentdepth) + -- end + -- nofcurrentcontent = nofcurrentcontent - 1 + -- end + nofcurrentcontent = nofcurrentcontent + 1 + currentcontent[nofcurrentcontent] = c end - -- if somespace[currentcontent[nofcurrentcontent]] then - -- if trace_export then - -- report_export("%w",currentdepth) - -- end - -- nofcurrentcontent = nofcurrentcontent - 1 - -- end - nofcurrentcontent = nofcurrentcontent + 1 - currentcontent[nofcurrentcontent] = c - end - else - local subtype = getsubtype(n) - if subtype == userskip_code then + elseif subtype == userskip_code then if getwidth(n) > threshold then if last and not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) or pat @@ -2965,6 +3170,8 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c if not keephyphens then nofcurrentcontent = nofcurrentcontent - 1 end + elseif pid == disc_code then + -- go on .. tricky: we should mark the glyhs as coming from a disc elseif not somespace[r] then local a = getattr(n,a_tagged) or pat if a == last then @@ -2988,101 +3195,134 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c end end elseif subtype == parfillskip_code then - -- deal with paragaph endings (crossings) elsewhere and we quit here + -- deal with paragraph endings (crossings) elsewhere and we quit here -- as we don't want the rightskip space addition + if maybewrong then + showmaybe(maybewrong) + end return end - end - elseif id == hlist_code or id == vlist_code then - local ai = getattr(n,a_image) - if ai then - local at = getattr(n,a_tagged) or pat - if nofcurrentcontent > 0 then - pushcontent() - pushentry(currentnesting) -- ?? - end - pushentry(taglist[at]) -- has an index, todo: flag empty element - if trace_export then - report_export("%w",currentdepth,kern) + end + nofcurrentcontent = nofcurrentcontent + 1 + currentcontent[nofcurrentcontent] = " " + end + elseif a then + -- e.g LOGOLOGO + if trace_export then + report_export("%w",currentdepth,limit,last,a) + end + last = a + pushcontent() if trace_export then - report_export("%w",currentdepth,kern) + report_export("%w",currentdepth,kern) end nofcurrentcontent = nofcurrentcontent + 1 currentcontent[nofcurrentcontent] = " " + currentnesting = taglist[last] + pushentry(currentnesting) + currentattribute = last end - elseif a then - -- e.g LOGOLOGO - if trace_export then - report_export("%w",currentdepth,limit,last,a) - end - last = a - pushcontent() - if trace_export then - report_export("%w",currentdepth,kern) - end - nofcurrentcontent = nofcurrentcontent + 1 - currentcontent[nofcurrentcontent] = " " - currentnesting = taglist[last] - pushentry(currentnesting) - currentattribute = last end end end + elseif id == whatsit_code then + if subtype == userdefinedwhatsit_code then + -- similar to images, see above + local at = getattr(n,a_tagged) + if nofcurrentcontent > 0 then + pushcontent() + pushentry(currentnesting) -- ?? + end + pushentry(taglist[at]) + if trace_export then + report_export("%w",currentdepth) + function nodes.handlers.export(head) -- hooks into the page builder + starttiming(treehash) + if trace_export then + report_export("%w",currentdepth) + end + -- continueexport() + restart = true + collectresults(head) + if trace_export then + report_export("%w",currentdepth) + end + stoptiming(treehash) + return head end - -- continueexport() - restart = true - collectresults(tonut(head)) - if trace_export then - report_export("%w",currentdepth) + + function nodes.handlers.checkparcounter(p) + setattr(p,a_taggedpar,texgetcount("tagparcounter") + 1) + return p end - stoptiming(treehash) - return head, true -end -function builders.paragraphs.tag(head) - noftextblocks = noftextblocks + 1 - for n in traverse_id(hlist_code,tonut(head)) do - local subtype = getsubtype(n) - if subtype == line_code then - setattr(n,a_textblock,noftextblocks) - elseif subtype == glue_code or subtype == kern_code then -- no need to set fontkerns - setattr(n,a_textblock,0) + function builders.paragraphs.tag(head) + noftextblocks = noftextblocks + 1 + for n, subtype in nexthlist, head do + if subtype == linelist_code then + setattr(n,a_textblock,noftextblocks) + elseif subtype == glue_code or subtype == kern_code then -- no need to set fontkerns + setattr(n,a_textblock,0) + end end + return false end - return false + end do @@ -3237,13 +3477,12 @@ local htmltemplate = [[ local function allcontent(tree,embed) local result = { } - local embedded = embed and { } - flushtree(result,embedded,tree.data,"display") -- we need to collect images + flushtree(result,tree.data,"display") -- we need to collect images result = concat(result) -- no need to lpeg .. fast enough result = gsub(result,"\n *\n","\n") result = gsub(result,"\n +([^< ])","\n%1") - return result, embedded + return result end -- local xhtmlpreamble = [[ @@ -3498,7 +3737,6 @@ local htmltemplate = [[ local basename = file.basename local embedfile = false directives.register("export.embed",function(v) embedfile = v end) - local embedmath = false function structurestags.finishexport() @@ -3508,12 +3746,18 @@ local htmltemplate = [[ return end + local onlyxml = finetuning.export == v_xml + starttiming(treehash) -- finishexport() -- report_export("") - report_export("exporting xml, xhtml and html files") + if onlyxml then + report_export("exporting xml, no other files") + else + report_export("exporting xml, xhtml, html and css files") + end report_export("") -- wrapups.collapsetree(tree) @@ -3541,7 +3785,7 @@ local htmltemplate = [[ -- ./jobname-export/styles/jobname-images.css -- ./jobname-export/styles/jobname-templates.css - if type(askedname) ~= "string" or askedname == v_yes or askedname == "" then + if type(askedname) ~= "string" or askedname == "" then askedname = tex.jobname end @@ -3609,6 +3853,74 @@ local htmltemplate = [[ stylefilebase, } + local cssextra = cssfile and table.unique(settings_to_array(cssfile)) or { } + + -- at this point we're ready for the content; the collector also does some + -- housekeeping and data collecting; at this point we still have an xml + -- representation that uses verbose element names and carries information in + -- attributes + + local data = tree.data + for i=1,#data do + if data[i].tg ~= "document" then + data[i] = { } + end + end + + local result = allcontent(tree,embedmath) -- embedfile is for testing + + -- ugly but so be it: + + local extradata = structures.tags.getextradata() + if extradata then + local t = { "" } + t[#t+1] = "" + for name, action in sortedhash(extradata) do + t[#t+1] = action() + end + t[#t+1] = "" + t[#t+1] = "" + -- we use a function because otherwise we can have a bad capture index + result = gsub(result,"",function() + return concat(t,"\n") + end) + end + + -- done with ugly + + if onlyxml then + + os.remove(defaultfilename) + os.remove(imagefilename) + os.remove(stylefilename) + os.remove(templatefilename) + + for i=1,#cssextra do + os.remove(joinfile(stylepath,basename(source))) + end + + -- os.remove(xmlfilename) + + os.remove(imagefilename) + os.remove(stylefilename) + os.remove(templatefilename) + os.remove(xhtmlfilename) + os.remove(specificationfilename) + os.remove(htmlfilename) + + result = concat { + wholepreamble(true), + "\n", + result, + } + + report_export("saving xml data in %a",xmlfilename) + io.savedata(xmlfilename,result) + + return + + end + local examplefilename = resolvers.find_file("export-example.css") if examplefilename then local data = io.loaddata(examplefilename) @@ -3621,9 +3933,8 @@ local htmltemplate = [[ end if cssfile then - local list = table.unique(settings_to_array(cssfile)) - for i=1,#list do - local source = addsuffix(list[i],"css") + for i=1,#cssextra do + local source = addsuffix(cssextra[i],"css") local target = joinfile(stylepath,basename(source)) cssfiles[#cssfiles+1] = source if not lfs.isfile(source) then @@ -3638,21 +3949,6 @@ local htmltemplate = [[ local x_styles, h_styles = allusedstylesheets(cssfiles,files,"styles") - -- at this point we're ready for the content; the collector also does some - -- housekeeping and data collecting; at this point we still have an xml - -- representation that uses verbose element names and carries information in - -- attributes - - - local data = tree.data - for i=1,#data do - if data[i].tg ~= "document" then - data[i] = { } - end - end - - local result, embedded = allcontent(tree,embedmath) -- embedfile is for testing - local attach = backends.nodeinjections.attachfile if embedfile and attach then @@ -3666,22 +3962,6 @@ local htmltemplate = [[ mimetype = "application/mathml+xml", } end - -- if embedmath and attach then - -- local refs = { } - -- for k, v in sortedhash(embedded) do - -- attach { - -- data = v, - -- file = basename(k), - -- name = addsuffix(k,"xml"), - -- registered = k, - -- reference = k, - -- title = "xml export snippet: " .. k, - -- method = v_hidden, - -- mimetype = "application/mathml+xml", - -- } - -- refs[k] = 0 - -- end - -- end result = concat { wholepreamble(true), @@ -3711,14 +3991,14 @@ local htmltemplate = [[ local xmltree = cleanxhtmltree(xml.convert(result)) --- local xmltree = xml.convert(result) --- for c in xml.collected(xmltree,"m:mtext[lastindex()=1]/m:mrow") do --- print(c) --- end --- for c in xml.collected(xmltree,"mtext/mrow") do --- print(c) --- end --- local xmltree = cleanxhtmltree(xmltree) + -- local xmltree = xml.convert(result) + -- for c in xml.collected(xmltree,"m:mtext[lastindex()=1]/m:mrow") do + -- print(c) + -- end + -- for c in xml.collected(xmltree,"mtext/mrow") do + -- print(c) + -- end + -- local xmltree = cleanxhtmltree(xmltree) xml.save(xmltree,xhtmlfilename) @@ -3727,8 +4007,8 @@ local htmltemplate = [[ -- looking at identity is somewhat redundant as we also inherit from interaction -- at the tex end - local identity = interactions.general.getidentity() - local metadata = structures.tags.getmetadata() + local identity = interactions.general.getidentity() + local metadata = structures.tags.getmetadata() local specification = { name = usedname, @@ -3791,19 +4071,15 @@ local htmltemplate = [[ stoptiming(treehash) end - local appendaction = nodes.tasks.appendaction local enableaction = nodes.tasks.enableaction function structurestags.initializeexport() if not exporting then report_export("enabling export to xml") - -- not yet known in task-ini - appendaction("shipouts","normalizers", "nodes.handlers.export") - -- enableaction("shipouts","nodes.handlers.export") + enableaction("shipouts","nodes.handlers.export") enableaction("shipouts","nodes.handlers.accessibility") enableaction("math", "noads.handlers.tags") - -- appendaction("finalizers","lists","builders.paragraphs.tag") - -- enableaction("finalizers","builders.paragraphs.tag") + enableaction("everypar","nodes.handlers.checkparcounter") luatex.registerstopactions(structurestags.finishexport) exporting = true end @@ -3846,6 +4122,7 @@ implement { { "svgstyle" }, { "cssfile" }, { "file" }, + { "export" }, } } } @@ -3860,7 +4137,6 @@ implement { actions = structurestags.initializeexport, } - implement { name = "settagitemgroup", actions = structurestags.setitemgroup, @@ -3879,6 +4155,12 @@ implement { arguments = "2 strings", } +implement { + name = "settagformulacontent", + actions = structurestags.setformulacontent, + arguments = "integer", +} + implement { name = "settagdelimitedsymbol", actions = structurestags.settagdelimitedsymbol, @@ -3962,3 +4244,9 @@ implement { actions = structurestags.setlist, arguments = "integer" } + +implement { + name = "settagpublication", + actions = structurestags.setpublication, + arguments = "2 strings" +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv index ad5ba837121..03dbe709a97 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/back-exp.mkiv @@ -17,7 +17,7 @@ %D This is an experimental exporter and a logical follow up on tagging. The %D exporter assumes a properly tagged document. Some elements get a couple -%D of attributes becaus eitherwise rendering information would get lost. In +%D of attributes because otherwise rendering information would get lost. In %D general we assume that when the \XML\ is converted to \HTML\ some stylesheet %D is applied anyway. @@ -241,6 +241,27 @@ \let\specialcontrolspace \explicitcontrolspace \to \everyenableelements +\appendtoks + \unexpanded\def\dotagregisterformula#1% + {\iftrialtypesetting\else + \clf_settagformulacontent#1\relax + \fi}% +\to \everyenableelements + +\appendtoks + \unexpanded\def\dotagmarginanchor#1% + {\iftrialtypesetting\else\clf_settagmarginanchor#1\relax\fi}% + \unexpanded\def\dotagmargintext#1% + {\iftrialtypesetting\else\clf_settagmargintext#1\relax\fi}% +\to \everyenableelements + +\appendtoks + \unexpanded\def\dotagpublication#1#2% + {\iftrialtypesetting\else + \clf_settagpublication{#1}{#2}\relax + \fi}% +\to \everyenableelements + % The action: \setupbackend[export=yes] % or filename % maybe xhtml css settings will move to setupexport @@ -261,18 +282,18 @@ \c!author={\directinteractionparameter\c!author}, % \c!firstpage=, % imagename % \c!lastpage=, % imagename - \c!alternative=, % html, div \c!properties=\v!no, % no: ignore, yes: as attribute, otherwise: use as prefix \c!hyphen=\v!no, \c!svgstyle=, \c!cssfile=, - \c!file={\backendparameter\c!export}] % downward compatibility + \c!file=] \resetsystemmode\v!export \unexpanded\def\doinitializeexport {\edef\p_export{\backendparameter\c!export}% \ifx\p_export\empty \else + % yes | xml \setuptagging[\c!state=\v!start]% \clf_initializeexport \setsystemmode\v!export @@ -300,6 +321,7 @@ svgstyle {\exportparameter\c!svgstyle}% cssfile {\exportparameter\c!cssfile}% file {\exportparameter\c!file}% + export {\backendparameter\c!export}% \relax} \unexpanded\def\dostopexport diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua index fd33d5ddc84..b7af1529b71 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/back-ini.lua @@ -6,34 +6,46 @@ if not modules then modules = { } end modules ['back-ini'] = { license = "see context related readme files" } --- -- how to create a shortcut: --- --- local function something(...) --- something = backends.codeinjections.something --- return something(...) --- end - local next, type = next, type local format = string.format +local sind, cosd, abs = math.sind, math.cosd, math.abs +local insert, remove = table.insert, table.remove +local unpack = unpack backends = backends or { } local backends = backends local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end) + +local report = logs.reporter("backend") local report_backend = logs.reporter("backend","initializing") local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex local setaction = nodes.tasks.setaction -local function nothing() return nil end +local scanners = tokens.scanners +local scannumber = scanners.number +local scankeyword = scanners.keyword +local scancount = scanners.count +local scanstring = scanners.string -backends.nothing = nothing +local scanners = interfaces.scanners + +local implement = interfaces.implement -local nodeinjections = { } -local codeinjections = { } -local registrations = { } -local tables = allocate() +local texset = tex.set + +local nodeinjections = { } +local codeinjections = { } +local registrations = { } +local tables = allocate() + +local function nothing() + return nil +end + +backends.nothing = nothing local function donothing(t,k) t[k] = nothing @@ -60,6 +72,17 @@ backends.tables = { } setmetatableindex(backends.tables, tables backends.current = "unknown" +local lmtx_mode = nil + +local function lmtxmode() + if lmtx_mode == nil then + lmtx_mode = ((tonumber(CONTEXTLMTXMODE) or 0) > 0) and drivers and drivers.lmtxversion + end + return lmtx_mode +end + +codeinjections.lmtxmode = lmtxmode + function backends.install(what) if type(what) == "string" then local backend = backends[what] @@ -73,7 +96,8 @@ function backends.install(what) end backends.current = what for category, default in next, defaults do - local target, plugin = backends[category], backend[category] + local target = backends[category] + local plugin = backend [category] setmetatableindex(plugin, default) setmetatableindex(target, plugin) end @@ -86,7 +110,13 @@ end statistics.register("used backend", function() local bc = backends.current if bc ~= "unknown" then - return format("%s (%s)",bc,backends[bc].comment or "no comment") + local lmtx = lmtxmode() + local cmnt = backends[bc].comment or "no comment" + if lmtx then + return format("lmtx version %0.2f, %s (%s)",lmtx,bc,cmnt) + else + return format("%s (%s)",bc,cmnt) + end else return nil end @@ -103,14 +133,6 @@ tables.vfspecials = allocate { stopslant = comment, } --- we'd better have this return something (defaults) - -function codeinjections.getpos () return 0, 0 end -function codeinjections.gethpos () return 0 end -function codeinjections.getvpos () return 0 end -function codeinjections.hasmatrix() return false end -function codeinjections.getmatrix() return 1, 0, 0, 1, 0, 0 end - -- can best be here interfaces.implement { @@ -139,3 +161,156 @@ backends.included = included function backends.timestamp() return os.date("%Y-%m-%dT%X") .. os.timezone(true) end + +-- Also here: + +local paper_width = 0 +local paper_height = 0 + +function codeinjections.setpagedimensions(paperwidth,paperheight) + if paperwidth then + paper_width = paperwidth + end + if paperheight then + paper_height = paperheight + end + if not lmtxmode() then + texset("global","pageheight",paper_height) + texset("global","pagewidth", paper_width) + end + return paper_width, paper_height +end + +function codeinjections.getpagedimensions() + return paper_width, paper_height +end + +implement { + name = "shipoutoffset", + actions = function() + context(lmtxmode() and "0pt" or "-1in") -- the old tex offset + end +} + +-- could also be codeinjections + +function backends.noflatelua() + return status.late_callbacks or 0 +end + +-- + +local stack = { } +local restore = true -- false + +local nodepool = nodes.pool +local savenode = nodepool.save +local restorenode = nodepool.restore +local setmatrixnode = nodepool.setmatrix + +updaters.register("backend.update",function() + savenode = nodepool.save + restorenode = nodepool.restore + setmatrixnode = nodepool.setmatrix +end) + +local function stopsomething() + local top = remove(stack) + if top == false then + -- not wrapped + elseif top == true then + context(restorenode()) + elseif top then + context(setmatrixnode(unpack(top))) -- not really needed anymore + context(restorenode()) + else + -- nesting error + end +end + +local function startrotation() + local a = scannumber() + if a == 0 then + insert(stack,false) + else + local s, c = sind(a), cosd(a) + if abs(s) < 0.000001 then + s = 0 -- otherwise funny -0.00000 + end + if abs(c) < 0.000001 then + c = 0 -- otherwise funny -0.00000 + end + context(savenode()) + context(setmatrixnode(c,s,-s,c)) + insert(stack,restore and { c, -s, s, c } or true) + end +end + +implement { name = "startrotation", actions = startrotation } +implement { name = "stoprotation", actions = stopsomething } + +local function startscaling() -- at the tex end we use sx and sy instead of rx and ry + local rx, ry = 1, 1 + while true do + if scankeyword("rx") then + rx = scannumber() + elseif scankeyword("ry") then + ry = scannumber() + -- elseif scankeyword("revert") then + -- local top = stack[#stack] + -- if top then + -- rx = top[1] + -- ry = top[4] + -- else + -- rx = 1 + -- ry = 1 + -- end + else + break + end + end + if rx == 1 and ry == 1 then + insert(stack,false) + else + if rx == 0 then + rx = 0.0001 + end + if ry == 0 then + ry = 0.0001 + end + context(savenode()) + context(setmatrixnode(rx,0,0,ry)) + insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true) + end +end + +implement { name = "startscaling", actions = startscaling } +implement { name = "stopscaling", actions = stopsomething } + +local function startmatrix() -- rx sx sy ry -- tx, ty + local rx, sx, sy, ry = 1, 0, 0, 1 + while true do + if scankeyword("rx") then rx = scannumber() + elseif scankeyword("ry") then ry = scannumber() + elseif scankeyword("sx") then sx = scannumber() + elseif scankeyword("sy") then sy = scannumber() + else break end + end + if rx == 1 and sx == 0 and sy == 0 and ry == 1 then + insert(stack,false) + else + context(savenode()) + context(setmatrixnode(rx,sx,sy,ry)) + insert(stack,store and { -rx, -sx, -sy, -ry } or true) + end +end + +implement { name = "startmatrix", actions = startmatrix } +implement { name = "stopmatrix", actions = stopsomething } + +local function startmirroring() + context(setmatrixnode(-1,0,0,1)) +end + +implement { name = "startmirroring", actions = startmirroring } +implement { name = "stopmirroring", actions = startmirroring } -- not: stopsomething diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv index e810ecde554..8729403f848 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/back-ini.mkiv @@ -16,10 +16,23 @@ \writestatus{loading}{ConTeXt Backend Macros / Initialization} +%D The exact page model depends on the backend so we just define some +%D variables that are used. A helper at the \LUA\ end will synchronize +%D with the internal variables. We store these in the format. + +% \newdimen\backendpageheight +% \newdimen\backendpagewidth +% \newdimen\backendinchoffset \backendinchoffset=1in + +%D Now we load the \LUA\ code: + \registerctxluafile{back-ini}{} +\registerctxluafile{back-res}{} -%D We currently have a curious mix between tex and lua backend -%D handling but eventually most will move to lua. +\doifelsefileexists{back-out.mkiv}{\loadmarkfile{back-out}}{} + +%D We currently have a curious mix between tex and lua backend handling but +%D eventually most will move to \LUA. \unprotect @@ -27,54 +40,84 @@ \ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi \ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi % e.g. finalize via latelua -%D Right from the start \CONTEXT\ had a backend system based on -%D runtime pluggable code. As most backend issues involved specials -%D and since postprocessors had not that much in common, we ended up -%D with a system where we could switch backend as well as output code -%D for multiple backends at the same time. +%D Right from the start \CONTEXT\ had a backend system based on runtime pluggable +%D code. As most backend issues involved specials and since postprocessors had not +%D that much in common, we ended up with a system where we could switch backend as +%D well as output code for multiple backends at the same time. %D -%D Because \LUATEX\ has the backend built in, and since some backend -%D issues have been moved to the frontend I decided to provide new -%D backend code for \MKIV, starting with what was actually used. +%D Because \LUATEX\ has the backend built in, and since some backend issues have +%D been moved to the frontend I decided to provide new backend code for \MKIV, +%D starting with what was actually used. %D -%D At this moment \DVI\ is no longer used for advanced document -%D output and we therefore dropped support for this format. Future -%D versions might support more backends again, but this has a low -%D priority. +%D At this moment \DVI\ is no longer used for advanced document output and we +%D therefore dropped support for this format. Future versions might support more +%D backends again, but this has a low priority. %D -%D Not everything here makes sense and the content of this file will -%D definitely change (or even go away). +%D Not everything here makes sense and the content of this file will definitely +%D change (or even go away). + +% rotation + +\unexpanded\def\dostartrotation#1% + {\forcecolorhack + \clf_startrotation#1\relax} % todo: implement without Q q + +\unexpanded\def\dostoprotation + {\clf_stoprotation + \forcecolorhack} + +% scaling + +\unexpanded\def\dostartscaling#1#2% + {\forcecolorhack + \clf_startscaling rx #1 ry #2\relax} -\let \dostartrotation \gobbleoneargument -\let \dostoprotation \donothing -\let \dostartscaling \gobbletwoarguments -\let \dostopscaling \donothing -\let \dostartmirroring \donothing -\let \dostopmirroring \donothing -\let \dotransformnextbox\gobblesixarguments % and pass last box +\unexpanded\def\dostopscaling + {\clf_stopscaling + \forcecolorhack} + +% mirroring + +\unexpanded\def\dostartmirroring + {\clf_startmirroring} + +\unexpanded\def\dostopmirroring + {\clf_stopmirroring} + +% transform + +\unexpanded\def\dotransformnextbox#1#2#3#4#5#6% + {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} + +\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% + {\hpack + {\kern #5\onebasepoint + \raise#6\onebasepoint + \hpack + {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax + \box\nextbox + \clf_stopmatrix}}} %D \macros %D {back_ovalbox} %D -%D When we look at the implementation, this is a complicated -%D one. There are seven arguments. +%D When we look at the implementation, this is a complicated one. There are seven +%D arguments. %D %D \starttyping %D \back_ovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant} %D \stoptyping %D -%D This command has to return a \type{\vbox} which can be used -%D to lay over another one (with text). The radius is in -%D degrees, the stroke and fill are~\type{1} (true) of~\type{0} -%D (false). +%D This command has to return a \type {\vbox} which can be used to lay over another +%D one (with text). The radius is in degrees, the stroke and fill are~\type {1} +%D (true) of~\type {0} (false). \let\back_ovalbox \gobbleeightarguments %D \macros %D {dostartclipping,dostopclipping} %D -%D Clipping is implemented in such a way that an arbitrary code -%D can be fed. +%D Clipping is implemented in such a way that an arbitrary code can be fed. %D %D \starttyping %D \dostartclipping {pathname} {width} {height} @@ -87,9 +130,8 @@ %D \macros %D {jobsuffix} %D -%D By default, \TEX\ produces \DVI\ files which can be -%D converted to other filetypes. Sometimes it is handy to -%D know what the target file will be. In other driver +%D By default, \TEX\ produces \DVI\ files which can be converted to other filetypes. +%D Sometimes it is handy to know what the target file will be. In other driver %D modules we wil set \type {\jobsuffix} to \type {pdf}. %D Backend configuration: @@ -113,6 +155,12 @@ \clf_setrealspaces{\backendparameter\c!space}% \to \everysetupbackend +\appendtoks + \ifdefined\clf_resetmapfile + \clf_resetmapfile + \fi +\to \everysetupbackend + %D For older styles: \let\setupoutput\gobbleoneoptional diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua index f45783e5101..8886967e0c5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.lua @@ -6,302 +6,21 @@ if not modules then modules = { } end modules ['back-pdf'] = { license = "see context related readme files" } --- we could do \pdfmatrix sx <> sy <> etc +-- We hide the pdf table from users so that we can guarantee no interference with +-- the way we manage resources, info, etc. Users should use the \type {lpdf} +-- interface instead. If needed I will provide replacement functionality. -local sind, cosd = math.sind, math.cosd -local insert, remove = table.insert, table.remove - -local codeinjections = backends.pdf.codeinjections - -local context = context - -local scanners = tokens.scanners -local scannumber = scanners.number -local scankeyword = scanners.keyword -local scandimen = scanners.dimen -local scancount = scanners.count -local scanstring = scanners.string - -local scanners = interfaces.scanners -local implement = interfaces.implement - -local report = logs.reporter("backend") - -local outputfilename - -function codeinjections.getoutputfilename() - if not outputfilename then - outputfilename = file.addsuffix(tex.jobname,"pdf") - end - return outputfilename -end - -backends.install("pdf") - -local f_matrix = string.formatters["%F %F %F %F"] -- 0.8 is default - -scanners.pdfrotation = function() -- a - -- todo: check for 1 and 0 and flush sparse - local a = scannumber() - local s, c = sind(a), cosd(a) - context(f_matrix(c,s,-s,c)) -end - --- experimental code (somewhat weird here) .. todo: nodeinjections .. this will only work --- out well if we also calculate the accumulated cm and wrap inclusions / annotations in --- the accumulated ... it's a mess --- --- we could also do the save restore wrapping here + colorhack - -local pdfsave = nodes.pool.pdfsave -local pdfrestore = nodes.pool.pdfrestore -local pdfsetmatrix = nodes.pool.pdfsetmatrix - -local stack = { } -local restore = true -- false - -scanners.pdfstartrotation = function() - local a = scannumber() - if a == 0 then - insert(stack,false) - else - local s, c = sind(a), cosd(a) - context(pdfsave()) - context(pdfsetmatrix(c,s,-s,c)) - insert(stack,restore and { c, -s, s, c } or true) - end -end - -scanners.pdfstartscaling = function() -- at the tex end we use sx and sy instead of rx and ry - local rx, ry = 1, 1 - while true do - if scankeyword("rx") then - rx = scannumber() - elseif scankeyword("ry") then - ry = scannumber() - -- elseif scankeyword("revert") then - -- local top = stack[#stack] - -- if top then - -- rx = top[1] - -- ry = top[4] - -- else - -- rx = 1 - -- ry = 1 - -- end - else - break - end - end - if rx == 1 and ry == 1 then - insert(stack,false) - else - if rx == 0 then - rx = 0.0001 - end - if ry == 0 then - ry = 0.0001 - end - context(pdfsave()) - context(pdfsetmatrix(rx,0,0,ry)) - insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true) - end -end - -scanners.pdfstartmatrix = function() -- rx sx sy ry -- tx, ty - local rx, sx, sy, ry = 1, 0, 0, 1 - while true do - if scankeyword("rx") then rx = scannumber() - elseif scankeyword("ry") then ry = scannumber() - elseif scankeyword("sx") then sx = scannumber() - elseif scankeyword("sy") then sy = scannumber() - else break end - end - if rx == 1 and sx == 0 and sy == 0 and ry == 1 then - insert(stack,false) - else - context(pdfsave()) - context(pdfsetmatrix(rx,sx,sy,ry)) - insert(stack,store and { -rx, -sx, -sy, -ry } or true) - end -end - -local function pdfstopsomething() - local top = remove(stack) - if top == false then - -- not wrapped - elseif top == true then - context(pdfrestore()) - elseif top then - context(pdfsetmatrix(unpack(top))) -- not really needed anymore - context(pdfrestore()) - else - -- nesting error - end -end - -scanners.pdfstoprotation = pdfstopsomething -scanners.pdfstopscaling = pdfstopsomething -scanners.pdfstopmatrix = pdfstopsomething - -scanners.pdfstartmirroring = function() - context(pdfsetmatrix(-1,0,0,1)) -end - -if environment.arguments.nocompression then - lpdf.setcompression(0,0,true) -end - -scanners.pdfstopmirroring = scanners.pdfstartmirroring - --- todo, change the above to implement too -- - -implement { - name = "setmapfile", - arguments = "string", - actions = pdf.mapfile -} - -implement { - name = "setmapline", - arguments = "string", - actions = pdf.mapline -} - -implement { +interfaces.implement { name = "setpdfcompression", arguments = { "integer", "integer" }, actions = lpdf.setcompression, } -local report = logs.reporter("backend","pdftex primitives") -local trace = false - -scanners.pdfannot = function() - if scankeyword("reserveobjectnum") then - report("\\pdfannot reserveobjectnum is not (yet) supported") - -- if trace then - -- report() - -- report("\\pdfannot: reserved number (not supported yet)") - -- report() - -- end - else - local width = false - local height = false - local depth = false - local data = false - local object = false - local attr = false - -- - if scankeyword("useobjnum") then - object = scancount() - report("\\pdfannot useobjectnum is not (yet) supported") - end - while true do - if scankeyword("width") then - width = scandimen() - elseif scankeyword("height") then - height = scandimen() - elseif scankeyword("depth") then - depth = scandimen() - else - break - end - end - if scankeyword("attr") then - attr = scanstring() - end - data = scanstring() - -- - -- less strict variant: - -- - -- while true do - -- if scankeyword("width") then - -- width = scandimen() - -- elseif scankeyword("height") then - -- height = scandimen() - -- elseif scankeyword("depth") then - -- depth = scandimen() - -- elseif scankeyword("useobjnum") then - -- object = scancount() - -- elseif scankeyword("attr") then - -- attr = scanstring() - -- else - -- data = scanstring() - -- break - -- end - -- end - -- - -- if trace then - -- report() - -- report("\\pdfannot:") - -- report() - -- report(" object: %s",object or " (not supported yet)") - -- report(" width : %p",width or "") - -- report(" height: %p",height or "") - -- report(" depth : %p",depth or "") - -- report(" attr : %s",attr or "") - -- report(" data : %s",data or "") - -- report() - -- end - context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or "")) - end +if CONTEXTLMTXMODE == 0 then + updaters.apply("backend.update.pdf") + updaters.apply("backend.update.lpdf") + updaters.apply("backend.update.tex") + updaters.apply("backend.update") end -scanners.pdfdest = function() - local name = false - local zoom = false - local view = false - local width = false - local height = false - local depth = false - if scankeyword("num") then - report("\\pdfdest num is not (yet) supported") - elseif scankeyword("name") then - name = scanstring() - end - if scankeyword("xyz") then - view = "xyz" - if scankeyword("zoom") then - report("\\pdfdest zoom is ignored") - zoom = scancount() -- will be divided by 1000 in the backend - end - elseif scankeyword("fitbh") then - view = "fitbh" - elseif scankeyword("fitbv") then - view = "fitbv" - elseif scankeyword("fitb") then - view = "fitb" - elseif scankeyword("fith") then - view = "fith" - elseif scankeyword("fitv") then - view = "fitv" - elseif scankeyword("fitr") then - view = "fitr" - while true do - if scankeyword("width") then - width = scandimen() - elseif scankeyword("height") then - height = scandimen() - elseif scankeyword("depth") then - depth = scandimen() - else - break - end - end - elseif scankeyword("fit") then - view = "fit" - end - -- if trace then - -- report() - -- report("\\pdfdest:") - -- report() - -- report(" name : %s",name or "") - -- report(" view : %s",view or "") - -- report(" zoom : %s",zoom or " (not supported)") - -- report(" width : %p",width or "") - -- report(" height: %p",height or "") - -- report(" depth : %p",depth or "") - -- report() - -- end - context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit")) -end +backends.install("pdf") diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv index 3b0dd78520a..9e88ab19399 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdf.mkiv @@ -11,11 +11,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D The less ther ei shere, the better. +%D The less there is here, the better. \writestatus{loading}{ConTeXt Backend Macros / PDF} -%registerctxluafile{lpdf-aux}{optimize} % common helpers \registerctxluafile{lpdf-ini}{optimize} \registerctxluafile{lpdf-nod}{} \registerctxluafile{lpdf-col}{} @@ -32,9 +31,22 @@ \registerctxluafile{lpdf-swf}{} % this will become a module \registerctxluafile{lpdf-tag}{} \registerctxluafile{lpdf-fmt}{} -\registerctxluafile{lpdf-epd}{} +\registerctxluafile{lpdf-pde}{} + +\ifcase\contextlmtxmode\else + \registerctxluafile{lpdf-img}{optimize} +\fi + \registerctxluafile{lpdf-epa}{} +\ifcase\contextlmtxmode\else + \registerctxluafile{lpdf-emb}{optimize} +\fi + +\registerctxluafile{back-pdp}{} + +\registerctxluafile{lpdf-fnt}{} + \registerctxluafile{back-pdf}{} % some code will move to lpdf-* \loadmarkfile{back-u3d} % this will become a module @@ -47,26 +59,53 @@ %D %D Here we initialize some internal quantities. We also protect them. -\outputmode\plusone \let\outputmode\relax \newcount\outputmode \outputmode\plusone +\ifdefined\outputmode + \outputmode\plusone + \let\outputmode\relax + \newcount\outputmode + \outputmode\plusone + \let\normaloutputmode\outputmode +\fi %D Because we do a lot in \LUA\ and don't want interferences, we nil most of the %D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable}, %D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably %D have bad side effects. +%D For the moment we put these here as they are pdf related but they might move to +%D a better place. We overload the primitives with our own but use a bit of indirection +%D for the purpose of tracing. + +\unexpanded\def\saveboxresource {\clf_saveboxresource} +\unexpanded\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax} +\unexpanded\def\useboxresource {\clf_useboxresource} + +\unexpanded\def\saveimageresource {\clf_saveimageresource} +\unexpanded\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax} +\unexpanded\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax} +\unexpanded\def\useimageresource {\clf_useimageresource} + +\unexpanded\def\savepos {\clf_savepos} + \def\lastxpos {\clf_lastxpos} + \def\lastypos {\clf_lastypos} + +\unexpanded\def\pdfextension {\clf_pdfextension} + \def\pdffeedback {\clf_pdffeedback} + %D These are no-ops and don't even intercept what comes next. Maybe some day %D I'll write a parser that maps onto \CONTEXT. \unexpanded\def\unsupportedpdfprimitive#1% - {\writestatus{error}{the primitive \string#1\space is not supported}} + {\writestatus{fatal error}{the primitive \string#1\space is not supported}% + \directlua{os.exit()}} \unexpanded\def\pdfcolorstack {\unsupportedpdfprimitive\pdfcolorstack} \unexpanded\def\pdfcolorstackinit{\unsupportedpdfprimitive\pdfcolorstackinit} -%unexpanded\def\pdfannot {\unsupportedpdfprimitive\pdfannot} +% pdfannot \unexpanded\def\pdfstartlink {\unsupportedpdfprimitive\pdfstartlink} \unexpanded\def\pdfendlink {\unsupportedpdfprimitive\pdfendlink} \unexpanded\def\pdfoutline {\unsupportedpdfprimitive\pdfoutline} -%unexpanded\def\pdfdest {\unsupportedpdfprimitive\pdfdest} +% pdfdest \unexpanded\def\pdfthread {\unsupportedpdfprimitive\pdfthread} \unexpanded\def\pdfstartthread {\unsupportedpdfprimitive\pdfstartthread} \unexpanded\def\pdfendthread {\unsupportedpdfprimitive\pdfendthread} @@ -97,23 +136,24 @@ %D But we still provide: -\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} -\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } -\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} +\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} +\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} +\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } +\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} %D These might even become no-ops as we don't need them in \CONTEXT: -\unexpanded\def\pdfmapfile#1{\clf_setmapfile{#1}} -\unexpanded\def\pdfmapline#1{\clf_setmapline{#1}} +\unexpanded\def\pdfmapfile#1{} % obsolete +\unexpanded\def\pdfmapline#1{} % obsolete %D We don't support these directives, at least not this way. If they are needed %D by third party modules we can provide some interface. -% \pdfcreationdate +%pdfcreationdate \let\pdfdecimaldigits \relax \newcount\pdfdecimaldigits \let\pdfdestmargin \relax \newdimen\pdfdestmargin -% \pdffontname -% \pdffontobjnum +% pdffontname +% pdffontobjnum \let\pdffontsize \relax \newcount\pdffontsize \let\pdfgamma \relax \newcount\pdfgamma \let\pdfgentounicode \relax \newcount\pdfgentounicode @@ -128,21 +168,21 @@ \let\pdfinclusioncopyfonts \relax \newcount\pdfinclusioncopyfonts \let\pdfinclusionerrorlevel \relax \newcount\pdfinclusionerrorlevel \let\pdfinfoomitdate \relax \newcount\pdfinfoomitdate -% \pdflastannot -% \pdflastlink +% pdflastannot +% pdflastlink \let\pdflinkmargin \relax \newdimen\pdflinkmargin \let\pdfmajorversion \relax \newcount\pdfmajorversion \let\pdfminorversion \relax \newcount\pdfminorversion \let\pdfpagebox \relax \newcount\pdfpagebox -% \pdfpageref +% pdfpageref \let\pdfpkfixeddpi \relax \newcount\pdfpkfixeddpi \let\pdfpkmode \relax \newtoks \pdfpkmode \let\pdfpkresolution \relax \newcount\pdfpkresolution -% \pdfretval +% pdfretval \let\pdfsuppressoptionalinfo \relax \newcount\pdfsuppressoptionalinfo \let\pdfsuppressptexinfo \relax \newcount\pdfsuppressptexinfo -% \pdftexrevision -% \pdftexversion +% pdftexrevision +% pdftexversion \let\pdfthreadmargin \relax \newdimen\pdfthreadmargin \let\pdftrailerid \relax \newtoks \pdftrailerid \let\pdfuniqueresname \relax \newcount\pdfuniqueresname @@ -152,27 +192,33 @@ %D These are still accepted but are normally not needed. +\let\pdfxform \saveboxresource +\let\pdfximage \saveimageresource + \let\pdflastxform \lastsavedboxresourceindex \let\pdflastximage \lastsavedimageresourceindex -\let\pdflastximagepages \lastsavedimageresourcepages -\let\pdflastxpos \lastxpos -\let\pdflastypos \lastypos + \let\pdfrefxform \useboxresource \let\pdfrefximage \useimageresource + +\let\pdflastximagepages \lastsavedimageresourcepages + \let\pdfsavepos \savepos -\let\pdfxform \saveboxresource -\let\pdfximage \saveimageresource +\let\pdflastxpos \lastxpos +\let\pdflastypos \lastypos %D For the moment we keep these as they are but they will become \LUA\ calls %D eventually, after which we will nil the three \type {\pdf} interface primitives. -\normalprotected\def\pdfliteral {\pdfextension literal } -\normalprotected\def\pdfobj {\pdfextension obj } - \def\pdflastobj {\numexpr\pdffeedback lastobj\relax} +\normalprotected\def\pdfliteral {\clf_pdfliteral}% + +\normalprotected\def\pdfobj {\clf_pdfobj}% +\normalprotected\def\pdflastobj {\numexpr\clf_pdflastobj\relax}% + \normalprotected\def\pdfrefobj {\pdfextension refobj } -\normalprotected\def\pdfrestore {\pdfextension restore\relax} -\normalprotected\def\pdfsave {\pdfextension save\relax} -\normalprotected\def\pdfsetmatrix{\pdfextension setmatrix } +\normalprotected\def\pdfrestore {\clf_restore} +\normalprotected\def\pdfsave {\clf_save} +\normalprotected\def\pdfsetmatrix{\clf_setmatrix} %D This one can be consulted by users although the suffix is also a system mode. @@ -225,84 +271,6 @@ \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} \let\PDFcolor\pdfcolor -%D Transformations - -% rotation - -\unexpanded\def\dostartrotation#1% - {\forcecolorhack - \clf_pdfstartrotation#1\relax} % todo: implement without Q q - -\unexpanded\def\dostoprotation - {\clf_pdfstoprotation - \forcecolorhack} - -% scaling - -\unexpanded\def\dostartscaling#1#2% - {\forcecolorhack - \clf_pdfstartscaling rx #1 ry #2\relax} - -\unexpanded\def\dostopscaling - {\clf_pdfstopscaling - \forcecolorhack} - -% mirroring - -\unexpanded\def\dostartmirroring - {\clf_pdfstartmirroring} - -\unexpanded\def\dostopmirroring - {\clf_pdfstopmirroring} - -% transform - -\unexpanded\def\dotransformnextbox#1#2#3#4#5#6% - {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} - -\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% - {\hpack - {\kern #5\onebasepoint - \raise#6\onebasepoint - \hpack - {\clf_pdfstartmatrix rx #1 sx #2 sy #3 ry #4\relax - \box\nextbox - \clf_pdfstopmatrix}}} - -% somehow the shift is not happening .. bug in luatex? -% -% \unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% -% {\ctxcommand{pdftransformbox(\number\nextbox,#1,#2,#3,#4,\number\dimexpr#5\onebasepoint,\number\dimexpr#6\onebasepoint)}% -% \box\nextbox} -% -% \startluacode -% function commands.pdftransformbox(box,rx,sx,sy,ry,tx,ty) -% if rx == 1 and sx == 0 and sy == 0 and ry == 1 then -% if tx == 0 and ty == 0 then -% local b = nodes.hpack(nodes.concat { -% nodes.pool.kern(tx), -% nodes.takebox(box), -% }) -% b.shift = -ty -% tex.setbox(box,b) -% else -% -- no need to transform -% end -% else -% local b = nodes.hpack(nodes.concat { -% nodes.pool.kern(tx), -% nodes.pool.pdfsave(), -% nodes.pool.pdfsetmatrix(rx,sx,sy,ry), -% nodes.takebox(box), -% nodes.pool.pdfsetmatrix(-rx,-sx,-sy,-ry), -% nodes.pool.pdfrestore(), -% }) -% b.shift = -ty -% tex.setbox(box,b) -% end -% end -% \stopluacode - % clipping \unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-pdp.lua b/Master/texmf-dist/tex/context/base/mkiv/back-pdp.lua new file mode 100644 index 00000000000..7363cfcae4d --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/back-pdp.lua @@ -0,0 +1,453 @@ +if not modules then modules = { } end modules ['back-pdp'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is temporary ... awaiting a better test .. basically we can +-- always use this: pdf primitives. + +local context = context + +local lpdfreserveobject = lpdf.reserveobject +local lpdfcompresslevel = lpdf.compresslevel +local lpdfobj = lpdf.obj +local lpdfpagereference = lpdf.pagereference +local lpdfxformname = lpdf.xformname + +local jobpositions = job.positions +local gethpos = jobpositions.gethpos +local getvpos = jobpositions.getvpos + +local tokenscanners = tokens.scanners +local scanword = tokenscanners.word +local scankeyword = tokenscanners.keyword +local scanstring = tokenscanners.string +local scaninteger = tokenscanners.integer +local scandimension = tokenscanners.dimension + +local trace = false trackers.register("commands", function(v) trace = v end) +local report = logs.reporter("command") + +local nodepool = nodes.pool +local newsavepos = nodepool.savepos +local newliteral = nodepool.literal +local newsave = nodepool.save +local newrestore = nodepool.restore +local newsetmatrix = nodepool.setmatrix + +local implement = interfaces.implement +local constants = interfaces.constants +local variables = interfaces.variables + +-- helper + +local function scanwhd() + local width, height, depth + while true do + if scankeyword("width") then + width = scandimension() + elseif scankeyword("height") then + height = scandimension() + elseif scankeyword("depth") then + depth = scandimension() + else + break + end + end + if width or height or depth then + return width or 0, height or 0, depth or 0 + else + -- we inherit + end +end + +-- positions + +local function savepos() + context(newsavepos()) +end + +local function lastxpos() + context(gethpos()) +end + +local function lastypos() + context(getvpos()) +end + +implement { name = "savepos", actions = savepos } +implement { name = "lastxpos", actions = lastxpos } +implement { name = "lastypos", actions = lastypos } + +-- literals + +local function pdfliteral() + context(newliteral(scanword() or "origin",scanstring())) +end + +implement { name = "pdfliteral", actions = pdfliteral } + +-- box resources + +local boxresources = tex.boxresources +local savebox = boxresources.save +local usebox = boxresources.use + +local lastindex = 0 + +local function saveboxresource() + local immediate = true + local kind = scankeyword("type") and scaninteger() or 0 + local attributes = scankeyword("attr") and scanstring() or nil + local resources = scankeyword("resources") and scanstring() or nil + local margin = scankeyword("margin") and scandimension() or 0 -- register + local boxnumber = scaninteger() + -- + lastindex = savebox(boxnumber,attributes,resources,immediate,kind,margin) + if trace then + report("\\saveboxresource: index %i",lastindex) + end +end + +local function lastsavedboxresourceindex() + if trace then + report("\\lastsaveboxresource: index %i",lastindex) + end + context("%i",lastindex) +end + +local function useboxresource() + local width, height, depth = scanwhd() + local index = scaninteger() + local node = usebox(index,width,height,depth) + if trace then + report("\\useboxresource: index %i",index) + end + context(node) +end + +implement { name = "saveboxresource", actions = saveboxresource } +implement { name = "lastsavedboxresourceindex", actions = lastsavedboxresourceindex } +implement { name = "useboxresource", actions = useboxresource } + +-- image resources (messy: will move) + +local imageresources = { } +local lastindex = 0 +local lastpages = 1 + +local function saveimageresource() + local width, height, depth = scanwhd() + local page = 1 + local immediate = true + local margin = 0 -- or dimension + local attributes = scankeyword("attr") and scanstring() or nil + if scankeyword("named") then + scanstring() -- ignored + elseif scankeyword("page") then + page = scaninteger() + end + local userpassword = scankeyword("userpassword") and scanstring() or nil + local ownerpassword = scankeyword("ownerpassword") and scanstring() or nil + local visiblefilename = scankeyword("visiblefilename") and scanstring() or nil + local colorspace = scankeyword("colorspace") and scaninteger() or nil + local pagebox = scanword() or nil + local filename = scanstring() +-- pcall + context.getfiguredimensions( { filename }, { + [constants.userpassword] = userpassword, + [constants.ownerpassword] = ownerpassword, + [constants.page] = page or 1, + [constants.size] = pagebox, + }) + context.relax() + lastindex = lastindex + 1 + lastpages = 1 + imageresources[lastindex] = { + filename = filename, + page = page or 1, + size = pagebox, + width = width, + height = height, + depth = depth, + attr = attributes, + -- margin = margin, + } +end + +local function lastsavedimageresourceindex() + context("%i",lastindex or 0) +end + +local function lastsavedimageresourcepages() + context("%i",lastpages or 0) -- todo +end + +local function useimageresource() + local width, height, depth = scanwhd() + if scankeyword("keepopen") then + -- ignored + end + local index = scaninteger() + local l = imageresources[index] + if l then + if not (width or height or depth) then + width = l.width + height = l.height + depth = l.depth + end +-- pcall + context.externalfigure( { l.filename }, { + [constants.userpassword] = l.userpassword, + [constants.ownerpassword] = l.ownerpassword, + [constants.width] = width and (width .. "sp") or nil, + [constants.height] = height and (height .. "sp") or nil, + [constants.page] = l.page or 1, + [constants.size] = pagebox, + }) + context.relax() + else + print("no image resource",index) + end +end + +implement { name = "saveimageresource", actions = saveimageresource } +implement { name = "lastsavedimageresourceindex", actions = lastsavedimageresourceindex } +implement { name = "lastsavedimageresourcepages", actions = lastsavedimageresourcepages } +implement { name = "useimageresource", actions = useimageresource } + +-- objects + +local lastobjnum = 0 + +local function pdfobj() + if scankeyword("reserveobjnum") then + lastobjnum = lpdfreserveobject() + if trace then + report("\\pdfobj reserveobjnum: object %i",lastobjnum) + end + else + local immediate = true + local objnum = scankeyword("useobjnum") and scaninteger() or lpdfreserveobject() + local uncompress = scankeyword("uncompressed") or lpdfcompresslevel() == 0 + local streamobject = scankeyword("stream") and true or false + local attributes = scankeyword("attr") and scanstring() + local fileobject = scankeyword("file") + local content = scanstring() + local object = { + immediate = immediate, + attr = attributes, + objnum = objnum, + type = streamobject and "stream" or nil, + compresslevel = uncompress and 0 or nil, + } + if fileobject then + object.filename = content + else + object.string = content + end + lpdfobj(object) + lastobjnum = objnum + if trace then + report("\\pdfobj: object %i",lastobjnum) + end + end +end + +local function pdflastobj() + context("%i",lastobjnum) + if trace then + report("\\lastobj: object %i",lastobjnum) + end +end + +local function pdfrefobj() + local objnum = scaninteger() + if trace then + report("\\refobj: object %i (todo)",objnum) + end +end + +implement { name = "pdfobj", actions = pdfobj } +implement { name = "pdflastobj", actions = pdflastobj } +implement { name = "pdfrefobj", actions = pdfrefobj } + +-- annotations + +local lastobjnum = 0 + +local function pdfannot() + if scankeyword("reserveobjnum") then + lastobjnum = lpdfreserveobject() + if trace then + report("\\pdfannot reserveobjnum: object %i",lastobjnum) + end + else + local width = false + local height = false + local depth = false + local data = false + local object = false + local attr = false + -- + if scankeyword("useobjnum") then + object = scancount() + report("\\pdfannot useobjectnum is not (yet) supported") + end + local width, height, depth = scanwhd() + if scankeyword("attr") then + attr = scanstring() + end + data = scanstring() + context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or "")) + end +end + +implement { name = "pdfannot", actions = pdfannot } + +local function pdfdest() + local name = false + local zoom = false + local view = false + local width = false + local height = false + local depth = false + if scankeyword("num") then + report("\\pdfdest num is not (yet) supported") + elseif scankeyword("name") then + name = scanstring() + end + if scankeyword("xyz") then + view = "xyz" + if scankeyword("zoom") then + report("\\pdfdest zoom is ignored") + zoom = scancount() -- will be divided by 1000 in the backend + end + elseif scankeyword("fitbh") then + view = "fitbh" + elseif scankeyword("fitbv") then + view = "fitbv" + elseif scankeyword("fitb") then + view = "fitb" + elseif scankeyword("fith") then + view = "fith" + elseif scankeyword("fitv") then + view = "fitv" + elseif scankeyword("fitr") then + view = "fitr" + width, height, depth = scanwhd() + elseif scankeyword("fit") then + view = "fit" + end + context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit")) +end + +implement { name = "pdfdest", actions = pdfdest } + +-- management + + +local function pdfsave() + context(newsave()) +end + +local function pdfrestore() + context(newrestore()) +end + +local function pdfsetmatrix() + context(newsetmatrix(scanstring())) +end + + +-- extras + +local function pdfpageref() + context(lpdfpagereference()) +end + +local function pdfxformname() + context(lpdfxformname()) +end + +-- extensions: literal dest annot save restore setmatrix obj refobj colorstack +-- startlink endlink startthread endthread thread outline glyphtounicode fontattr +-- mapfile mapline includechars catalog info names trailer + +local extensions = { + literal = pdfliteral, + obj = pdfobj, + refobj = pdfrefobj, + dest = pdfdest, + annot = pdfannot, + save = pdfsave, + restore = pdfrestore, + setmatrix = pdfsetmatrix, +} + +local function pdfextension() + local w = scanword() + if w then + local e = extensions[w] + if e then + e() + else + report("\\pdfextension: unknown %a",w) + end + end +end + +implement { name = "pdfextension", actions = pdfextension } + +-- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot +-- lastlink lastobj pageref retval revision version xformname + +local feedbacks = { + lastobj = pdflastobj, + pageref = pdfpageref, + xformname = pdfxformname, +} + +local function pdffeedback() + local w = scanword() + if w then + local f = feedbacks[w] + if f then + f() + else + report("\\pdffeedback: unknown %a",w) + end + end +end + +implement { name = "pdffeedback", actions = pdffeedback } + +-- variables: (integers:) compresslevel decimaldigits gamma gentounicode +-- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor +-- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion +-- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution +-- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin +-- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources +-- pagesattr pkmode trailerid xformattr xformresources + +-- local variables = { +-- } +-- +-- local function pdfvariable() +-- local w = scanword() +-- if w then +-- local f = variables[w] +-- if f then +-- f() +-- else +-- print("invalid variable",w) +-- end +-- else +-- print("missing variable") +-- end +-- end + +--------- { name = "pdfvariable", actions = pdfvariable } diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-res.lua b/Master/texmf-dist/tex/context/base/mkiv/back-res.lua new file mode 100644 index 00000000000..be92c74a6db --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/back-res.lua @@ -0,0 +1,44 @@ +if not modules then modules = { } end modules ['back-res'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- A box resource has an index. This happens to be an object number +-- due to the pdf backend but in fact it's an abstraction. This is why +-- we have explicit fetchers. The internal number (as in \Fm123) is yet +-- another number. + +local tex_saveboxresource = tex.saveboxresource +local tex_useboxresource = tex.useboxresource +local tex_getboxresourcebox = tex.getboxresourcebox +local tex_getboxresourcedimensions = tex.getboxresourcedimensions + +updaters.register("backend.update",function() + tex_saveboxresource = tex.saveboxresource + tex_useboxresource = tex.useboxresource + tex_getboxresourcebox = tex.getboxresourcebox + tex_getboxresourcedimensions = tex.getboxresourcedimensions +end) + +tex.boxresources = { + save = function(...) return tex_saveboxresource(...) end, + use = function(...) return tex_useboxresource(...) end, + getbox = function(...) return tex_getboxresourcebox(...) end, + getdimensions = function(...) return tex_getboxresourcedimensions(...) end, +} + +-- local tex_saveimageresource = tex.saveimageresource +-- local tex_useimageresource = tex.useimageresource +-- +-- updaters.register("backend.update",function() +-- tex_saveimageresource = tex.saveimageresource +-- tex_useimageresource = tex.useimageresource +-- end) +-- +-- tex.imageresources = { +-- save = function(...) return tex_saveimageresource(...) end, +-- use = function(...) return tex_useimageresource(...) end, +-- } diff --git a/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv index 0a53a8fd2e7..20a94266a4f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/back-swf.mkiv @@ -11,6 +11,9 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +%D The question is: should I still document this in interaction.tex or just +%D assume it's obsolete technology \unknown + %D This is only a placeholder that demonstrates the usage of swf resources. %D There is no need to include this file into the format. The module was %D tested by Luigi and Willi and based on their suggestions the functionality @@ -58,6 +61,8 @@ %D [file=test.mp4, %D label=foo] %D +%D \useJSscripts[vplayer] % or \useJSscripts[videoplayer] +%D %D \goto{START} [JS(StartShockwave{foo})] %D \goto{REWIND}[JS(RewindShockwave{foo})] %D \goto{PAUSE} [JS(PauseShockwave{foo})] @@ -84,100 +89,8 @@ \unprotect -\startluaparameterset[shockwave:display] - toolbar = true, - -- preview = "somefile", - open = "click", - close = "focus", -\stopluaparameterset - -% using vplayer9.swf from ctan: - -\useexternalfigure - [shockwave] - [vplayer9.swf] -% [arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file",source="\externalfigureparameter\v!file"}, - [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file",autoPlay=true}, - \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}}, - \c!display=shockwave:display] - -\startJSpreamble shockwave used now - function StartShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - // ok - } else { - rm.activated = true ; - } - rm.callAS("rewind") ; - rm.callAS("playPause") ; - } - function StopShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("pause") ; - rm.callAS("rewind") ; - } - } - function RewindShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("rewind") ; - } - } - function PauseShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("playPause") ; - } - } -\stopJSpreamble - -% using videoplayer.swf from adobe or strobemediaplayback.swf from sourceforge: - -%\useexternalfigure -% [shockwave] -% [videoplayer.swf] -% [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file"}, -% \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}}, -% \c!display=shockwave:display] - -\startJSpreamble shockwave used now - function StartShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("multimedia_play") ; - } else { - rm.activated = true ; - } - } - function StopShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("multimedia_pause") ; - rm.callAS("multimedia_rewind") ; - } - } - function RewindShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("multimedia_rewind") ; - } - } - function PauseShockwave(label) { - var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ; - if (rm.activated) { - rm.callAS("multimedia_pause") ; - } - } -\stopJSpreamble - -% \useexternalfigure -% [shockwave] -% [strobemediaplayback.swf] -% [arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file"}, -% resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}}, -% display=shockwave:display] +%D The code has moved to the (explicitly loaded) \JAVASCRIPT\ modules. See there +%D for more info. \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv index 784c87a020b..60291ee71b5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-bib.mkiv @@ -812,12 +812,12 @@ {\iflocation \edef\temp{\bibtexcitationparameter\c!interaction}% \ifx\temp\v!stop - \@EA@EA@EA\secondoftwoarguments + \doubleexpandafter\secondoftwoarguments \else - \@EA@EA@EA\firstoftwoarguments + \doubleexpandafter\firstoftwoarguments \fi \else - \@EA\secondoftwoarguments + \expandafter\secondoftwoarguments \fi} \let\doifbibtexinteractionelse\doifelsebibtexinteraction diff --git a/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv index 3ff07ead595..5389400f31b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/bibl-tra.mkiv @@ -1500,7 +1500,7 @@ \c!numbercommand=\bibleftnumber] \unexpanded\def\preloadbiblist - {\globallet\preloadbiblist\relax + {\glet\preloadbiblist\relax \dousepublications\jobname} % \appendtoks \preloadbiblist \to \everysetuppublications diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv index a4ad788bb76..4da4ff0df20 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/buff-imp-default.mkiv @@ -15,11 +15,11 @@ \unprotect -\definestartstop - [DefaultSnippet] - [\c!before=\blank, - \c!after=\blank, - \c!style=\tt] +\setupstartstop + [DefaultSnippet] + [\c!before={\typingparameter\c!before}, + \c!after={\typingparameter\c!after}, + \c!style={\typingparameter\c!style}] % Name % NamePrimitive diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua index 1c791277318..bd3cf9d5ae2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.lua @@ -167,7 +167,8 @@ local function collectcontent(name,separator) -- no print elseif nnames == 1 then return getcontent(names[1]) else - local t, n = { }, 0 + local t = { } + local n = 0 for i=1,nnames do local c = getcontent(names[i]) if c ~= "" then @@ -182,7 +183,7 @@ local function collectcontent(name,separator) -- no print end local function loadcontent(name) -- no print - local content = collectcontent(name,"\n") -- tex likes \n + local content = collectcontent(name,"\n") -- tex likes \n hm, elsewhere \r local ok, err = load(content) if ok then return ok() @@ -645,7 +646,10 @@ local function gettexbuffer(name) end end -buffers.run = runbuffer +buffers.get = getbuffer +buffers.getmkiv = getbuffermkiv +buffers.gettexbuffer = gettexbuffer +buffers.run = runbuffer implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" } implement { name = "getbuffer", actions = getbuffer, arguments = "string" } @@ -708,3 +712,18 @@ do end end + +-- moved here: + +function buffers.samplefile(name) + if not buffers.exists(name) then + buffers.assign(name,io.loaddata(resolvers.findfile(name))) + end + buffers.get(name) +end + +implement { + name = "samplefile", -- bad name, maybe rename to injectbuffercontent + actions = buffers.samplefile, + arguments = "string" +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv index 1a5ce459103..145f0f39245 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ini.mkiv @@ -44,8 +44,18 @@ % \def\buff_start_indeed#1#2#3#4#5% \donothing needed ! #5=undent) % {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}} +% \def\buff_start_indeed#1#2#3#4% +% {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}} + \def\buff_start_indeed#1#2#3#4% - {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}} + {\edef\p_strip{\namedbufferparameter{#1}\c!strip}% for aditya + \normalexpanded{\buff_pickup + {#2}% + {#3}% + {#4}% + {}% + {\buff_stop{#4}}% + \ifx\p_strip\v!no\zerocount\else\plusone\fi}} \unexpanded\def\grabbufferdata % was: \dostartbuffer {\begingroup % (4) @@ -155,7 +165,7 @@ \setexpandedbufferparameter\c!number{\number\c_buff_n_of_defined}% \edef\currentdefinedbuffer{def-\number\c_buff_n_of_defined}% \setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}% - \setuevalue{\e!get\currentbuffer }{\buff_get_stored{\currentbuffer}{\currentdefinedbuffer}}% + \setuevalue{\e!get \currentbuffer}{\buff_get_stored {\currentbuffer}{\currentdefinedbuffer}}% \to \everydefinebuffer \unexpanded\def\buff_start_defined @@ -169,16 +179,16 @@ {\dosingleempty\buff_get} \unexpanded\def\buff_get[#1]% [name] - {\namedbufferparameter\empty\c!before + {\namedbufferparameter\empty\c!before\relax \doifelsenothing{#1} {\buff_get_stored_indeed\empty} {\processcommalist[#1]\buff_get_stored_indeed}% - \namedbufferparameter\empty\c!after} + \namedbufferparameter\empty\c!after\relax} \unexpanded\def\buff_get_stored#1#2% - {\namedbufferparameter{#1}\c!before + {\namedbufferparameter{#1}\c!before\relax \buff_get_stored_indeed{#2}% - \namedbufferparameter{#1}\c!after} + \namedbufferparameter{#1}\c!after\relax} \unexpanded\def\buff_get_stored_indeed#1% {\clf_getbuffer{#1}} @@ -274,28 +284,4 @@ \def\getbufferdata[#1]{\buff_get_stored_indeed{#1}} -%D This is a weird one, moved from cont-new. Do we really need it? If not -%D it will go away. - -\bgroup \permitcircumflexescape - -\obeylines % don't remove %'s ! - -\gdef\collapsedspace#1% - {\ifx#1^^M% - \expandafter\collapsedspace - \else - \space - \expandafter#1% - \fi} - -\unexpanded\gdef\collapsespaces - {\prependtoksonce\relax\to\everyeof% - \ignorelines% - \ignoretabs% - \let\obeyedspace\collapsedspace% - \obeyspaces} - -\egroup - \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua index d9178b1dfc9..88605631d84 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.lua @@ -43,6 +43,7 @@ local findfile = resolvers.findfile local addsuffix = file.addsuffix local v_yes = variables.yes +local v_no = variables.no local v_last = variables.last local v_all = variables.all local v_absolute = variables.absolute @@ -141,7 +142,8 @@ local functions = { __index = { local handlers = { } function visualizers.newhandler(name,data) - local tname, tdata = type(name), type(data) + local tname = type(name) + local tdata = type(data) if tname == "table" then -- (data) setmetatable(name,getmetatable(name) or functions) return name @@ -255,7 +257,7 @@ function visualizers.load(name) if trace_visualize then report_visualizers("loading visualizer %a",name) end - lua.registercode(luaname) + lua.registercode(luaname) -- only used here, end up in format context.input(texname) end if rawget(specifications,name) == nil then @@ -445,7 +447,7 @@ function visualizers.registerescapecommand(name,token,normalmethod,escapecommand end token = P(token) local notoken = hack((1 - token)^1) - local cstoken = name_pattern * space_pattern + local cstoken = Cs(name_pattern * (space_pattern/"")) escapepattern = ( (token / "") * (cstoken / (escapecommand or texcommand)) @@ -614,7 +616,12 @@ end local onlyspaces = S(" \t\f\n\r")^0 * P(-1) local function getstrip(lines,first,last) - local first, last = first or 1, last or #lines + if not first then + first = 1 + end + if not last then + last = #lines + end for i=first,last do local li = lines[i] if #li == 0 or lpegmatch(onlyspaces,li) then @@ -736,12 +743,14 @@ end local function filter(lines,settings) -- todo: inline or display in settings local strip = settings.strip - if strip and strip ~= "" then + -- if strip and strip == "" then + if strip ~= v_no and strip ~= false then lines = realign(lines,strip) end - local line, n = 0, 0 - local first, last, m = getstrip(lines) + local line = 0 + local n = 0 local range = settings.range + local first, last, m = getstrip(lines) if range then first, last = getrange(lines,first,last,range) first, last = getstrip(lines,first,last) diff --git a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv index 558049dcc59..7cf829b746c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/buff-ver.mkiv @@ -496,7 +496,7 @@ \def\buff_verbatim_typing_start_nop {\typingparameter\c!before - \startpacked[\v!blank] + \startpacked[\v!blank]% \buff_verbatim_setup_line_numbering \buff_verbatim_initialize_typing_one \buff_verbatim_setup_keep_together @@ -504,7 +504,7 @@ \def\buff_verbatim_typing_start_yes[#1]% {\typingparameter\c!before - \startpacked[\v!blank] + \startpacked[\v!blank]% \doifelseassignment{#1} {\setupcurrenttyping[#1]} {\doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}}% @@ -514,9 +514,16 @@ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}} \unexpanded\def\buff_verbatim_type_block#1#2% - {\buff_pickup{_typing_}{#1}{#2}{}{\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}\plusone} % was dowithbuffer - -\def\buff_verbatim_type_block_verbatim_indeed#1#2% + {\edef\p_strip{\typingparameter\c!strip}% + \normalexpanded{\buff_pickup + {_typing_}% + {#1}% + {#2}% + {}% + {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}% + \ifx\p_strip\v!no\zerocount\else\plusone\fi}} + +\unexpanded\def\buff_verbatim_type_block_verbatim_indeed#1#2% {\buff_verbatim_initialize_typing_two \dostarttaggedchained\t!verbatimblock\currenttyping\??typing \beginofverbatimlines @@ -533,7 +540,7 @@ \dostoptagged \endofverbatimlines \dostoptagged - \csname#2\endcsname} + \begincsname#2\endcsname} \unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping {\stoppacked diff --git a/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv index 471e4d1c856..215ec14e16c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/catc-ini.mkiv @@ -23,58 +23,110 @@ %D \MKII\ file. There is some overlap in code with \MKII\ but we take that %D for granted. Also, in \MKIV\ less active characters are used. -\setnewconstant\escapecatcode 0 -\setnewconstant\begingroupcatcode 1 -\setnewconstant\endgroupcatcode 2 -\setnewconstant\mathshiftcatcode 3 -\setnewconstant\alignmentcatcode 4 -\setnewconstant\endoflinecatcode 5 -\setnewconstant\parametercatcode 6 -\setnewconstant\superscriptcatcode 7 -\setnewconstant\subscriptcatcode 8 -\setnewconstant\ignorecatcode 9 -\setnewconstant\spacecatcode 10 -\setnewconstant\lettercatcode 11 -\setnewconstant\othercatcode 12 % finally obsolete: \let\other \othercatcode -\setnewconstant\activecatcode 13 % finally obsolete: \let\active\activecatcode -\setnewconstant\commentcatcode 14 -\setnewconstant\invalidcatcode 15 - -\setnewconstant\tabasciicode 9 -\setnewconstant\newlineasciicode 10 % don't confuse this one with \endoflineasciicode -\setnewconstant\formfeedasciicode 12 -\setnewconstant\endoflineasciicode 13 % somewhat messy but this can be the active \par -\setnewconstant\endoffileasciicode 26 -\setnewconstant\spaceasciicode 32 -\setnewconstant\exclamationmarkasciicode 33 % ! used in namespace protection -\setnewconstant\doublequoteasciicode 34 % " -\setnewconstant\hashasciicode 35 -\setnewconstant\dollarasciicode 36 -\setnewconstant\commentasciicode 37 -\setnewconstant\ampersandasciicode 38 -\setnewconstant\singlequoteasciicode 39 % ' -\setnewconstant\primeasciicode 39 % ' -\setnewconstant\hyphenasciicode 45 -\setnewconstant\forwardslashasciicode 47 % / -\setnewconstant\colonasciicode 58 -\setnewconstant\lessthanasciicode 60 % < used as alternative verbatim { -\setnewconstant\morethanasciicode 62 % > used as alternative verbatim } -\setnewconstant\questionmarkasciicode 63 % ? used in namespace protection -\setnewconstant\atsignasciicode 64 % @ used in namespace protection -\setnewconstant\backslashasciicode 92 % `\\ -\setnewconstant\circumflexasciicode 94 -\setnewconstant\underscoreasciicode 95 -\setnewconstant\leftbraceasciicode 123 % `\{ -\setnewconstant\barasciicode 124 % `\| -\setnewconstant\rightbraceasciicode 125 % `\} -\setnewconstant\tildeasciicode 126 % `\~ -\setnewconstant\delasciicode 127 +% \normalprotected\def\setnewconstantfromchar#1% +% {\expandafter\ifdefined\expandafter#1\expandafter +% \let\expandafter#1\expandafter\undefined\expandafter\fi\expandafter +% \newcount\expandafter#1\expandafter#1\the#1\relax} +% +% \normalprotected\def\setnewconstantfromchar#1% +% {\begingroup +% \scratchcounter#1% +% \edef\!!stringa{\meaning#1}% +% \chardef#1\scratchcounter +% \edef\!!stringb{\meaning#1}% +% \normalexpanded{\endgroup +% \ifx\!!stringa\!!stringb +% \let#1\noexpand\undefined +% \newcount#1% +% \fi +% #1\the\scratchcounter\relax}} +% +% \normalprotected\def\setnewconstantfromchar#1% +% {\begingroup +% \edef\!!stringa{\meaning#1}% +% \expandafter\chardef\expandafter#1\the#1% +% \edef\!!stringb{\meaning#1}% +% \normalexpanded{\endgroup +% \ifx\!!stringa\!!stringb +% \let#1\noexpand\undefined +% \newcount#1% +% \fi +% #1\the#1\relax}} +% +% \normalprotected\def\setnewconstantfromchar#1% +% {\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter} + +\def\promote#1{\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter} + +\promote\escapecatcode +\promote\begingroupcatcode +\promote\endgroupcatcode +\promote\mathshiftcatcode +\promote\alignmentcatcode +\promote\endoflinecatcode +\promote\parametercatcode +\promote\superscriptcatcode +\promote\subscriptcatcode +\promote\ignorecatcode +\promote\spacecatcode +\promote\lettercatcode +\promote\othercatcode +\promote\activecatcode +\promote\commentcatcode +\promote\invalidcatcode + +\promote\tabasciicode +\promote\newlineasciicode +\promote\formfeedasciicode +\promote\endoflineasciicode +\promote\endoffileasciicode +\promote\spaceasciicode +\promote\exclamationmarkasciicode +\promote\doublequoteasciicode +\promote\hashasciicode +\promote\dollarasciicode +\promote\commentasciicode +\promote\ampersandasciicode +\promote\singlequoteasciicode +\promote\primeasciicode +\promote\hyphenasciicode +\promote\forwardslashasciicode +\promote\colonasciicode +\promote\lessthanasciicode +\promote\morethanasciicode +\promote\questionmarkasciicode +\promote\atsignasciicode +\promote\backslashasciicode +\promote\circumflexasciicode +\promote\underscoreasciicode +\promote\leftbraceasciicode +\promote\barasciicode +\promote\rightbraceasciicode +\promote\tildeasciicode +\promote\delasciicode + +\let\promote\undefined + +% \begingroup +% +% \catcode\tabasciicode \activecatcode +% \catcode\formfeedasciicode \activecatcode +% \catcode\endoflineasciicode\activecatcode +% +% \letcharcode\tabasciicode \relax +% \letcharcode\newlineasciicode \relax +% \letcharcode\formfeedasciicode \relax +% \letcharcode\endoflineasciicode\relax +% +% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I} +% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J} +% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L} +% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M} +% +% \endgroup \begingroup - \catcode \tabasciicode \activecatcode \gdef\activetabtoken {^^I} - \gdef\outputnewlinechar {^^J} - \catcode \formfeedasciicode \activecatcode \gdef\activeformfeedtoken {^^L} - \catcode \endoflineasciicode \activecatcode \gdef\activeendoflinetoken{^^M} + \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode} \endgroup % \endlinechar = \endoflineasciicode % appended to input lines @@ -82,10 +134,17 @@ % rather special and used in writing to file: \let\par\outputnewlinechar +% \normalprotected\def\initializenewlinechar % operating system dependent +% {\begingroup +% \newlinechar\newlineasciicode +% \xdef\outputnewlinechar{^^J}% +% \endgroup} + \normalprotected\def\initializenewlinechar % operating system dependent {\begingroup + \letcharcode\newlineasciicode\relax \newlinechar\newlineasciicode - \xdef\outputnewlinechar{^^J}% + \xdef\outputnewlinechar{\Uchar\newlineasciicode}% \endgroup} %D We predefine some prefixes ahead of syst-aux and mult-sys. diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv index 7d7268c8ba6..dd9a325f234 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/char-act.mkiv @@ -44,11 +44,14 @@ \unexpanded\def\controlspace{\hbox{\asciispacechar}} % rather tex, we need the unicode value \unexpanded\def\normalspaces{\catcode\spaceasciicode\spacecatcode} -\bgroup - \catcode\spaceasciicode\activecatcode - \unexpanded\gdef\obeyspaces{\catcode\spaceasciicode\activecatcode\def {\obeyedspace}} - \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}} -\egroup +% \bgroup +% \catcode\spaceasciicode\activecatcode +% \unexpanded\gdef\obeyspaces {\catcode\spaceasciicode\activecatcode\def {\obeyedspace }} +% \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}} +% \egroup + +%unexpanded\def\obeyspaces {\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\obeyedspace } +\unexpanded\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\controlspace} %D \macros %D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages} @@ -59,20 +62,42 @@ %D \NEWPAGE\ character locally, we redefine the meaning of %D this (often already) active character. -\expandafter\def\activeformfeedtoken{\par} +% \expandafter\def\activeformfeedtoken{\par} + +\letcharcode\formfeedasciicode\par %D The following indirect definitions enable us to implement %D all kind of \type{\obeyed} handlers. -\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }} -\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}} -\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}} +% \unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }} +% \unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}} +% \unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}} + +% \unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}} +% \unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}} +% \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} +% \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} + +% but ... as we don't want to freeze to \obeyedspace etc which can be set after \obeyspaces, we +% use an idirectness -\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}} -\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}} +\def\_obeyed_space_{\obeyedspace} +\def\_obeyed_tab_ {\obeyedtab} +\def\_obeyed_line_ {\obeyedline} +\def\_obeyed_page_ {\obeyedpage} + +\unexpanded\def\obeyspaces {\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \_obeyed_space_} +\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_tab_} +\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_line_} +\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\letcharcode\formfeedasciicode \_obeyed_page_} + +\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_space_} +\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_space_} \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} +\unexpanded\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\_control_space_} + %D \macros %D {naturaltextext} %D diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-def.lua b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua index fcbf0190087..c17400a7942 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-def.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua @@ -10232,6 +10232,7 @@ characters.data={ [0x3D0]={ adobename="betasymbolgreek", category="ll", + contextname="greekbetaalt", description="GREEK BETA SYMBOL", direction="l", linebreak="al", @@ -14164,6 +14165,13 @@ characters.data={ synonyms={ "armenian patiw" }, unicodeslot=0x55F, }, + [0x560]={ + category="ll", + description="ARMENIAN SMALL LETTER TURNED AYB", + direction="l", + linebreak="al", + unicodeslot=0x560, + }, [0x561]={ adobename="aybarmenian", category="ll", @@ -14515,6 +14523,13 @@ characters.data={ specials={ "compat", 0x565, 0x582 }, unicodeslot=0x587, }, + [0x588]={ + category="ll", + description="ARMENIAN SMALL LETTER YI WITH STROKE", + direction="l", + linebreak="al", + unicodeslot=0x588, + }, [0x589]={ adobename="periodarmenian", category="po", @@ -15283,6 +15298,13 @@ characters.data={ linebreak="hl", unicodeslot=0x5EA, }, + [0x5EF]={ + category="lo", + description="HEBREW YOD TRIANGLE", + direction="r", + linebreak="hl", + unicodeslot=0x5EF, + }, [0x5F0]={ adobename="vavvavhebrew", category="lo", @@ -17638,6 +17660,7 @@ characters.data={ unicodeslot=0x70D, }, [0x70F]={ + arabic="t", category="cf", description="SYRIAC ABBREVIATION MARK", direction="al", @@ -19362,6 +19385,28 @@ characters.data={ linebreak="al", unicodeslot=0x7FA, }, + [0x7FD]={ + category="mn", + combining=0xDC, + description="NKO DANTAYALAN", + direction="nsm", + linebreak="cm", + unicodeslot=0x7FD, + }, + [0x7FE]={ + category="sc", + description="NKO DOROME SIGN", + direction="r", + linebreak="pr", + unicodeslot=0x7FE, + }, + [0x7FF]={ + category="sc", + description="NKO TAMAN SIGN", + direction="r", + linebreak="pr", + unicodeslot=0x7FF, + }, [0x800]={ category="lo", description="SAMARITAN LETTER ALAF", @@ -20361,6 +20406,14 @@ characters.data={ linebreak="al", unicodeslot=0x8BD, }, + [0x8D3]={ + category="mn", + combining=0xDC, + description="ARABIC SMALL LOW WAW", + direction="nsm", + linebreak="cm", + unicodeslot=0x8D3, + }, [0x8D4]={ category="mn", combining=0xE6, @@ -21284,8 +21337,8 @@ characters.data={ description="DEVANAGARI SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0x93C, }, @@ -21522,8 +21575,8 @@ characters.data={ description="DEVANAGARI STRESS SIGN ANUDATTA", direction="nsm", indic="s", - indicmark="b", indicclass="anudatta", + indicmark="b", linebreak="cm", unicodeslot=0x952, }, @@ -22376,8 +22429,8 @@ characters.data={ description="BENGALI SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0x9BC, }, @@ -22823,6 +22876,14 @@ characters.data={ linebreak="al", unicodeslot=0x9FD, }, + [0x9FE]={ + category="mn", + combining=0xE6, + description="BENGALI SANDHI MARK", + direction="nsm", + linebreak="cm", + unicodeslot=0x9FE, + }, [0xA01]={ category="mn", description="GURMUKHI SIGN ADAK BINDI", @@ -23247,8 +23308,8 @@ characters.data={ description="GURMUKHI SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0xA3C, }, @@ -23565,6 +23626,13 @@ characters.data={ linebreak="cm", unicodeslot=0xA75, }, + [0xA76]={ + category="po", + description="GURMUKHI ABBREVIATION SIGN", + direction="l", + linebreak="al", + unicodeslot=0xA76, + }, [0xA81]={ adobename="candrabindugujarati", category="mn", @@ -24032,8 +24100,8 @@ characters.data={ description="GUJARATI SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0xABC, }, @@ -24807,8 +24875,8 @@ characters.data={ description="ORIYA SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0xB3C, }, @@ -25809,6 +25877,13 @@ characters.data={ linebreak="cm", unicodeslot=0xC03, }, + [0xC04]={ + category="mn", + description="TELUGU SIGN COMBINING ANUSVARA ABOVE", + direction="nsm", + linebreak="cm", + unicodeslot=0xC04, + }, [0xC05]={ category="lo", description="TELUGU LETTER A", @@ -26175,9 +26250,9 @@ characters.data={ category="lo", description="TELUGU LETTER VA", direction="l", + indic="c", linebreak="al", unicodeslot=0xC35, - indic="c", }, [0xC36]={ category="lo", @@ -26614,6 +26689,13 @@ characters.data={ linebreak="cm", unicodeslot=0xC83, }, + [0xC84]={ + category="po", + description="KANNADA SIGN SIDDHAM", + direction="l", + linebreak="bb", + unicodeslot=0xC84, + }, [0xC85]={ category="lo", description="KANNADA LETTER A", @@ -27014,8 +27096,8 @@ characters.data={ description="KANNADA SIGN NUKTA", direction="nsm", indic="o", - indicmark="b", indicclass="nukta", + indicmark="b", linebreak="cm", unicodeslot=0xCBC, }, @@ -31643,6 +31725,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1000, variants={ @@ -31653,6 +31736,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1001, }, @@ -31660,6 +31744,7 @@ characters.data={ category="lo", description="MYANMAR LETTER GA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1002, variants={ @@ -31670,6 +31755,7 @@ characters.data={ category="lo", description="MYANMAR LETTER GHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1003, }, @@ -31677,6 +31763,7 @@ characters.data={ category="lo", description="MYANMAR LETTER NGA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1004, variants={ @@ -31687,6 +31774,7 @@ characters.data={ category="lo", description="MYANMAR LETTER CA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1005, }, @@ -31694,6 +31782,7 @@ characters.data={ category="lo", description="MYANMAR LETTER CHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1006, }, @@ -31701,6 +31790,7 @@ characters.data={ category="lo", description="MYANMAR LETTER JA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1007, }, @@ -31708,6 +31798,7 @@ characters.data={ category="lo", description="MYANMAR LETTER JHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1008, }, @@ -31715,6 +31806,7 @@ characters.data={ category="lo", description="MYANMAR LETTER NYA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1009, }, @@ -31722,6 +31814,7 @@ characters.data={ category="lo", description="MYANMAR LETTER NNYA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100A, }, @@ -31729,6 +31822,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TTA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100B, }, @@ -31736,6 +31830,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TTHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100C, }, @@ -31743,6 +31838,7 @@ characters.data={ category="lo", description="MYANMAR LETTER DDA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100D, }, @@ -31750,6 +31846,7 @@ characters.data={ category="lo", description="MYANMAR LETTER DDHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100E, }, @@ -31757,6 +31854,7 @@ characters.data={ category="lo", description="MYANMAR LETTER NNA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x100F, }, @@ -31764,6 +31862,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1010, variants={ @@ -31774,6 +31873,7 @@ characters.data={ category="lo", description="MYANMAR LETTER THA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1011, variants={ @@ -31784,6 +31884,7 @@ characters.data={ category="lo", description="MYANMAR LETTER DA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1012, }, @@ -31791,6 +31892,7 @@ characters.data={ category="lo", description="MYANMAR LETTER DHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1013, }, @@ -31798,6 +31900,7 @@ characters.data={ category="lo", description="MYANMAR LETTER NA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1014, }, @@ -31805,6 +31908,7 @@ characters.data={ category="lo", description="MYANMAR LETTER PA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1015, variants={ @@ -31815,6 +31919,7 @@ characters.data={ category="lo", description="MYANMAR LETTER PHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1016, }, @@ -31822,6 +31927,7 @@ characters.data={ category="lo", description="MYANMAR LETTER BA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1017, }, @@ -31829,6 +31935,7 @@ characters.data={ category="lo", description="MYANMAR LETTER BHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1018, }, @@ -31836,6 +31943,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1019, variants={ @@ -31846,6 +31954,7 @@ characters.data={ category="lo", description="MYANMAR LETTER YA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101A, variants={ @@ -31856,6 +31965,7 @@ characters.data={ category="lo", description="MYANMAR LETTER RA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101B, }, @@ -31863,6 +31973,7 @@ characters.data={ category="lo", description="MYANMAR LETTER LA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101C, variants={ @@ -31873,6 +31984,7 @@ characters.data={ category="lo", description="MYANMAR LETTER WA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101D, variants={ @@ -31883,6 +31995,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101E, }, @@ -31890,6 +32003,7 @@ characters.data={ category="lo", description="MYANMAR LETTER HA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x101F, }, @@ -31897,6 +32011,7 @@ characters.data={ category="lo", description="MYANMAR LETTER LLA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1020, }, @@ -31904,6 +32019,7 @@ characters.data={ category="lo", description="MYANMAR LETTER A", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1021, }, @@ -31911,6 +32027,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN A", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1022, variants={ @@ -31921,6 +32038,7 @@ characters.data={ category="lo", description="MYANMAR LETTER I", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1023, }, @@ -31928,6 +32046,7 @@ characters.data={ category="lo", description="MYANMAR LETTER II", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1024, }, @@ -31935,6 +32054,7 @@ characters.data={ category="lo", description="MYANMAR LETTER U", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1025, }, @@ -31942,6 +32062,7 @@ characters.data={ category="lo", description="MYANMAR LETTER UU", direction="l", + indic="i", linebreak="sa", specials={ "char", 0x1025, 0x102E }, unicodeslot=0x1026, @@ -31950,6 +32071,7 @@ characters.data={ category="lo", description="MYANMAR LETTER E", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1027, }, @@ -31957,6 +32079,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MON E", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1028, }, @@ -31964,6 +32087,7 @@ characters.data={ category="lo", description="MYANMAR LETTER O", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1029, }, @@ -31971,6 +32095,7 @@ characters.data={ category="lo", description="MYANMAR LETTER AU", direction="l", + indic="i", linebreak="sa", unicodeslot=0x102A, }, @@ -31978,6 +32103,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN TALL AA", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x102B, }, @@ -31985,6 +32112,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN AA", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x102C, }, @@ -31992,6 +32121,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN I", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x102D, }, @@ -31999,6 +32130,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN II", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x102E, }, @@ -32006,6 +32139,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN U", direction="nsm", + indic="d", + indicmark="b", linebreak="sa", unicodeslot=0x102F, }, @@ -32013,6 +32148,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN UU", direction="nsm", + indic="d", + indicmark="b", linebreak="sa", unicodeslot=0x1030, }, @@ -32020,6 +32157,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN E", direction="l", + indic="d", + indicmark="l", linebreak="sa", unicodeslot=0x1031, variants={ @@ -32030,6 +32169,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN AI", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1032, }, @@ -32037,6 +32178,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN MON II", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1033, }, @@ -32044,6 +32187,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN MON O", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1034, }, @@ -32051,6 +32196,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN E ABOVE", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1035, }, @@ -32058,6 +32205,8 @@ characters.data={ category="mn", description="MYANMAR SIGN ANUSVARA", direction="nsm", + indic="m", + indicmark="t", linebreak="sa", unicodeslot=0x1036, }, @@ -32066,6 +32215,8 @@ characters.data={ combining=0x7, description="MYANMAR SIGN DOT BELOW", direction="nsm", + indic="s", + indicmark="b", linebreak="sa", unicodeslot=0x1037, }, @@ -32073,6 +32224,8 @@ characters.data={ category="mc", description="MYANMAR SIGN VISARGA", direction="l", + indic="m", + indicmark="r", linebreak="sa", unicodeslot=0x1038, }, @@ -32081,6 +32234,8 @@ characters.data={ combining=0x9, description="MYANMAR SIGN VIRAMA", direction="nsm", + indic="m", + indicmark="b", linebreak="sa", synonyms={ "myanmar killer" }, unicodeslot=0x1039, @@ -32090,6 +32245,8 @@ characters.data={ combining=0x9, description="MYANMAR SIGN ASAT", direction="nsm", + indic="m", + indicmark="t", linebreak="sa", unicodeslot=0x103A, }, @@ -32097,6 +32254,8 @@ characters.data={ category="mc", description="MYANMAR CONSONANT SIGN MEDIAL YA", direction="l", + indic="c", + indicmark="r", linebreak="sa", unicodeslot=0x103B, }, @@ -32104,6 +32263,7 @@ characters.data={ category="mc", description="MYANMAR CONSONANT SIGN MEDIAL RA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x103C, }, @@ -32111,6 +32271,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN MEDIAL WA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x103D, }, @@ -32118,6 +32280,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN MEDIAL HA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x103E, }, @@ -32125,6 +32289,7 @@ characters.data={ category="lo", description="MYANMAR LETTER GREAT SA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x103F, }, @@ -32132,6 +32297,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT ZERO", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1040, }, @@ -32139,6 +32305,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT ONE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1041, }, @@ -32146,6 +32313,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT TWO", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1042, }, @@ -32153,6 +32321,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT THREE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1043, }, @@ -32160,6 +32329,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT FOUR", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1044, }, @@ -32167,6 +32337,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT FIVE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1045, }, @@ -32174,6 +32345,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT SIX", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1046, }, @@ -32181,6 +32353,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT SEVEN", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1047, }, @@ -32188,6 +32361,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT EIGHT", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1048, }, @@ -32195,6 +32369,7 @@ characters.data={ category="nd", description="MYANMAR DIGIT NINE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1049, }, @@ -32202,6 +32377,7 @@ characters.data={ category="po", description="MYANMAR SIGN LITTLE SECTION", direction="l", + indic="o", linebreak="ba", unicodeslot=0x104A, }, @@ -32209,6 +32385,7 @@ characters.data={ category="po", description="MYANMAR SIGN SECTION", direction="l", + indic="o", linebreak="ba", unicodeslot=0x104B, }, @@ -32216,6 +32393,7 @@ characters.data={ category="po", description="MYANMAR SYMBOL LOCATIVE", direction="l", + indic="o", linebreak="al", unicodeslot=0x104C, }, @@ -32223,6 +32401,7 @@ characters.data={ category="po", description="MYANMAR SYMBOL COMPLETED", direction="l", + indic="o", linebreak="al", unicodeslot=0x104D, }, @@ -32230,6 +32409,7 @@ characters.data={ category="po", description="MYANMAR SYMBOL AFOREMENTIONED", direction="l", + indic="o", linebreak="al", unicodeslot=0x104E, }, @@ -32237,6 +32417,7 @@ characters.data={ category="po", description="MYANMAR SYMBOL GENITIVE", direction="l", + indic="o", linebreak="al", unicodeslot=0x104F, }, @@ -32244,6 +32425,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1050, }, @@ -32251,6 +32433,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SSA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1051, }, @@ -32258,6 +32441,7 @@ characters.data={ category="lo", description="MYANMAR LETTER VOCALIC R", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1052, }, @@ -32265,6 +32449,7 @@ characters.data={ category="lo", description="MYANMAR LETTER VOCALIC RR", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1053, }, @@ -32272,6 +32457,7 @@ characters.data={ category="lo", description="MYANMAR LETTER VOCALIC L", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1054, }, @@ -32279,6 +32465,7 @@ characters.data={ category="lo", description="MYANMAR LETTER VOCALIC LL", direction="l", + indic="i", linebreak="sa", unicodeslot=0x1055, }, @@ -32286,6 +32473,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN VOCALIC R", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1056, }, @@ -32293,6 +32482,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN VOCALIC RR", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1057, }, @@ -32300,6 +32491,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN VOCALIC L", direction="nsm", + indic="d", + indicmark="b", linebreak="sa", unicodeslot=0x1058, }, @@ -32307,6 +32500,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN VOCALIC LL", direction="nsm", + indic="d", + indicmark="b", linebreak="sa", unicodeslot=0x1059, }, @@ -32314,6 +32509,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MON NGA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x105A, }, @@ -32321,6 +32517,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MON JHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x105B, }, @@ -32328,6 +32525,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MON BBA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x105C, }, @@ -32335,6 +32533,7 @@ characters.data={ category="lo", description="MYANMAR LETTER MON BBE", direction="l", + indic="c", linebreak="sa", unicodeslot=0x105D, }, @@ -32342,6 +32541,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN MON MEDIAL NA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x105E, }, @@ -32349,6 +32550,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN MON MEDIAL MA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x105F, }, @@ -32356,6 +32559,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN MON MEDIAL LA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x1060, }, @@ -32363,6 +32568,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SGAW KAREN SHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1061, }, @@ -32370,6 +32576,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN SGAW KAREN EU", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1062, }, @@ -32377,6 +32585,8 @@ characters.data={ category="mc", description="MYANMAR TONE MARK SGAW KAREN HATHI", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1063, }, @@ -32384,6 +32594,8 @@ characters.data={ category="mc", description="MYANMAR TONE MARK SGAW KAREN KE PHO", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1064, }, @@ -32391,6 +32603,7 @@ characters.data={ category="lo", description="MYANMAR LETTER WESTERN PWO KAREN THA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1065, }, @@ -32398,6 +32611,7 @@ characters.data={ category="lo", description="MYANMAR LETTER WESTERN PWO KAREN PWA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1066, }, @@ -32405,6 +32619,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN WESTERN PWO KAREN EU", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1067, }, @@ -32412,6 +32628,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN WESTERN PWO KAREN UE", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1068, }, @@ -32419,6 +32637,8 @@ characters.data={ category="mc", description="MYANMAR SIGN WESTERN PWO KAREN TONE-1", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1069, }, @@ -32426,6 +32646,8 @@ characters.data={ category="mc", description="MYANMAR SIGN WESTERN PWO KAREN TONE-2", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x106A, }, @@ -32433,6 +32655,8 @@ characters.data={ category="mc", description="MYANMAR SIGN WESTERN PWO KAREN TONE-3", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x106B, }, @@ -32440,6 +32664,8 @@ characters.data={ category="mc", description="MYANMAR SIGN WESTERN PWO KAREN TONE-4", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x106C, }, @@ -32447,6 +32673,8 @@ characters.data={ category="mc", description="MYANMAR SIGN WESTERN PWO KAREN TONE-5", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x106D, }, @@ -32454,6 +32682,7 @@ characters.data={ category="lo", description="MYANMAR LETTER EASTERN PWO KAREN NNA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x106E, }, @@ -32461,6 +32690,7 @@ characters.data={ category="lo", description="MYANMAR LETTER EASTERN PWO KAREN YWA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x106F, }, @@ -32468,6 +32698,7 @@ characters.data={ category="lo", description="MYANMAR LETTER EASTERN PWO KAREN GHWA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1070, }, @@ -32475,6 +32706,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN GEBA KAREN I", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1071, }, @@ -32482,6 +32715,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN KAYAH OE", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1072, }, @@ -32489,6 +32724,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN KAYAH U", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1073, }, @@ -32496,6 +32733,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN KAYAH EE", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1074, }, @@ -32503,6 +32742,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN KA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1075, variants={ @@ -32513,6 +32753,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN KHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1076, }, @@ -32520,6 +32761,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN GA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1077, }, @@ -32527,6 +32769,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN CA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1078, variants={ @@ -32537,6 +32780,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN ZA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1079, }, @@ -32544,6 +32788,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN NYA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107A, variants={ @@ -32554,6 +32799,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN DA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107B, }, @@ -32561,6 +32807,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN NA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107C, }, @@ -32568,6 +32815,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN PHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107D, }, @@ -32575,6 +32823,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN FA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107E, }, @@ -32582,6 +32831,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN BA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x107F, }, @@ -32589,6 +32839,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN THA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1080, variants={ @@ -32599,6 +32850,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN HA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x1081, }, @@ -32606,6 +32858,8 @@ characters.data={ category="mn", description="MYANMAR CONSONANT SIGN SHAN MEDIAL WA", direction="nsm", + indic="c", + indicmark="b", linebreak="sa", unicodeslot=0x1082, }, @@ -32613,6 +32867,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN SHAN AA", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x1083, }, @@ -32620,6 +32876,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN SHAN E", direction="l", + indic="d", + indicmark="l", linebreak="sa", unicodeslot=0x1084, }, @@ -32627,6 +32885,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN SHAN E ABOVE", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1085, }, @@ -32634,6 +32894,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN SHAN FINAL Y", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x1086, }, @@ -32641,6 +32903,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN TONE-2", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1087, }, @@ -32648,6 +32912,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN TONE-3", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1088, }, @@ -32655,6 +32921,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN TONE-5", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x1089, }, @@ -32662,6 +32930,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN TONE-6", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x108A, }, @@ -32669,6 +32939,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN COUNCIL TONE-2", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x108B, }, @@ -32676,6 +32948,8 @@ characters.data={ category="mc", description="MYANMAR SIGN SHAN COUNCIL TONE-3", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x108C, }, @@ -32684,6 +32958,8 @@ characters.data={ combining=0xDC, description="MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE", direction="nsm", + indic="s", + indicmark="b", linebreak="sa", unicodeslot=0x108D, }, @@ -32691,6 +32967,7 @@ characters.data={ category="lo", description="MYANMAR LETTER RUMAI PALAUNG FA", direction="l", + indic="c", linebreak="sa", unicodeslot=0x108E, }, @@ -32698,6 +32975,8 @@ characters.data={ category="mc", description="MYANMAR SIGN RUMAI PALAUNG TONE-5", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x108F, }, @@ -32705,6 +32984,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT ZERO", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1090, }, @@ -32712,6 +32992,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT ONE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1091, }, @@ -32719,6 +33000,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT TWO", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1092, }, @@ -32726,6 +33008,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT THREE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1093, }, @@ -32733,6 +33016,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT FOUR", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1094, }, @@ -32740,6 +33024,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT FIVE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1095, }, @@ -32747,6 +33032,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT SIX", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1096, }, @@ -32754,6 +33040,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT SEVEN", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1097, }, @@ -32761,6 +33048,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT EIGHT", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1098, }, @@ -32768,6 +33056,7 @@ characters.data={ category="nd", description="MYANMAR SHAN DIGIT NINE", direction="l", + indic="o", linebreak="nu", unicodeslot=0x1099, }, @@ -32775,6 +33064,8 @@ characters.data={ category="mc", description="MYANMAR SIGN KHAMTI TONE-1", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x109A, }, @@ -32782,6 +33073,8 @@ characters.data={ category="mc", description="MYANMAR SIGN KHAMTI TONE-3", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0x109B, }, @@ -32789,6 +33082,8 @@ characters.data={ category="mc", description="MYANMAR VOWEL SIGN AITON A", direction="l", + indic="d", + indicmark="r", linebreak="sa", unicodeslot=0x109C, }, @@ -32796,6 +33091,8 @@ characters.data={ category="mn", description="MYANMAR VOWEL SIGN AITON AI", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0x109D, }, @@ -32803,6 +33100,7 @@ characters.data={ category="so", description="MYANMAR SYMBOL SHAN ONE", direction="l", + indic="o", linebreak="sa", unicodeslot=0x109E, }, @@ -32810,6 +33108,7 @@ characters.data={ category="so", description="MYANMAR SYMBOL SHAN EXCLAMATION", direction="l", + indic="o", linebreak="sa", unicodeslot=0x109F, }, @@ -46377,6 +46676,14 @@ characters.data={ linebreak="al", unicodeslot=0x1877, }, + [0x1878]={ + arabic="d", + category="lo", + description="MONGOLIAN LETTER CHA WITH TWO DOTS", + direction="l", + linebreak="al", + unicodeslot=0x1878, + }, [0x1880]={ arabic="u", category="lo", @@ -52619,6 +52926,328 @@ characters.data={ linebreak="al", unicodeslot=0x1C88, }, + [0x1C90]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER AN", + direction="l", + linebreak="al", + unicodeslot=0x1C90, + }, + [0x1C91]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER BAN", + direction="l", + linebreak="al", + unicodeslot=0x1C91, + }, + [0x1C92]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER GAN", + direction="l", + linebreak="al", + unicodeslot=0x1C92, + }, + [0x1C93]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER DON", + direction="l", + linebreak="al", + unicodeslot=0x1C93, + }, + [0x1C94]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER EN", + direction="l", + linebreak="al", + unicodeslot=0x1C94, + }, + [0x1C95]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER VIN", + direction="l", + linebreak="al", + unicodeslot=0x1C95, + }, + [0x1C96]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER ZEN", + direction="l", + linebreak="al", + unicodeslot=0x1C96, + }, + [0x1C97]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER TAN", + direction="l", + linebreak="al", + unicodeslot=0x1C97, + }, + [0x1C98]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER IN", + direction="l", + linebreak="al", + unicodeslot=0x1C98, + }, + [0x1C99]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER KAN", + direction="l", + linebreak="al", + unicodeslot=0x1C99, + }, + [0x1C9A]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER LAS", + direction="l", + linebreak="al", + unicodeslot=0x1C9A, + }, + [0x1C9B]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER MAN", + direction="l", + linebreak="al", + unicodeslot=0x1C9B, + }, + [0x1C9C]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER NAR", + direction="l", + linebreak="al", + unicodeslot=0x1C9C, + }, + [0x1C9D]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER ON", + direction="l", + linebreak="al", + unicodeslot=0x1C9D, + }, + [0x1C9E]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER PAR", + direction="l", + linebreak="al", + unicodeslot=0x1C9E, + }, + [0x1C9F]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER ZHAR", + direction="l", + linebreak="al", + unicodeslot=0x1C9F, + }, + [0x1CA0]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER RAE", + direction="l", + linebreak="al", + unicodeslot=0x1CA0, + }, + [0x1CA1]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER SAN", + direction="l", + linebreak="al", + unicodeslot=0x1CA1, + }, + [0x1CA2]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER TAR", + direction="l", + linebreak="al", + unicodeslot=0x1CA2, + }, + [0x1CA3]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER UN", + direction="l", + linebreak="al", + unicodeslot=0x1CA3, + }, + [0x1CA4]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER PHAR", + direction="l", + linebreak="al", + unicodeslot=0x1CA4, + }, + [0x1CA5]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER KHAR", + direction="l", + linebreak="al", + unicodeslot=0x1CA5, + }, + [0x1CA6]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER GHAN", + direction="l", + linebreak="al", + unicodeslot=0x1CA6, + }, + [0x1CA7]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER QAR", + direction="l", + linebreak="al", + unicodeslot=0x1CA7, + }, + [0x1CA8]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER SHIN", + direction="l", + linebreak="al", + unicodeslot=0x1CA8, + }, + [0x1CA9]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER CHIN", + direction="l", + linebreak="al", + unicodeslot=0x1CA9, + }, + [0x1CAA]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER CAN", + direction="l", + linebreak="al", + unicodeslot=0x1CAA, + }, + [0x1CAB]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER JIL", + direction="l", + linebreak="al", + unicodeslot=0x1CAB, + }, + [0x1CAC]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER CIL", + direction="l", + linebreak="al", + unicodeslot=0x1CAC, + }, + [0x1CAD]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER CHAR", + direction="l", + linebreak="al", + unicodeslot=0x1CAD, + }, + [0x1CAE]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER XAN", + direction="l", + linebreak="al", + unicodeslot=0x1CAE, + }, + [0x1CAF]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER JHAN", + direction="l", + linebreak="al", + unicodeslot=0x1CAF, + }, + [0x1CB0]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HAE", + direction="l", + linebreak="al", + unicodeslot=0x1CB0, + }, + [0x1CB1]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HE", + direction="l", + linebreak="al", + unicodeslot=0x1CB1, + }, + [0x1CB2]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HIE", + direction="l", + linebreak="al", + unicodeslot=0x1CB2, + }, + [0x1CB3]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER WE", + direction="l", + linebreak="al", + unicodeslot=0x1CB3, + }, + [0x1CB4]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HAR", + direction="l", + linebreak="al", + unicodeslot=0x1CB4, + }, + [0x1CB5]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HOE", + direction="l", + linebreak="al", + unicodeslot=0x1CB5, + }, + [0x1CB6]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER FI", + direction="l", + linebreak="al", + unicodeslot=0x1CB6, + }, + [0x1CB7]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER YN", + direction="l", + linebreak="al", + unicodeslot=0x1CB7, + }, + [0x1CB8]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER ELIFI", + direction="l", + linebreak="al", + unicodeslot=0x1CB8, + }, + [0x1CB9]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN", + direction="l", + linebreak="al", + unicodeslot=0x1CB9, + }, + [0x1CBA]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER AIN", + direction="l", + linebreak="al", + unicodeslot=0x1CBA, + }, + [0x1CBD]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER AEN", + direction="l", + linebreak="al", + unicodeslot=0x1CBD, + }, + [0x1CBE]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN", + direction="l", + linebreak="al", + unicodeslot=0x1CBE, + }, + [0x1CBF]={ + category="lu", + description="GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN", + direction="l", + linebreak="al", + unicodeslot=0x1CBF, + }, [0x1CC0]={ category="po", description="SUNDANESE PUNCTUATION BINDU SURYA", @@ -65371,6 +66000,7 @@ characters.data={ linebreak="ai", mathclass="ordinary", mathname="rightangle", + mirror=0x2BFE, unicodeslot=0x221F, }, [0x2220]={ @@ -65382,6 +66012,7 @@ characters.data={ linebreak="ai", mathclass="ordinary", mathname="angle", + mirror=0x29A3, unicodeslot=0x2220, }, [0x2221]={ @@ -65391,6 +66022,7 @@ characters.data={ linebreak="al", mathclass="ordinary", mathname="measuredangle", + mirror=0x299B, unicodeslot=0x2221, }, [0x2222]={ @@ -65400,6 +66032,7 @@ characters.data={ linebreak="al", mathclass="ordinary", mathname="sphericalangle", + mirror=0x29A0, synonyms={ "angle arc" }, unicodeslot=0x2222, }, @@ -65430,6 +66063,7 @@ characters.data={ name="nmid", }, }, + mirror=0x2AEE, specials={ "char", 0x2223, 0x338 }, unicodeslot=0x2224, }, @@ -65834,6 +66468,7 @@ characters.data={ name="cong", }, }, + mirror=0x224C, unicodeslot=0x2245, }, [0x2246]={ @@ -65909,6 +66544,7 @@ characters.data={ direction="on", linebreak="ai", mathclass="relation", + mirror=0x2245, unicodeslot=0x224C, }, [0x224D]={ @@ -67110,6 +67746,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="multimap", + mirror=0x27DC, unicodeslot=0x22B8, }, [0x22B9]={ @@ -73450,8 +74087,8 @@ characters.data={ }, [0x25CC]={ adobename="dottedcircle", - contextname="dottedcircle", category="so", + contextname="dottedcircle", description="DOTTED CIRCLE", direction="on", linebreak="al", @@ -77559,6 +78196,7 @@ characters.data={ description="LEFT MULTIMAP", direction="on", linebreak="al", + mirror=0x22B8, unicodeslot=0x27DC, }, [0x27DD]={ @@ -80944,6 +81582,7 @@ characters.data={ description="MEASURED ANGLE OPENING LEFT", direction="on", linebreak="al", + mirror=0x2221, unicodeslot=0x299B, }, [0x299C]={ @@ -80979,6 +81618,7 @@ characters.data={ description="SPHERICAL ANGLE OPENING LEFT", direction="on", linebreak="al", + mirror=0x2222, unicodeslot=0x29A0, }, [0x29A1]={ @@ -81000,6 +81640,7 @@ characters.data={ description="REVERSED ANGLE", direction="on", linebreak="al", + mirror=0x2220, unicodeslot=0x29A3, }, [0x29A4]={ @@ -81007,6 +81648,7 @@ characters.data={ description="ANGLE WITH UNDERBAR", direction="on", linebreak="al", + mirror=0x29A5, unicodeslot=0x29A4, }, [0x29A5]={ @@ -81014,6 +81656,7 @@ characters.data={ description="REVERSED ANGLE WITH UNDERBAR", direction="on", linebreak="al", + mirror=0x29A4, unicodeslot=0x29A5, }, [0x29A6]={ @@ -81035,6 +81678,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT", direction="on", linebreak="al", + mirror=0x29A9, unicodeslot=0x29A8, }, [0x29A9]={ @@ -81042,6 +81686,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT", direction="on", linebreak="al", + mirror=0x29A8, unicodeslot=0x29A9, }, [0x29AA]={ @@ -81049,6 +81694,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT", direction="on", linebreak="al", + mirror=0x29AB, unicodeslot=0x29AA, }, [0x29AB]={ @@ -81056,6 +81702,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT", direction="on", linebreak="al", + mirror=0x29AA, unicodeslot=0x29AB, }, [0x29AC]={ @@ -81063,6 +81710,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP", direction="on", linebreak="al", + mirror=0x29AD, unicodeslot=0x29AC, }, [0x29AD]={ @@ -81070,6 +81718,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP", direction="on", linebreak="al", + mirror=0x29AC, unicodeslot=0x29AD, }, [0x29AE]={ @@ -81077,6 +81726,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN", direction="on", linebreak="al", + mirror=0x29AF, unicodeslot=0x29AE, }, [0x29AF]={ @@ -81084,6 +81734,7 @@ characters.data={ description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN", direction="on", linebreak="al", + mirror=0x29AE, unicodeslot=0x29AF, }, [0x29B0]={ @@ -81502,6 +82153,7 @@ characters.data={ description="DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK", direction="on", linebreak="al", + mirror=0x29E9, unicodeslot=0x29E8, }, [0x29E9]={ @@ -81509,6 +82161,7 @@ characters.data={ description="DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK", direction="on", linebreak="al", + mirror=0x29E8, unicodeslot=0x29E9, }, [0x29EA]={ @@ -82608,6 +83261,7 @@ characters.data={ description="LESS-THAN WITH QUESTION MARK ABOVE", direction="on", linebreak="al", + mirror=0x2A7C, unicodeslot=0x2A7B, }, [0x2A7C]={ @@ -82615,6 +83269,7 @@ characters.data={ description="GREATER-THAN WITH QUESTION MARK ABOVE", direction="on", linebreak="al", + mirror=0x2A7B, unicodeslot=0x2A7C, }, [0x2A7D]={ @@ -82692,6 +83347,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="lessapprox", + mirror=0x2A86, unicodeslot=0x2A85, }, [0x2A86]={ @@ -82701,6 +83357,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="gtrapprox", + mirror=0x2A85, unicodeslot=0x2A86, }, [0x2A87]={ @@ -82710,6 +83367,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="lneq", + mirror=0x2A88, unicodeslot=0x2A87, }, [0x2A88]={ @@ -82719,6 +83377,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="rneq", + mirror=0x2A87, unicodeslot=0x2A88, }, [0x2A89]={ @@ -82728,6 +83387,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="lnapprox", + mirror=0x2A8A, unicodeslot=0x2A89, }, [0x2A8A]={ @@ -82737,6 +83397,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="gnapprox", + mirror=0x2A89, unicodeslot=0x2A8A, }, [0x2A8B]={ @@ -82766,6 +83427,7 @@ characters.data={ description="LESS-THAN ABOVE SIMILAR OR EQUAL", direction="on", linebreak="al", + mirror=0x2A8E, unicodeslot=0x2A8D, }, [0x2A8E]={ @@ -82773,6 +83435,7 @@ characters.data={ description="GREATER-THAN ABOVE SIMILAR OR EQUAL", direction="on", linebreak="al", + mirror=0x2A8D, unicodeslot=0x2A8E, }, [0x2A8F]={ @@ -82780,6 +83443,7 @@ characters.data={ description="LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN", direction="on", linebreak="al", + mirror=0x2A90, unicodeslot=0x2A8F, }, [0x2A90]={ @@ -82787,6 +83451,7 @@ characters.data={ description="GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN", direction="on", linebreak="al", + mirror=0x2A8F, unicodeslot=0x2A90, }, [0x2A91]={ @@ -82894,6 +83559,7 @@ characters.data={ description="SIMILAR OR LESS-THAN", direction="on", linebreak="al", + mirror=0x2A9E, unicodeslot=0x2A9D, variants={ [0xFE00]="with similar following the slant of the upper leg", @@ -82904,6 +83570,7 @@ characters.data={ description="SIMILAR OR GREATER-THAN", direction="on", linebreak="al", + mirror=0x2A9D, unicodeslot=0x2A9E, variants={ [0xFE00]="with similar following the slant of the upper leg", @@ -82914,6 +83581,7 @@ characters.data={ description="SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN", direction="on", linebreak="al", + mirror=0x2AA0, unicodeslot=0x2A9F, }, [0x2AA0]={ @@ -82921,6 +83589,7 @@ characters.data={ description="SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN", direction="on", linebreak="al", + mirror=0x2A9F, unicodeslot=0x2AA0, }, [0x2AA1]={ @@ -83065,6 +83734,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="precneq", + mirror=0x2AB2, unicodeslot=0x2AB1, }, [0x2AB2]={ @@ -83074,6 +83744,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="succneq", + mirror=0x2AB1, unicodeslot=0x2AB2, }, [0x2AB3]={ @@ -83103,6 +83774,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="precneqq", + mirror=0x2AB6, unicodeslot=0x2AB5, }, [0x2AB6]={ @@ -83112,6 +83784,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="succneqq", + mirror=0x2AB5, unicodeslot=0x2AB6, }, [0x2AB7]={ @@ -83121,6 +83794,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="precapprox", + mirror=0x2AB8, unicodeslot=0x2AB7, }, [0x2AB8]={ @@ -83130,6 +83804,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="succapprox", + mirror=0x2AB7, unicodeslot=0x2AB8, }, [0x2AB9]={ @@ -83139,6 +83814,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="precnapprox", + mirror=0x2ABA, unicodeslot=0x2AB9, }, [0x2ABA]={ @@ -83148,6 +83824,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="succnapprox", + mirror=0x2AB9, unicodeslot=0x2ABA, }, [0x2ABB]={ @@ -83255,6 +83932,7 @@ characters.data={ description="SUBSET OF ABOVE TILDE OPERATOR", direction="on", linebreak="al", + mirror=0x2AC8, unicodeslot=0x2AC7, }, [0x2AC8]={ @@ -83262,6 +83940,7 @@ characters.data={ description="SUPERSET OF ABOVE TILDE OPERATOR", direction="on", linebreak="al", + mirror=0x2AC7, unicodeslot=0x2AC8, }, [0x2AC9]={ @@ -83269,6 +83948,7 @@ characters.data={ description="SUBSET OF ABOVE ALMOST EQUAL TO", direction="on", linebreak="al", + mirror=0x2ACA, unicodeslot=0x2AC9, }, [0x2ACA]={ @@ -83276,6 +83956,7 @@ characters.data={ description="SUPERSET OF ABOVE ALMOST EQUAL TO", direction="on", linebreak="al", + mirror=0x2AC9, unicodeslot=0x2ACA, }, [0x2ACB]={ @@ -83285,6 +83966,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="subsetneqq", + mirror=0x2ACC, unicodeslot=0x2ACB, variants={ [0xFE00]="with stroke through bottom members", @@ -83297,6 +83979,7 @@ characters.data={ linebreak="al", mathclass="relation", mathname="supsetneqq", + mirror=0x2ACB, unicodeslot=0x2ACC, variants={ [0xFE00]="with stroke through bottom members", @@ -83559,6 +84242,7 @@ characters.data={ description="DOES NOT DIVIDE WITH REVERSED NEGATION SLASH", direction="on", linebreak="al", + mirror=0x2224, unicodeslot=0x2AEE, }, [0x2AEF]={ @@ -84998,6 +85682,27 @@ characters.data={ synonyms={ "escape" }, unicodeslot=0x2BB9, }, + [0x2BBA]={ + category="so", + description="OVERLAPPING WHITE SQUARES", + direction="on", + linebreak="al", + unicodeslot=0x2BBA, + }, + [0x2BBB]={ + category="so", + description="OVERLAPPING WHITE AND BLACK SQUARES", + direction="on", + linebreak="al", + unicodeslot=0x2BBB, + }, + [0x2BBC]={ + category="so", + description="OVERLAPPING BLACK SQUARES", + direction="on", + linebreak="al", + unicodeslot=0x2BBC, + }, [0x2BBD]={ category="so", description="BALLOT BOX WITH LIGHT X", @@ -85145,6 +85850,181 @@ characters.data={ linebreak="al", unicodeslot=0x2BD2, }, + [0x2BD3]={ + category="so", + description="PLUTO FORM TWO", + direction="on", + linebreak="al", + unicodeslot=0x2BD3, + }, + [0x2BD4]={ + category="so", + description="PLUTO FORM THREE", + direction="on", + linebreak="al", + unicodeslot=0x2BD4, + }, + [0x2BD5]={ + category="so", + description="PLUTO FORM FOUR", + direction="on", + linebreak="al", + unicodeslot=0x2BD5, + }, + [0x2BD6]={ + category="so", + description="PLUTO FORM FIVE", + direction="on", + linebreak="al", + unicodeslot=0x2BD6, + }, + [0x2BD7]={ + category="so", + description="TRANSPLUTO", + direction="on", + linebreak="al", + unicodeslot=0x2BD7, + }, + [0x2BD8]={ + category="so", + description="PROSERPINA", + direction="on", + linebreak="al", + unicodeslot=0x2BD8, + }, + [0x2BD9]={ + category="so", + description="ASTRAEA", + direction="on", + linebreak="al", + unicodeslot=0x2BD9, + }, + [0x2BDA]={ + category="so", + description="HYGIEA", + direction="on", + linebreak="al", + unicodeslot=0x2BDA, + }, + [0x2BDB]={ + category="so", + description="PHOLUS", + direction="on", + linebreak="al", + unicodeslot=0x2BDB, + }, + [0x2BDC]={ + category="so", + description="NESSUS", + direction="on", + linebreak="al", + unicodeslot=0x2BDC, + }, + [0x2BDD]={ + category="so", + description="WHITE MOON SELENA", + direction="on", + linebreak="al", + unicodeslot=0x2BDD, + }, + [0x2BDE]={ + category="so", + description="BLACK DIAMOND ON CROSS", + direction="on", + linebreak="al", + unicodeslot=0x2BDE, + }, + [0x2BDF]={ + category="so", + description="TRUE LIGHT MOON ARTA", + direction="on", + linebreak="al", + unicodeslot=0x2BDF, + }, + [0x2BE0]={ + category="so", + description="CUPIDO", + direction="on", + linebreak="al", + unicodeslot=0x2BE0, + }, + [0x2BE1]={ + category="so", + description="HADES", + direction="on", + linebreak="al", + unicodeslot=0x2BE1, + }, + [0x2BE2]={ + category="so", + description="ZEUS", + direction="on", + linebreak="al", + unicodeslot=0x2BE2, + }, + [0x2BE3]={ + category="so", + description="KRONOS", + direction="on", + linebreak="al", + unicodeslot=0x2BE3, + }, + [0x2BE4]={ + category="so", + description="APOLLON", + direction="on", + linebreak="al", + unicodeslot=0x2BE4, + }, + [0x2BE5]={ + category="so", + description="ADMETOS", + direction="on", + linebreak="al", + unicodeslot=0x2BE5, + }, + [0x2BE6]={ + category="so", + description="VULCANUS", + direction="on", + linebreak="al", + unicodeslot=0x2BE6, + }, + [0x2BE7]={ + category="so", + description="POSEIDON", + direction="on", + linebreak="al", + unicodeslot=0x2BE7, + }, + [0x2BE8]={ + category="so", + description="LEFT HALF BLACK STAR", + direction="on", + linebreak="al", + unicodeslot=0x2BE8, + }, + [0x2BE9]={ + category="so", + description="RIGHT HALF BLACK STAR", + direction="on", + linebreak="al", + unicodeslot=0x2BE9, + }, + [0x2BEA]={ + category="so", + description="STAR WITH LEFT HALF BLACK", + direction="on", + linebreak="al", + unicodeslot=0x2BEA, + }, + [0x2BEB]={ + category="so", + description="STAR WITH RIGHT HALF BLACK", + direction="on", + linebreak="al", + unicodeslot=0x2BEB, + }, [0x2BEC]={ category="so", description="LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS", @@ -85173,6 +86053,112 @@ characters.data={ linebreak="al", unicodeslot=0x2BEF, }, + [0x2BF0]={ + category="so", + description="ERIS FORM ONE", + direction="on", + linebreak="al", + unicodeslot=0x2BF0, + }, + [0x2BF1]={ + category="so", + description="ERIS FORM TWO", + direction="on", + linebreak="al", + unicodeslot=0x2BF1, + }, + [0x2BF2]={ + category="so", + description="SEDNA", + direction="on", + linebreak="al", + unicodeslot=0x2BF2, + }, + [0x2BF3]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL VIGINTILE", + direction="on", + linebreak="al", + unicodeslot=0x2BF3, + }, + [0x2BF4]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL NOVILE", + direction="on", + linebreak="al", + unicodeslot=0x2BF4, + }, + [0x2BF5]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL QUINTILE", + direction="on", + linebreak="al", + unicodeslot=0x2BF5, + }, + [0x2BF6]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL BINOVILE", + direction="on", + linebreak="al", + unicodeslot=0x2BF6, + }, + [0x2BF7]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL SENTAGON", + direction="on", + linebreak="al", + unicodeslot=0x2BF7, + }, + [0x2BF8]={ + category="so", + description="RUSSIAN ASTROLOGICAL SYMBOL TREDECILE", + direction="on", + linebreak="al", + unicodeslot=0x2BF8, + }, + [0x2BF9]={ + category="so", + description="EQUALS SIGN WITH INFINITY BELOW", + direction="on", + linebreak="al", + unicodeslot=0x2BF9, + }, + [0x2BFA]={ + category="so", + description="UNITED SYMBOL", + direction="on", + linebreak="al", + unicodeslot=0x2BFA, + }, + [0x2BFB]={ + category="so", + description="SEPARATED SYMBOL", + direction="on", + linebreak="al", + unicodeslot=0x2BFB, + }, + [0x2BFC]={ + category="so", + description="DOUBLED SYMBOL", + direction="on", + linebreak="al", + unicodeslot=0x2BFC, + }, + [0x2BFD]={ + category="so", + description="PASSED SYMBOL", + direction="on", + linebreak="al", + unicodeslot=0x2BFD, + }, + [0x2BFE]={ + category="so", + description="REVERSED RIGHT ANGLE", + direction="on", + linebreak="al", + mirror=0x221F, + unicodeslot=0x2BFE, + }, [0x2C00]={ category="lu", description="GLAGOLITIC CAPITAL LETTER AZU", @@ -89226,6 +90212,41 @@ characters.data={ linebreak="ba", unicodeslot=0x2E49, }, + [0x2E4A]={ + category="po", + description="DOTTED SOLIDUS", + direction="on", + linebreak="ba", + unicodeslot=0x2E4A, + }, + [0x2E4B]={ + category="po", + description="TRIPLE DAGGER", + direction="on", + linebreak="al", + unicodeslot=0x2E4B, + }, + [0x2E4C]={ + category="po", + description="MEDIEVAL COMMA", + direction="on", + linebreak="ba", + unicodeslot=0x2E4C, + }, + [0x2E4D]={ + category="po", + description="PARAGRAPHUS MARK", + direction="on", + linebreak="al", + unicodeslot=0x2E4D, + }, + [0x2E4E]={ + category="po", + description="PUNCTUS ELEVATUS MARK", + direction="on", + linebreak="ba", + unicodeslot=0x2E4E, + }, [0x2E80]={ category="so", cjkwd="w", @@ -95434,6 +96455,14 @@ characters.data={ linebreak="id", unicodeslot=0x312E, }, + [0x312F]={ + category="lo", + cjkwd="w", + description="BOPOMOFO LETTER NN", + direction="l", + linebreak="id", + unicodeslot=0x312F, + }, [0x3131]={ adobename="kiyeokkorean", category="lo", @@ -117174,6 +118203,13 @@ characters.data={ linebreak="al", unicodeslot=0xA7AE, }, + [0xA7AF]={ + category="ll", + description="LATIN LETTER SMALL CAPITAL Q", + direction="l", + linebreak="al", + unicodeslot=0xA7AF, + }, [0xA7B0]={ category="lu", description="LATIN CAPITAL LETTER TURNED K", @@ -117230,6 +118266,20 @@ characters.data={ linebreak="al", unicodeslot=0xA7B7, }, + [0xA7B8]={ + category="lu", + description="LATIN CAPITAL LETTER U WITH STROKE", + direction="l", + linebreak="al", + unicodeslot=0xA7B8, + }, + [0xA7B9]={ + category="ll", + description="LATIN SMALL LETTER U WITH STROKE", + direction="l", + linebreak="al", + unicodeslot=0xA7B9, + }, [0xA7F7]={ category="lo", description="LATIN EPIGRAPHIC LETTER SIDEWAYS I", @@ -118975,6 +120025,20 @@ characters.data={ linebreak="al", unicodeslot=0xA8FD, }, + [0xA8FE]={ + category="lo", + description="DEVANAGARI LETTER AY", + direction="l", + linebreak="al", + unicodeslot=0xA8FE, + }, + [0xA8FF]={ + category="mn", + description="DEVANAGARI VOWEL SIGN AY", + direction="nsm", + linebreak="cm", + unicodeslot=0xA8FF, + }, [0xA900]={ category="nd", description="KAYAH LI DIGIT ZERO", @@ -120449,6 +121513,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN GHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E0, }, @@ -120456,6 +121521,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN CHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E1, }, @@ -120463,6 +121529,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN JHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E2, }, @@ -120470,6 +121537,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN NNA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E3, }, @@ -120477,6 +121545,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHAN BHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E4, }, @@ -120484,6 +121553,8 @@ characters.data={ category="mn", description="MYANMAR SIGN SHAN SAW", direction="nsm", + indic="d", + indicmark="t", linebreak="sa", unicodeslot=0xA9E5, }, @@ -120491,6 +121562,7 @@ characters.data={ category="lm", description="MYANMAR MODIFIER LETTER SHAN REDUPLICATION", direction="l", + indic="o", linebreak="sa", unicodeslot=0xA9E6, }, @@ -120498,6 +121570,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING NYA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E7, }, @@ -120505,6 +121578,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING FA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E8, }, @@ -120512,6 +121586,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING GA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9E9, }, @@ -120519,6 +121594,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING GHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9EA, }, @@ -120526,6 +121602,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING JA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9EB, }, @@ -120533,6 +121610,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING JHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9EC, }, @@ -120540,6 +121618,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING DDA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9ED, }, @@ -120547,6 +121626,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING DDHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9EE, }, @@ -120554,6 +121634,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING NNA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9EF, }, @@ -120561,6 +121642,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT ZERO", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F0, }, @@ -120568,6 +121650,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT ONE", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F1, }, @@ -120575,6 +121658,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT TWO", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F2, }, @@ -120582,6 +121666,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT THREE", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F3, }, @@ -120589,6 +121674,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT FOUR", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F4, }, @@ -120596,6 +121682,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT FIVE", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F5, }, @@ -120603,6 +121690,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT SIX", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F6, }, @@ -120610,6 +121698,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT SEVEN", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F7, }, @@ -120617,6 +121706,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT EIGHT", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F8, }, @@ -120624,6 +121714,7 @@ characters.data={ category="nd", description="MYANMAR TAI LAING DIGIT NINE", direction="l", + indic="o", linebreak="nu", unicodeslot=0xA9F9, }, @@ -120631,6 +121722,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING LLA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9FA, }, @@ -120638,6 +121730,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING DA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9FB, }, @@ -120645,6 +121738,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING DHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9FC, }, @@ -120652,6 +121746,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING BA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9FD, }, @@ -120659,6 +121754,7 @@ characters.data={ category="lo", description="MYANMAR LETTER TAI LAING BHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xA9FE, }, @@ -121247,6 +122343,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI GA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA60, variants={ @@ -121257,6 +122354,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI CA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA61, variants={ @@ -121267,6 +122365,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI CHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA62, variants={ @@ -121277,6 +122376,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI JA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA63, variants={ @@ -121287,6 +122387,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI JHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA64, variants={ @@ -121297,6 +122398,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI NYA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA65, variants={ @@ -121307,6 +122409,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI TTA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA66, variants={ @@ -121317,6 +122420,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI TTHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA67, }, @@ -121324,6 +122428,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI DDA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA68, }, @@ -121331,6 +122436,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI DDHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA69, }, @@ -121338,6 +122444,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI DHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA6A, }, @@ -121355,6 +122462,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI SA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA6C, variants={ @@ -121365,6 +122473,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI HA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA6D, }, @@ -121372,6 +122481,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI HHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA6E, }, @@ -121379,6 +122489,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI FA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA6F, variants={ @@ -121389,6 +122500,7 @@ characters.data={ category="lm", description="MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION", direction="l", + indic="o", linebreak="sa", unicodeslot=0xAA70, }, @@ -121396,6 +122508,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI XA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA71, }, @@ -121403,6 +122516,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI ZA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA72, }, @@ -121410,6 +122524,7 @@ characters.data={ category="lo", description="MYANMAR LETTER KHAMTI RA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA73, }, @@ -121417,6 +122532,7 @@ characters.data={ category="lo", description="MYANMAR LOGOGRAM KHAMTI OAY", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA74, }, @@ -121424,6 +122540,7 @@ characters.data={ category="lo", description="MYANMAR LOGOGRAM KHAMTI QN", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA75, }, @@ -121431,6 +122548,7 @@ characters.data={ category="lo", description="MYANMAR LOGOGRAM KHAMTI HM", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA76, }, @@ -121438,6 +122556,7 @@ characters.data={ category="so", description="MYANMAR SYMBOL AITON EXCLAMATION", direction="l", + indic="o", linebreak="sa", unicodeslot=0xAA77, }, @@ -121445,6 +122564,7 @@ characters.data={ category="so", description="MYANMAR SYMBOL AITON ONE", direction="l", + indic="o", linebreak="sa", unicodeslot=0xAA78, }, @@ -121452,6 +122572,7 @@ characters.data={ category="so", description="MYANMAR SYMBOL AITON TWO", direction="l", + indic="o", linebreak="sa", unicodeslot=0xAA79, }, @@ -121459,6 +122580,7 @@ characters.data={ category="lo", description="MYANMAR LETTER AITON RA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA7A, variants={ @@ -121469,6 +122591,8 @@ characters.data={ category="mc", description="MYANMAR SIGN PAO KAREN TONE", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0xAA7B, }, @@ -121476,6 +122600,8 @@ characters.data={ category="mn", description="MYANMAR SIGN TAI LAING TONE-2", direction="nsm", + indic="s", + indicmark="t", linebreak="sa", unicodeslot=0xAA7C, }, @@ -121483,6 +122609,8 @@ characters.data={ category="mc", description="MYANMAR SIGN TAI LAING TONE-5", direction="l", + indic="s", + indicmark="r", linebreak="sa", unicodeslot=0xAA7D, }, @@ -121490,6 +122618,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHWE PALAUNG CHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA7E, }, @@ -121497,6 +122626,7 @@ characters.data={ category="lo", description="MYANMAR LETTER SHWE PALAUNG SHA", direction="l", + indic="c", linebreak="sa", unicodeslot=0xAA7F, }, @@ -136230,6 +137360,9 @@ characters.data={ linebreak="id", specials={ "wide", 0x30 }, unicodeslot=0xFF10, + variants={ + [0xFE00]="short diagonal stroke form", + }, }, [0xFF11]={ adobename="onemonospace", @@ -150982,6 +152115,20 @@ characters.data={ linebreak="al", unicodeslot=0x10A33, }, + [0x10A34]={ + category="lo", + description="KHAROSHTHI LETTER TTTA", + direction="r", + linebreak="al", + unicodeslot=0x10A34, + }, + [0x10A35]={ + category="lo", + description="KHAROSHTHI LETTER VHA", + direction="r", + linebreak="al", + unicodeslot=0x10A35, + }, [0x10A38]={ category="mn", combining=0xE6, @@ -151070,6 +152217,13 @@ characters.data={ linebreak="al", unicodeslot=0x10A47, }, + [0x10A48]={ + category="no", + description="KHAROSHTHI FRACTION ONE HALF", + direction="r", + linebreak="al", + unicodeslot=0x10A48, + }, [0x10A50]={ category="po", description="KHAROSHTHI PUNCTUATION DOT", @@ -154318,6 +155472,396 @@ characters.data={ linebreak="al", unicodeslot=0x10CFF, }, + [0x10D00]={ + arabic="l", + category="lo", + description="HANIFI ROHINGYA LETTER A", + direction="al", + linebreak="al", + unicodeslot=0x10D00, + }, + [0x10D01]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER BA", + direction="al", + linebreak="al", + unicodeslot=0x10D01, + }, + [0x10D02]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER PA", + direction="al", + linebreak="al", + unicodeslot=0x10D02, + }, + [0x10D03]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER TA", + direction="al", + linebreak="al", + unicodeslot=0x10D03, + }, + [0x10D04]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER TTA", + direction="al", + linebreak="al", + unicodeslot=0x10D04, + }, + [0x10D05]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER JA", + direction="al", + linebreak="al", + unicodeslot=0x10D05, + }, + [0x10D06]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER CA", + direction="al", + linebreak="al", + unicodeslot=0x10D06, + }, + [0x10D07]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER HA", + direction="al", + linebreak="al", + unicodeslot=0x10D07, + }, + [0x10D08]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER KHA", + direction="al", + linebreak="al", + unicodeslot=0x10D08, + }, + [0x10D09]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER FA", + direction="al", + linebreak="al", + unicodeslot=0x10D09, + }, + [0x10D0A]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER DA", + direction="al", + linebreak="al", + unicodeslot=0x10D0A, + }, + [0x10D0B]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER DDA", + direction="al", + linebreak="al", + unicodeslot=0x10D0B, + }, + [0x10D0C]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER RA", + direction="al", + linebreak="al", + unicodeslot=0x10D0C, + }, + [0x10D0D]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER RRA", + direction="al", + linebreak="al", + unicodeslot=0x10D0D, + }, + [0x10D0E]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER ZA", + direction="al", + linebreak="al", + unicodeslot=0x10D0E, + }, + [0x10D0F]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER SA", + direction="al", + linebreak="al", + unicodeslot=0x10D0F, + }, + [0x10D10]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER SHA", + direction="al", + linebreak="al", + unicodeslot=0x10D10, + }, + [0x10D11]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER KA", + direction="al", + linebreak="al", + unicodeslot=0x10D11, + }, + [0x10D12]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER GA", + direction="al", + linebreak="al", + unicodeslot=0x10D12, + }, + [0x10D13]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER LA", + direction="al", + linebreak="al", + unicodeslot=0x10D13, + }, + [0x10D14]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER MA", + direction="al", + linebreak="al", + unicodeslot=0x10D14, + }, + [0x10D15]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER NA", + direction="al", + linebreak="al", + unicodeslot=0x10D15, + }, + [0x10D16]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER WA", + direction="al", + linebreak="al", + unicodeslot=0x10D16, + }, + [0x10D17]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER KINNA WA", + direction="al", + linebreak="al", + unicodeslot=0x10D17, + }, + [0x10D18]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER YA", + direction="al", + linebreak="al", + unicodeslot=0x10D18, + }, + [0x10D19]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER KINNA YA", + direction="al", + linebreak="al", + unicodeslot=0x10D19, + }, + [0x10D1A]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER NGA", + direction="al", + linebreak="al", + unicodeslot=0x10D1A, + }, + [0x10D1B]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER NYA", + direction="al", + linebreak="al", + unicodeslot=0x10D1B, + }, + [0x10D1C]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA LETTER VA", + direction="al", + linebreak="al", + unicodeslot=0x10D1C, + }, + [0x10D1D]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA VOWEL A", + direction="al", + linebreak="al", + unicodeslot=0x10D1D, + }, + [0x10D1E]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA VOWEL I", + direction="al", + linebreak="al", + unicodeslot=0x10D1E, + }, + [0x10D1F]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA VOWEL U", + direction="al", + linebreak="al", + unicodeslot=0x10D1F, + }, + [0x10D20]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA VOWEL E", + direction="al", + linebreak="al", + unicodeslot=0x10D20, + }, + [0x10D21]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA VOWEL O", + direction="al", + linebreak="al", + unicodeslot=0x10D21, + }, + [0x10D22]={ + arabic="r", + category="lo", + description="HANIFI ROHINGYA MARK SAKIN", + direction="al", + linebreak="al", + unicodeslot=0x10D22, + }, + [0x10D23]={ + arabic="d", + category="lo", + description="HANIFI ROHINGYA MARK NA KHONNA", + direction="al", + linebreak="al", + unicodeslot=0x10D23, + }, + [0x10D24]={ + category="mn", + combining=0xE6, + description="HANIFI ROHINGYA SIGN HARBAHAY", + direction="nsm", + linebreak="cm", + unicodeslot=0x10D24, + }, + [0x10D25]={ + category="mn", + combining=0xE6, + description="HANIFI ROHINGYA SIGN TAHALA", + direction="nsm", + linebreak="cm", + unicodeslot=0x10D25, + }, + [0x10D26]={ + category="mn", + combining=0xE6, + description="HANIFI ROHINGYA SIGN TANA", + direction="nsm", + linebreak="cm", + unicodeslot=0x10D26, + }, + [0x10D27]={ + category="mn", + combining=0xE6, + description="HANIFI ROHINGYA SIGN TASSI", + direction="nsm", + linebreak="cm", + unicodeslot=0x10D27, + }, + [0x10D30]={ + category="nd", + description="HANIFI ROHINGYA DIGIT ZERO", + direction="an", + linebreak="nu", + unicodeslot=0x10D30, + }, + [0x10D31]={ + category="nd", + description="HANIFI ROHINGYA DIGIT ONE", + direction="an", + linebreak="nu", + unicodeslot=0x10D31, + }, + [0x10D32]={ + category="nd", + description="HANIFI ROHINGYA DIGIT TWO", + direction="an", + linebreak="nu", + unicodeslot=0x10D32, + }, + [0x10D33]={ + category="nd", + description="HANIFI ROHINGYA DIGIT THREE", + direction="an", + linebreak="nu", + unicodeslot=0x10D33, + }, + [0x10D34]={ + category="nd", + description="HANIFI ROHINGYA DIGIT FOUR", + direction="an", + linebreak="nu", + unicodeslot=0x10D34, + }, + [0x10D35]={ + category="nd", + description="HANIFI ROHINGYA DIGIT FIVE", + direction="an", + linebreak="nu", + unicodeslot=0x10D35, + }, + [0x10D36]={ + category="nd", + description="HANIFI ROHINGYA DIGIT SIX", + direction="an", + linebreak="nu", + unicodeslot=0x10D36, + }, + [0x10D37]={ + category="nd", + description="HANIFI ROHINGYA DIGIT SEVEN", + direction="an", + linebreak="nu", + unicodeslot=0x10D37, + }, + [0x10D38]={ + category="nd", + description="HANIFI ROHINGYA DIGIT EIGHT", + direction="an", + linebreak="nu", + unicodeslot=0x10D38, + }, + [0x10D39]={ + category="nd", + description="HANIFI ROHINGYA DIGIT NINE", + direction="an", + linebreak="nu", + unicodeslot=0x10D39, + }, [0x10E60]={ category="no", description="RUMI DIGIT ONE", @@ -154535,6 +156079,617 @@ characters.data={ linebreak="al", unicodeslot=0x10E7E, }, + [0x10F00]={ + category="lo", + description="OLD SOGDIAN LETTER ALEPH", + direction="r", + linebreak="al", + unicodeslot=0x10F00, + }, + [0x10F01]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL ALEPH", + direction="r", + linebreak="al", + unicodeslot=0x10F01, + }, + [0x10F02]={ + category="lo", + description="OLD SOGDIAN LETTER BETH", + direction="r", + linebreak="al", + unicodeslot=0x10F02, + }, + [0x10F03]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL BETH", + direction="r", + linebreak="al", + unicodeslot=0x10F03, + }, + [0x10F04]={ + category="lo", + description="OLD SOGDIAN LETTER GIMEL", + direction="r", + linebreak="al", + unicodeslot=0x10F04, + }, + [0x10F05]={ + category="lo", + description="OLD SOGDIAN LETTER HE", + direction="r", + linebreak="al", + unicodeslot=0x10F05, + }, + [0x10F06]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL HE", + direction="r", + linebreak="al", + unicodeslot=0x10F06, + }, + [0x10F07]={ + category="lo", + description="OLD SOGDIAN LETTER WAW", + direction="r", + linebreak="al", + unicodeslot=0x10F07, + }, + [0x10F08]={ + category="lo", + description="OLD SOGDIAN LETTER ZAYIN", + direction="r", + linebreak="al", + unicodeslot=0x10F08, + }, + [0x10F09]={ + category="lo", + description="OLD SOGDIAN LETTER HETH", + direction="r", + linebreak="al", + unicodeslot=0x10F09, + }, + [0x10F0A]={ + category="lo", + description="OLD SOGDIAN LETTER YODH", + direction="r", + linebreak="al", + unicodeslot=0x10F0A, + }, + [0x10F0B]={ + category="lo", + description="OLD SOGDIAN LETTER KAPH", + direction="r", + linebreak="al", + unicodeslot=0x10F0B, + }, + [0x10F0C]={ + category="lo", + description="OLD SOGDIAN LETTER LAMEDH", + direction="r", + linebreak="al", + unicodeslot=0x10F0C, + }, + [0x10F0D]={ + category="lo", + description="OLD SOGDIAN LETTER MEM", + direction="r", + linebreak="al", + unicodeslot=0x10F0D, + }, + [0x10F0E]={ + category="lo", + description="OLD SOGDIAN LETTER NUN", + direction="r", + linebreak="al", + unicodeslot=0x10F0E, + }, + [0x10F0F]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL NUN", + direction="r", + linebreak="al", + unicodeslot=0x10F0F, + }, + [0x10F10]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL NUN WITH VERTICAL TAIL", + direction="r", + linebreak="al", + unicodeslot=0x10F10, + }, + [0x10F11]={ + category="lo", + description="OLD SOGDIAN LETTER SAMEKH", + direction="r", + linebreak="al", + unicodeslot=0x10F11, + }, + [0x10F12]={ + category="lo", + description="OLD SOGDIAN LETTER AYIN", + direction="r", + linebreak="al", + unicodeslot=0x10F12, + }, + [0x10F13]={ + category="lo", + description="OLD SOGDIAN LETTER ALTERNATE AYIN", + direction="r", + linebreak="al", + unicodeslot=0x10F13, + }, + [0x10F14]={ + category="lo", + description="OLD SOGDIAN LETTER PE", + direction="r", + linebreak="al", + unicodeslot=0x10F14, + }, + [0x10F15]={ + category="lo", + description="OLD SOGDIAN LETTER SADHE", + direction="r", + linebreak="al", + unicodeslot=0x10F15, + }, + [0x10F16]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL SADHE", + direction="r", + linebreak="al", + unicodeslot=0x10F16, + }, + [0x10F17]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL SADHE WITH VERTICAL TAIL", + direction="r", + linebreak="al", + unicodeslot=0x10F17, + }, + [0x10F18]={ + category="lo", + description="OLD SOGDIAN LETTER RESH-AYIN-DALETH", + direction="r", + linebreak="al", + unicodeslot=0x10F18, + }, + [0x10F19]={ + category="lo", + description="OLD SOGDIAN LETTER SHIN", + direction="r", + linebreak="al", + unicodeslot=0x10F19, + }, + [0x10F1A]={ + category="lo", + description="OLD SOGDIAN LETTER TAW", + direction="r", + linebreak="al", + unicodeslot=0x10F1A, + }, + [0x10F1B]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL TAW", + direction="r", + linebreak="al", + unicodeslot=0x10F1B, + }, + [0x10F1C]={ + category="lo", + description="OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL", + direction="r", + linebreak="al", + unicodeslot=0x10F1C, + }, + [0x10F1D]={ + category="no", + description="OLD SOGDIAN NUMBER ONE", + direction="r", + linebreak="al", + unicodeslot=0x10F1D, + }, + [0x10F1E]={ + category="no", + description="OLD SOGDIAN NUMBER TWO", + direction="r", + linebreak="al", + unicodeslot=0x10F1E, + }, + [0x10F1F]={ + category="no", + description="OLD SOGDIAN NUMBER THREE", + direction="r", + linebreak="al", + unicodeslot=0x10F1F, + }, + [0x10F20]={ + category="no", + description="OLD SOGDIAN NUMBER FOUR", + direction="r", + linebreak="al", + unicodeslot=0x10F20, + }, + [0x10F21]={ + category="no", + description="OLD SOGDIAN NUMBER FIVE", + direction="r", + linebreak="al", + unicodeslot=0x10F21, + }, + [0x10F22]={ + category="no", + description="OLD SOGDIAN NUMBER TEN", + direction="r", + linebreak="al", + unicodeslot=0x10F22, + }, + [0x10F23]={ + category="no", + description="OLD SOGDIAN NUMBER TWENTY", + direction="r", + linebreak="al", + unicodeslot=0x10F23, + }, + [0x10F24]={ + category="no", + description="OLD SOGDIAN NUMBER THIRTY", + direction="r", + linebreak="al", + unicodeslot=0x10F24, + }, + [0x10F25]={ + category="no", + description="OLD SOGDIAN NUMBER ONE HUNDRED", + direction="r", + linebreak="al", + unicodeslot=0x10F25, + }, + [0x10F26]={ + category="no", + description="OLD SOGDIAN FRACTION ONE HALF", + direction="r", + linebreak="al", + unicodeslot=0x10F26, + }, + [0x10F27]={ + category="lo", + description="OLD SOGDIAN LIGATURE AYIN-DALETH", + direction="r", + linebreak="al", + unicodeslot=0x10F27, + }, + [0x10F30]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER ALEPH", + direction="al", + linebreak="al", + unicodeslot=0x10F30, + }, + [0x10F31]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER BETH", + direction="al", + linebreak="al", + unicodeslot=0x10F31, + }, + [0x10F32]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER GIMEL", + direction="al", + linebreak="al", + unicodeslot=0x10F32, + }, + [0x10F33]={ + arabic="r", + category="lo", + description="SOGDIAN LETTER HE", + direction="al", + linebreak="al", + unicodeslot=0x10F33, + }, + [0x10F34]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER WAW", + direction="al", + linebreak="al", + unicodeslot=0x10F34, + }, + [0x10F35]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER ZAYIN", + direction="al", + linebreak="al", + unicodeslot=0x10F35, + }, + [0x10F36]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER HETH", + direction="al", + linebreak="al", + unicodeslot=0x10F36, + }, + [0x10F37]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER YODH", + direction="al", + linebreak="al", + unicodeslot=0x10F37, + }, + [0x10F38]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER KAPH", + direction="al", + linebreak="al", + unicodeslot=0x10F38, + }, + [0x10F39]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER LAMEDH", + direction="al", + linebreak="al", + unicodeslot=0x10F39, + }, + [0x10F3A]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER MEM", + direction="al", + linebreak="al", + unicodeslot=0x10F3A, + }, + [0x10F3B]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER NUN", + direction="al", + linebreak="al", + unicodeslot=0x10F3B, + }, + [0x10F3C]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER SAMEKH", + direction="al", + linebreak="al", + unicodeslot=0x10F3C, + }, + [0x10F3D]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER AYIN", + direction="al", + linebreak="al", + unicodeslot=0x10F3D, + }, + [0x10F3E]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER PE", + direction="al", + linebreak="al", + unicodeslot=0x10F3E, + }, + [0x10F3F]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER SADHE", + direction="al", + linebreak="al", + unicodeslot=0x10F3F, + }, + [0x10F40]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER RESH-AYIN", + direction="al", + linebreak="al", + unicodeslot=0x10F40, + }, + [0x10F41]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER SHIN", + direction="al", + linebreak="al", + unicodeslot=0x10F41, + }, + [0x10F42]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER TAW", + direction="al", + linebreak="al", + unicodeslot=0x10F42, + }, + [0x10F43]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER FETH", + direction="al", + linebreak="al", + unicodeslot=0x10F43, + }, + [0x10F44]={ + arabic="d", + category="lo", + description="SOGDIAN LETTER LESH", + direction="al", + linebreak="al", + unicodeslot=0x10F44, + }, + [0x10F45]={ + arabic="u", + category="lo", + description="SOGDIAN INDEPENDENT SHIN", + direction="al", + linebreak="al", + unicodeslot=0x10F45, + }, + [0x10F46]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING DOT BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F46, + }, + [0x10F47]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING TWO DOTS BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F47, + }, + [0x10F48]={ + category="mn", + combining=0xE6, + description="SOGDIAN COMBINING DOT ABOVE", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F48, + }, + [0x10F49]={ + category="mn", + combining=0xE6, + description="SOGDIAN COMBINING TWO DOTS ABOVE", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F49, + }, + [0x10F4A]={ + category="mn", + combining=0xE6, + description="SOGDIAN COMBINING CURVE ABOVE", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4A, + }, + [0x10F4B]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING CURVE BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4B, + }, + [0x10F4C]={ + category="mn", + combining=0xE6, + description="SOGDIAN COMBINING HOOK ABOVE", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4C, + }, + [0x10F4D]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING HOOK BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4D, + }, + [0x10F4E]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING LONG HOOK BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4E, + }, + [0x10F4F]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING RESH BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F4F, + }, + [0x10F50]={ + category="mn", + combining=0xDC, + description="SOGDIAN COMBINING STROKE BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x10F50, + }, + [0x10F51]={ + arabic="d", + category="no", + description="SOGDIAN NUMBER ONE", + direction="al", + linebreak="al", + unicodeslot=0x10F51, + }, + [0x10F52]={ + arabic="d", + category="no", + description="SOGDIAN NUMBER TEN", + direction="al", + linebreak="al", + unicodeslot=0x10F52, + }, + [0x10F53]={ + arabic="d", + category="no", + description="SOGDIAN NUMBER TWENTY", + direction="al", + linebreak="al", + unicodeslot=0x10F53, + }, + [0x10F54]={ + arabic="r", + category="no", + description="SOGDIAN NUMBER ONE HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x10F54, + }, + [0x10F55]={ + category="po", + description="SOGDIAN PUNCTUATION TWO VERTICAL BARS", + direction="al", + linebreak="al", + unicodeslot=0x10F55, + }, + [0x10F56]={ + category="po", + description="SOGDIAN PUNCTUATION TWO VERTICAL BARS WITH DOTS", + direction="al", + linebreak="al", + unicodeslot=0x10F56, + }, + [0x10F57]={ + category="po", + description="SOGDIAN PUNCTUATION CIRCLE WITH DOT", + direction="al", + linebreak="al", + unicodeslot=0x10F57, + }, + [0x10F58]={ + category="po", + description="SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS", + direction="al", + linebreak="al", + unicodeslot=0x10F58, + }, + [0x10F59]={ + category="po", + description="SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT", + direction="al", + linebreak="al", + unicodeslot=0x10F59, + }, [0x11000]={ category="mc", description="BRAHMI SIGN CANDRABINDU", @@ -155733,6 +157888,7 @@ characters.data={ unicodeslot=0x110BC, }, [0x110BD]={ + arabic="u", category="cf", description="KAITHI NUMBER SIGN", direction="l", @@ -155767,6 +157923,14 @@ characters.data={ linebreak="ba", unicodeslot=0x110C1, }, + [0x110CD]={ + arabic="u", + category="cf", + description="KAITHI NUMBER SIGN ABOVE", + direction="l", + linebreak="al", + unicodeslot=0x110CD, + }, [0x110D0]={ category="lo", description="SORA SOMPENG LETTER SAH", @@ -156488,6 +158652,27 @@ characters.data={ linebreak="ba", unicodeslot=0x11143, }, + [0x11144]={ + category="lo", + description="CHAKMA LETTER LHAA", + direction="l", + linebreak="al", + unicodeslot=0x11144, + }, + [0x11145]={ + category="mc", + description="CHAKMA VOWEL SIGN AA", + direction="l", + linebreak="cm", + unicodeslot=0x11145, + }, + [0x11146]={ + category="mc", + description="CHAKMA VOWEL SIGN EI", + direction="l", + linebreak="cm", + unicodeslot=0x11146, + }, [0x11150]={ category="lo", description="MAHAJANI LETTER A", @@ -157277,8 +159462,8 @@ characters.data={ [0x111C9]={ category="po", description="SHARADA SANDHI MARK", - direction="l", - linebreak="al", + direction="nsm", + linebreak="cm", unicodeslot=0x111C9, }, [0x111CA]={ @@ -159099,6 +161284,14 @@ characters.data={ linebreak="al", unicodeslot=0x11339, }, + [0x1133B]={ + category="mn", + combining=0x7, + description="COMBINING BINDU BELOW", + direction="nsm", + linebreak="cm", + unicodeslot=0x1133B, + }, [0x1133C]={ category="mn", combining=0x7, @@ -160006,6 +162199,14 @@ characters.data={ linebreak="al", unicodeslot=0x1145D, }, + [0x1145E]={ + category="mn", + combining=0xE6, + description="NEWA SANDHI MARK", + direction="nsm", + linebreak="cm", + unicodeslot=0x1145E, + }, [0x11480]={ category="lo", description="TIRHUTA ANJI", @@ -162524,6 +164725,13 @@ characters.data={ linebreak="sa", unicodeslot=0x11719, }, + [0x1171A]={ + category="lo", + description="AHOM LETTER ALTERNATE BA", + direction="l", + linebreak="sa", + unicodeslot=0x1171A, + }, [0x1171D]={ category="mn", description="AHOM CONSONANT SIGN MEDIAL LA", @@ -162742,6 +164950,428 @@ characters.data={ linebreak="sa", unicodeslot=0x1173F, }, + [0x11800]={ + category="lo", + description="DOGRA LETTER A", + direction="l", + linebreak="al", + unicodeslot=0x11800, + }, + [0x11801]={ + category="lo", + description="DOGRA LETTER AA", + direction="l", + linebreak="al", + unicodeslot=0x11801, + }, + [0x11802]={ + category="lo", + description="DOGRA LETTER I", + direction="l", + linebreak="al", + unicodeslot=0x11802, + }, + [0x11803]={ + category="lo", + description="DOGRA LETTER II", + direction="l", + linebreak="al", + unicodeslot=0x11803, + }, + [0x11804]={ + category="lo", + description="DOGRA LETTER U", + direction="l", + linebreak="al", + unicodeslot=0x11804, + }, + [0x11805]={ + category="lo", + description="DOGRA LETTER UU", + direction="l", + linebreak="al", + unicodeslot=0x11805, + }, + [0x11806]={ + category="lo", + description="DOGRA LETTER E", + direction="l", + linebreak="al", + unicodeslot=0x11806, + }, + [0x11807]={ + category="lo", + description="DOGRA LETTER AI", + direction="l", + linebreak="al", + unicodeslot=0x11807, + }, + [0x11808]={ + category="lo", + description="DOGRA LETTER O", + direction="l", + linebreak="al", + unicodeslot=0x11808, + }, + [0x11809]={ + category="lo", + description="DOGRA LETTER AU", + direction="l", + linebreak="al", + unicodeslot=0x11809, + }, + [0x1180A]={ + category="lo", + description="DOGRA LETTER KA", + direction="l", + linebreak="al", + unicodeslot=0x1180A, + }, + [0x1180B]={ + category="lo", + description="DOGRA LETTER KHA", + direction="l", + linebreak="al", + unicodeslot=0x1180B, + }, + [0x1180C]={ + category="lo", + description="DOGRA LETTER GA", + direction="l", + linebreak="al", + unicodeslot=0x1180C, + }, + [0x1180D]={ + category="lo", + description="DOGRA LETTER GHA", + direction="l", + linebreak="al", + unicodeslot=0x1180D, + }, + [0x1180E]={ + category="lo", + description="DOGRA LETTER NGA", + direction="l", + linebreak="al", + unicodeslot=0x1180E, + }, + [0x1180F]={ + category="lo", + description="DOGRA LETTER CA", + direction="l", + linebreak="al", + unicodeslot=0x1180F, + }, + [0x11810]={ + category="lo", + description="DOGRA LETTER CHA", + direction="l", + linebreak="al", + unicodeslot=0x11810, + }, + [0x11811]={ + category="lo", + description="DOGRA LETTER JA", + direction="l", + linebreak="al", + unicodeslot=0x11811, + }, + [0x11812]={ + category="lo", + description="DOGRA LETTER JHA", + direction="l", + linebreak="al", + unicodeslot=0x11812, + }, + [0x11813]={ + category="lo", + description="DOGRA LETTER NYA", + direction="l", + linebreak="al", + unicodeslot=0x11813, + }, + [0x11814]={ + category="lo", + description="DOGRA LETTER TTA", + direction="l", + linebreak="al", + unicodeslot=0x11814, + }, + [0x11815]={ + category="lo", + description="DOGRA LETTER TTHA", + direction="l", + linebreak="al", + unicodeslot=0x11815, + }, + [0x11816]={ + category="lo", + description="DOGRA LETTER DDA", + direction="l", + linebreak="al", + unicodeslot=0x11816, + }, + [0x11817]={ + category="lo", + description="DOGRA LETTER DDHA", + direction="l", + linebreak="al", + unicodeslot=0x11817, + }, + [0x11818]={ + category="lo", + description="DOGRA LETTER NNA", + direction="l", + linebreak="al", + unicodeslot=0x11818, + }, + [0x11819]={ + category="lo", + description="DOGRA LETTER TA", + direction="l", + linebreak="al", + unicodeslot=0x11819, + }, + [0x1181A]={ + category="lo", + description="DOGRA LETTER THA", + direction="l", + linebreak="al", + unicodeslot=0x1181A, + }, + [0x1181B]={ + category="lo", + description="DOGRA LETTER DA", + direction="l", + linebreak="al", + unicodeslot=0x1181B, + }, + [0x1181C]={ + category="lo", + description="DOGRA LETTER DHA", + direction="l", + linebreak="al", + unicodeslot=0x1181C, + }, + [0x1181D]={ + category="lo", + description="DOGRA LETTER NA", + direction="l", + linebreak="al", + unicodeslot=0x1181D, + }, + [0x1181E]={ + category="lo", + description="DOGRA LETTER PA", + direction="l", + linebreak="al", + unicodeslot=0x1181E, + }, + [0x1181F]={ + category="lo", + description="DOGRA LETTER PHA", + direction="l", + linebreak="al", + unicodeslot=0x1181F, + }, + [0x11820]={ + category="lo", + description="DOGRA LETTER BA", + direction="l", + linebreak="al", + unicodeslot=0x11820, + }, + [0x11821]={ + category="lo", + description="DOGRA LETTER BHA", + direction="l", + linebreak="al", + unicodeslot=0x11821, + }, + [0x11822]={ + category="lo", + description="DOGRA LETTER MA", + direction="l", + linebreak="al", + unicodeslot=0x11822, + }, + [0x11823]={ + category="lo", + description="DOGRA LETTER YA", + direction="l", + linebreak="al", + unicodeslot=0x11823, + }, + [0x11824]={ + category="lo", + description="DOGRA LETTER RA", + direction="l", + linebreak="al", + unicodeslot=0x11824, + }, + [0x11825]={ + category="lo", + description="DOGRA LETTER LA", + direction="l", + linebreak="al", + unicodeslot=0x11825, + }, + [0x11826]={ + category="lo", + description="DOGRA LETTER VA", + direction="l", + linebreak="al", + unicodeslot=0x11826, + }, + [0x11827]={ + category="lo", + description="DOGRA LETTER SHA", + direction="l", + linebreak="al", + unicodeslot=0x11827, + }, + [0x11828]={ + category="lo", + description="DOGRA LETTER SSA", + direction="l", + linebreak="al", + unicodeslot=0x11828, + }, + [0x11829]={ + category="lo", + description="DOGRA LETTER SA", + direction="l", + linebreak="al", + unicodeslot=0x11829, + }, + [0x1182A]={ + category="lo", + description="DOGRA LETTER HA", + direction="l", + linebreak="al", + unicodeslot=0x1182A, + }, + [0x1182B]={ + category="lo", + description="DOGRA LETTER RRA", + direction="l", + linebreak="al", + unicodeslot=0x1182B, + }, + [0x1182C]={ + category="mc", + description="DOGRA VOWEL SIGN AA", + direction="l", + linebreak="cm", + unicodeslot=0x1182C, + }, + [0x1182D]={ + category="mc", + description="DOGRA VOWEL SIGN I", + direction="l", + linebreak="cm", + unicodeslot=0x1182D, + }, + [0x1182E]={ + category="mc", + description="DOGRA VOWEL SIGN II", + direction="l", + linebreak="cm", + unicodeslot=0x1182E, + }, + [0x1182F]={ + category="mn", + description="DOGRA VOWEL SIGN U", + direction="nsm", + linebreak="cm", + unicodeslot=0x1182F, + }, + [0x11830]={ + category="mn", + description="DOGRA VOWEL SIGN UU", + direction="nsm", + linebreak="cm", + unicodeslot=0x11830, + }, + [0x11831]={ + category="mn", + description="DOGRA VOWEL SIGN VOCALIC R", + direction="nsm", + linebreak="cm", + unicodeslot=0x11831, + }, + [0x11832]={ + category="mn", + description="DOGRA VOWEL SIGN VOCALIC RR", + direction="nsm", + linebreak="cm", + unicodeslot=0x11832, + }, + [0x11833]={ + category="mn", + description="DOGRA VOWEL SIGN E", + direction="nsm", + linebreak="cm", + unicodeslot=0x11833, + }, + [0x11834]={ + category="mn", + description="DOGRA VOWEL SIGN AI", + direction="nsm", + linebreak="cm", + unicodeslot=0x11834, + }, + [0x11835]={ + category="mn", + description="DOGRA VOWEL SIGN O", + direction="nsm", + linebreak="cm", + unicodeslot=0x11835, + }, + [0x11836]={ + category="mn", + description="DOGRA VOWEL SIGN AU", + direction="nsm", + linebreak="cm", + unicodeslot=0x11836, + }, + [0x11837]={ + category="mn", + description="DOGRA SIGN ANUSVARA", + direction="nsm", + linebreak="cm", + unicodeslot=0x11837, + }, + [0x11838]={ + category="mc", + description="DOGRA SIGN VISARGA", + direction="l", + linebreak="cm", + unicodeslot=0x11838, + }, + [0x11839]={ + category="mn", + combining=0x9, + description="DOGRA SIGN VIRAMA", + direction="nsm", + linebreak="cm", + unicodeslot=0x11839, + }, + [0x1183A]={ + category="mn", + combining=0x7, + description="DOGRA SIGN NUKTA", + direction="nsm", + linebreak="cm", + unicodeslot=0x1183A, + }, + [0x1183B]={ + category="po", + description="DOGRA ABBREVIATION SIGN", + direction="l", + linebreak="al", + unicodeslot=0x1183B, + }, [0x118A0]={ category="lu", description="WARANG CITI CAPITAL LETTER NGAA", @@ -164362,6 +166992,13 @@ characters.data={ linebreak="ba", unicodeslot=0x11A9C, }, + [0x11A9D]={ + category="lo", + description="SOYOMBO MARK PLUTA", + direction="l", + linebreak="al", + unicodeslot=0x11A9D, + }, [0x11A9E]={ category="po", description="SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME", @@ -166480,6 +169117,623 @@ characters.data={ linebreak="nu", unicodeslot=0x11D59, }, + [0x11D60]={ + category="lo", + description="GUNJALA GONDI LETTER A", + direction="l", + linebreak="al", + unicodeslot=0x11D60, + }, + [0x11D61]={ + category="lo", + description="GUNJALA GONDI LETTER AA", + direction="l", + linebreak="al", + unicodeslot=0x11D61, + }, + [0x11D62]={ + category="lo", + description="GUNJALA GONDI LETTER I", + direction="l", + linebreak="al", + unicodeslot=0x11D62, + }, + [0x11D63]={ + category="lo", + description="GUNJALA GONDI LETTER II", + direction="l", + linebreak="al", + unicodeslot=0x11D63, + }, + [0x11D64]={ + category="lo", + description="GUNJALA GONDI LETTER U", + direction="l", + linebreak="al", + unicodeslot=0x11D64, + }, + [0x11D65]={ + category="lo", + description="GUNJALA GONDI LETTER UU", + direction="l", + linebreak="al", + unicodeslot=0x11D65, + }, + [0x11D67]={ + category="lo", + description="GUNJALA GONDI LETTER EE", + direction="l", + linebreak="al", + unicodeslot=0x11D67, + }, + [0x11D68]={ + category="lo", + description="GUNJALA GONDI LETTER AI", + direction="l", + linebreak="al", + unicodeslot=0x11D68, + }, + [0x11D6A]={ + category="lo", + description="GUNJALA GONDI LETTER OO", + direction="l", + linebreak="al", + unicodeslot=0x11D6A, + }, + [0x11D6B]={ + category="lo", + description="GUNJALA GONDI LETTER AU", + direction="l", + linebreak="al", + unicodeslot=0x11D6B, + }, + [0x11D6C]={ + category="lo", + description="GUNJALA GONDI LETTER YA", + direction="l", + linebreak="al", + unicodeslot=0x11D6C, + }, + [0x11D6D]={ + category="lo", + description="GUNJALA GONDI LETTER VA", + direction="l", + linebreak="al", + unicodeslot=0x11D6D, + }, + [0x11D6E]={ + category="lo", + description="GUNJALA GONDI LETTER BA", + direction="l", + linebreak="al", + unicodeslot=0x11D6E, + }, + [0x11D6F]={ + category="lo", + description="GUNJALA GONDI LETTER BHA", + direction="l", + linebreak="al", + unicodeslot=0x11D6F, + }, + [0x11D70]={ + category="lo", + description="GUNJALA GONDI LETTER MA", + direction="l", + linebreak="al", + unicodeslot=0x11D70, + }, + [0x11D71]={ + category="lo", + description="GUNJALA GONDI LETTER KA", + direction="l", + linebreak="al", + unicodeslot=0x11D71, + }, + [0x11D72]={ + category="lo", + description="GUNJALA GONDI LETTER KHA", + direction="l", + linebreak="al", + unicodeslot=0x11D72, + }, + [0x11D73]={ + category="lo", + description="GUNJALA GONDI LETTER TA", + direction="l", + linebreak="al", + unicodeslot=0x11D73, + }, + [0x11D74]={ + category="lo", + description="GUNJALA GONDI LETTER THA", + direction="l", + linebreak="al", + unicodeslot=0x11D74, + }, + [0x11D75]={ + category="lo", + description="GUNJALA GONDI LETTER LA", + direction="l", + linebreak="al", + unicodeslot=0x11D75, + }, + [0x11D76]={ + category="lo", + description="GUNJALA GONDI LETTER GA", + direction="l", + linebreak="al", + unicodeslot=0x11D76, + }, + [0x11D77]={ + category="lo", + description="GUNJALA GONDI LETTER GHA", + direction="l", + linebreak="al", + unicodeslot=0x11D77, + }, + [0x11D78]={ + category="lo", + description="GUNJALA GONDI LETTER DA", + direction="l", + linebreak="al", + unicodeslot=0x11D78, + }, + [0x11D79]={ + category="lo", + description="GUNJALA GONDI LETTER DHA", + direction="l", + linebreak="al", + unicodeslot=0x11D79, + }, + [0x11D7A]={ + category="lo", + description="GUNJALA GONDI LETTER NA", + direction="l", + linebreak="al", + unicodeslot=0x11D7A, + }, + [0x11D7B]={ + category="lo", + description="GUNJALA GONDI LETTER CA", + direction="l", + linebreak="al", + unicodeslot=0x11D7B, + }, + [0x11D7C]={ + category="lo", + description="GUNJALA GONDI LETTER CHA", + direction="l", + linebreak="al", + unicodeslot=0x11D7C, + }, + [0x11D7D]={ + category="lo", + description="GUNJALA GONDI LETTER TTA", + direction="l", + linebreak="al", + unicodeslot=0x11D7D, + }, + [0x11D7E]={ + category="lo", + description="GUNJALA GONDI LETTER TTHA", + direction="l", + linebreak="al", + unicodeslot=0x11D7E, + }, + [0x11D7F]={ + category="lo", + description="GUNJALA GONDI LETTER LLA", + direction="l", + linebreak="al", + unicodeslot=0x11D7F, + }, + [0x11D80]={ + category="lo", + description="GUNJALA GONDI LETTER JA", + direction="l", + linebreak="al", + unicodeslot=0x11D80, + }, + [0x11D81]={ + category="lo", + description="GUNJALA GONDI LETTER JHA", + direction="l", + linebreak="al", + unicodeslot=0x11D81, + }, + [0x11D82]={ + category="lo", + description="GUNJALA GONDI LETTER DDA", + direction="l", + linebreak="al", + unicodeslot=0x11D82, + }, + [0x11D83]={ + category="lo", + description="GUNJALA GONDI LETTER DDHA", + direction="l", + linebreak="al", + unicodeslot=0x11D83, + }, + [0x11D84]={ + category="lo", + description="GUNJALA GONDI LETTER NGA", + direction="l", + linebreak="al", + unicodeslot=0x11D84, + }, + [0x11D85]={ + category="lo", + description="GUNJALA GONDI LETTER PA", + direction="l", + linebreak="al", + unicodeslot=0x11D85, + }, + [0x11D86]={ + category="lo", + description="GUNJALA GONDI LETTER PHA", + direction="l", + linebreak="al", + unicodeslot=0x11D86, + }, + [0x11D87]={ + category="lo", + description="GUNJALA GONDI LETTER HA", + direction="l", + linebreak="al", + unicodeslot=0x11D87, + }, + [0x11D88]={ + category="lo", + description="GUNJALA GONDI LETTER RA", + direction="l", + linebreak="al", + unicodeslot=0x11D88, + }, + [0x11D89]={ + category="lo", + description="GUNJALA GONDI LETTER SA", + direction="l", + linebreak="al", + unicodeslot=0x11D89, + }, + [0x11D8A]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN AA", + direction="l", + linebreak="cm", + unicodeslot=0x11D8A, + }, + [0x11D8B]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN I", + direction="l", + linebreak="cm", + unicodeslot=0x11D8B, + }, + [0x11D8C]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN II", + direction="l", + linebreak="cm", + unicodeslot=0x11D8C, + }, + [0x11D8D]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN U", + direction="l", + linebreak="cm", + unicodeslot=0x11D8D, + }, + [0x11D8E]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN UU", + direction="l", + linebreak="cm", + unicodeslot=0x11D8E, + }, + [0x11D90]={ + category="mn", + description="GUNJALA GONDI VOWEL SIGN EE", + direction="nsm", + linebreak="cm", + unicodeslot=0x11D90, + }, + [0x11D91]={ + category="mn", + description="GUNJALA GONDI VOWEL SIGN AI", + direction="nsm", + linebreak="cm", + unicodeslot=0x11D91, + }, + [0x11D93]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN OO", + direction="l", + linebreak="cm", + unicodeslot=0x11D93, + }, + [0x11D94]={ + category="mc", + description="GUNJALA GONDI VOWEL SIGN AU", + direction="l", + linebreak="cm", + unicodeslot=0x11D94, + }, + [0x11D95]={ + category="mn", + description="GUNJALA GONDI SIGN ANUSVARA", + direction="nsm", + linebreak="cm", + unicodeslot=0x11D95, + }, + [0x11D96]={ + category="mc", + description="GUNJALA GONDI SIGN VISARGA", + direction="l", + linebreak="cm", + unicodeslot=0x11D96, + }, + [0x11D97]={ + category="mn", + combining=0x9, + description="GUNJALA GONDI VIRAMA", + direction="nsm", + linebreak="cm", + unicodeslot=0x11D97, + }, + [0x11D98]={ + category="lo", + description="GUNJALA GONDI OM", + direction="l", + linebreak="al", + unicodeslot=0x11D98, + }, + [0x11DA0]={ + category="nd", + description="GUNJALA GONDI DIGIT ZERO", + direction="l", + linebreak="nu", + unicodeslot=0x11DA0, + }, + [0x11DA1]={ + category="nd", + description="GUNJALA GONDI DIGIT ONE", + direction="l", + linebreak="nu", + unicodeslot=0x11DA1, + }, + [0x11DA2]={ + category="nd", + description="GUNJALA GONDI DIGIT TWO", + direction="l", + linebreak="nu", + unicodeslot=0x11DA2, + }, + [0x11DA3]={ + category="nd", + description="GUNJALA GONDI DIGIT THREE", + direction="l", + linebreak="nu", + unicodeslot=0x11DA3, + }, + [0x11DA4]={ + category="nd", + description="GUNJALA GONDI DIGIT FOUR", + direction="l", + linebreak="nu", + unicodeslot=0x11DA4, + }, + [0x11DA5]={ + category="nd", + description="GUNJALA GONDI DIGIT FIVE", + direction="l", + linebreak="nu", + unicodeslot=0x11DA5, + }, + [0x11DA6]={ + category="nd", + description="GUNJALA GONDI DIGIT SIX", + direction="l", + linebreak="nu", + unicodeslot=0x11DA6, + }, + [0x11DA7]={ + category="nd", + description="GUNJALA GONDI DIGIT SEVEN", + direction="l", + linebreak="nu", + unicodeslot=0x11DA7, + }, + [0x11DA8]={ + category="nd", + description="GUNJALA GONDI DIGIT EIGHT", + direction="l", + linebreak="nu", + unicodeslot=0x11DA8, + }, + [0x11DA9]={ + category="nd", + description="GUNJALA GONDI DIGIT NINE", + direction="l", + linebreak="nu", + unicodeslot=0x11DA9, + }, + [0x11EE0]={ + category="lo", + description="MAKASAR LETTER KA", + direction="l", + linebreak="al", + unicodeslot=0x11EE0, + }, + [0x11EE1]={ + category="lo", + description="MAKASAR LETTER GA", + direction="l", + linebreak="al", + unicodeslot=0x11EE1, + }, + [0x11EE2]={ + category="lo", + description="MAKASAR LETTER NGA", + direction="l", + linebreak="al", + unicodeslot=0x11EE2, + }, + [0x11EE3]={ + category="lo", + description="MAKASAR LETTER PA", + direction="l", + linebreak="al", + unicodeslot=0x11EE3, + }, + [0x11EE4]={ + category="lo", + description="MAKASAR LETTER BA", + direction="l", + linebreak="al", + unicodeslot=0x11EE4, + }, + [0x11EE5]={ + category="lo", + description="MAKASAR LETTER MA", + direction="l", + linebreak="al", + unicodeslot=0x11EE5, + }, + [0x11EE6]={ + category="lo", + description="MAKASAR LETTER TA", + direction="l", + linebreak="al", + unicodeslot=0x11EE6, + }, + [0x11EE7]={ + category="lo", + description="MAKASAR LETTER DA", + direction="l", + linebreak="al", + unicodeslot=0x11EE7, + }, + [0x11EE8]={ + category="lo", + description="MAKASAR LETTER NA", + direction="l", + linebreak="al", + unicodeslot=0x11EE8, + }, + [0x11EE9]={ + category="lo", + description="MAKASAR LETTER CA", + direction="l", + linebreak="al", + unicodeslot=0x11EE9, + }, + [0x11EEA]={ + category="lo", + description="MAKASAR LETTER JA", + direction="l", + linebreak="al", + unicodeslot=0x11EEA, + }, + [0x11EEB]={ + category="lo", + description="MAKASAR LETTER NYA", + direction="l", + linebreak="al", + unicodeslot=0x11EEB, + }, + [0x11EEC]={ + category="lo", + description="MAKASAR LETTER YA", + direction="l", + linebreak="al", + unicodeslot=0x11EEC, + }, + [0x11EED]={ + category="lo", + description="MAKASAR LETTER RA", + direction="l", + linebreak="al", + unicodeslot=0x11EED, + }, + [0x11EEE]={ + category="lo", + description="MAKASAR LETTER LA", + direction="l", + linebreak="al", + unicodeslot=0x11EEE, + }, + [0x11EEF]={ + category="lo", + description="MAKASAR LETTER VA", + direction="l", + linebreak="al", + unicodeslot=0x11EEF, + }, + [0x11EF0]={ + category="lo", + description="MAKASAR LETTER SA", + direction="l", + linebreak="al", + unicodeslot=0x11EF0, + }, + [0x11EF1]={ + category="lo", + description="MAKASAR LETTER A", + direction="l", + linebreak="al", + unicodeslot=0x11EF1, + }, + [0x11EF2]={ + category="lo", + description="MAKASAR ANGKA", + direction="l", + linebreak="al", + unicodeslot=0x11EF2, + }, + [0x11EF3]={ + category="mn", + description="MAKASAR VOWEL SIGN I", + direction="nsm", + linebreak="cm", + unicodeslot=0x11EF3, + }, + [0x11EF4]={ + category="mn", + description="MAKASAR VOWEL SIGN U", + direction="nsm", + linebreak="cm", + unicodeslot=0x11EF4, + }, + [0x11EF5]={ + category="mc", + description="MAKASAR VOWEL SIGN E", + direction="l", + linebreak="cm", + unicodeslot=0x11EF5, + }, + [0x11EF6]={ + category="mc", + description="MAKASAR VOWEL SIGN O", + direction="l", + linebreak="cm", + unicodeslot=0x11EF6, + }, + [0x11EF7]={ + category="po", + description="MAKASAR PASSIMBANG", + direction="l", + linebreak="al", + unicodeslot=0x11EF7, + }, + [0x11EF8]={ + category="po", + description="MAKASAR END OF SECTION", + direction="l", + linebreak="al", + unicodeslot=0x11EF8, + }, [0x12000]={ category="lo", description="CUNEIFORM SIGN A", @@ -192135,6 +195389,643 @@ characters.data={ linebreak="al", unicodeslot=0x16B8F, }, + [0x16E40]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER M", + direction="l", + linebreak="al", + unicodeslot=0x16E40, + }, + [0x16E41]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER S", + direction="l", + linebreak="al", + unicodeslot=0x16E41, + }, + [0x16E42]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER V", + direction="l", + linebreak="al", + unicodeslot=0x16E42, + }, + [0x16E43]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER W", + direction="l", + linebreak="al", + unicodeslot=0x16E43, + }, + [0x16E44]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER ATIU", + direction="l", + linebreak="al", + unicodeslot=0x16E44, + }, + [0x16E45]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER Z", + direction="l", + linebreak="al", + unicodeslot=0x16E45, + }, + [0x16E46]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER KP", + direction="l", + linebreak="al", + unicodeslot=0x16E46, + }, + [0x16E47]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER P", + direction="l", + linebreak="al", + unicodeslot=0x16E47, + }, + [0x16E48]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER T", + direction="l", + linebreak="al", + unicodeslot=0x16E48, + }, + [0x16E49]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER G", + direction="l", + linebreak="al", + unicodeslot=0x16E49, + }, + [0x16E4A]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER F", + direction="l", + linebreak="al", + unicodeslot=0x16E4A, + }, + [0x16E4B]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER I", + direction="l", + linebreak="al", + unicodeslot=0x16E4B, + }, + [0x16E4C]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER K", + direction="l", + linebreak="al", + unicodeslot=0x16E4C, + }, + [0x16E4D]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER A", + direction="l", + linebreak="al", + unicodeslot=0x16E4D, + }, + [0x16E4E]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER J", + direction="l", + linebreak="al", + unicodeslot=0x16E4E, + }, + [0x16E4F]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER E", + direction="l", + linebreak="al", + unicodeslot=0x16E4F, + }, + [0x16E50]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER B", + direction="l", + linebreak="al", + unicodeslot=0x16E50, + }, + [0x16E51]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER C", + direction="l", + linebreak="al", + unicodeslot=0x16E51, + }, + [0x16E52]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER U", + direction="l", + linebreak="al", + unicodeslot=0x16E52, + }, + [0x16E53]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER YU", + direction="l", + linebreak="al", + unicodeslot=0x16E53, + }, + [0x16E54]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER L", + direction="l", + linebreak="al", + unicodeslot=0x16E54, + }, + [0x16E55]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER Q", + direction="l", + linebreak="al", + unicodeslot=0x16E55, + }, + [0x16E56]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER HP", + direction="l", + linebreak="al", + unicodeslot=0x16E56, + }, + [0x16E57]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER NY", + direction="l", + linebreak="al", + unicodeslot=0x16E57, + }, + [0x16E58]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER X", + direction="l", + linebreak="al", + unicodeslot=0x16E58, + }, + [0x16E59]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER D", + direction="l", + linebreak="al", + unicodeslot=0x16E59, + }, + [0x16E5A]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER OE", + direction="l", + linebreak="al", + unicodeslot=0x16E5A, + }, + [0x16E5B]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER N", + direction="l", + linebreak="al", + unicodeslot=0x16E5B, + }, + [0x16E5C]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER R", + direction="l", + linebreak="al", + unicodeslot=0x16E5C, + }, + [0x16E5D]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER O", + direction="l", + linebreak="al", + unicodeslot=0x16E5D, + }, + [0x16E5E]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER AI", + direction="l", + linebreak="al", + unicodeslot=0x16E5E, + }, + [0x16E5F]={ + category="lu", + description="MEDEFAIDRIN CAPITAL LETTER Y", + direction="l", + linebreak="al", + unicodeslot=0x16E5F, + }, + [0x16E60]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER M", + direction="l", + linebreak="al", + unicodeslot=0x16E60, + }, + [0x16E61]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER S", + direction="l", + linebreak="al", + unicodeslot=0x16E61, + }, + [0x16E62]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER V", + direction="l", + linebreak="al", + unicodeslot=0x16E62, + }, + [0x16E63]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER W", + direction="l", + linebreak="al", + unicodeslot=0x16E63, + }, + [0x16E64]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER ATIU", + direction="l", + linebreak="al", + unicodeslot=0x16E64, + }, + [0x16E65]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER Z", + direction="l", + linebreak="al", + unicodeslot=0x16E65, + }, + [0x16E66]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER KP", + direction="l", + linebreak="al", + unicodeslot=0x16E66, + }, + [0x16E67]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER P", + direction="l", + linebreak="al", + unicodeslot=0x16E67, + }, + [0x16E68]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER T", + direction="l", + linebreak="al", + unicodeslot=0x16E68, + }, + [0x16E69]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER G", + direction="l", + linebreak="al", + unicodeslot=0x16E69, + }, + [0x16E6A]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER F", + direction="l", + linebreak="al", + unicodeslot=0x16E6A, + }, + [0x16E6B]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER I", + direction="l", + linebreak="al", + unicodeslot=0x16E6B, + }, + [0x16E6C]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER K", + direction="l", + linebreak="al", + unicodeslot=0x16E6C, + }, + [0x16E6D]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER A", + direction="l", + linebreak="al", + unicodeslot=0x16E6D, + }, + [0x16E6E]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER J", + direction="l", + linebreak="al", + unicodeslot=0x16E6E, + }, + [0x16E6F]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER E", + direction="l", + linebreak="al", + unicodeslot=0x16E6F, + }, + [0x16E70]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER B", + direction="l", + linebreak="al", + unicodeslot=0x16E70, + }, + [0x16E71]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER C", + direction="l", + linebreak="al", + unicodeslot=0x16E71, + }, + [0x16E72]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER U", + direction="l", + linebreak="al", + unicodeslot=0x16E72, + }, + [0x16E73]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER YU", + direction="l", + linebreak="al", + unicodeslot=0x16E73, + }, + [0x16E74]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER L", + direction="l", + linebreak="al", + unicodeslot=0x16E74, + }, + [0x16E75]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER Q", + direction="l", + linebreak="al", + unicodeslot=0x16E75, + }, + [0x16E76]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER HP", + direction="l", + linebreak="al", + unicodeslot=0x16E76, + }, + [0x16E77]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER NY", + direction="l", + linebreak="al", + unicodeslot=0x16E77, + }, + [0x16E78]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER X", + direction="l", + linebreak="al", + unicodeslot=0x16E78, + }, + [0x16E79]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER D", + direction="l", + linebreak="al", + unicodeslot=0x16E79, + }, + [0x16E7A]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER OE", + direction="l", + linebreak="al", + unicodeslot=0x16E7A, + }, + [0x16E7B]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER N", + direction="l", + linebreak="al", + unicodeslot=0x16E7B, + }, + [0x16E7C]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER R", + direction="l", + linebreak="al", + unicodeslot=0x16E7C, + }, + [0x16E7D]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER O", + direction="l", + linebreak="al", + unicodeslot=0x16E7D, + }, + [0x16E7E]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER AI", + direction="l", + linebreak="al", + unicodeslot=0x16E7E, + }, + [0x16E7F]={ + category="ll", + description="MEDEFAIDRIN SMALL LETTER Y", + direction="l", + linebreak="al", + unicodeslot=0x16E7F, + }, + [0x16E80]={ + category="no", + description="MEDEFAIDRIN DIGIT ZERO", + direction="l", + linebreak="al", + unicodeslot=0x16E80, + }, + [0x16E81]={ + category="no", + description="MEDEFAIDRIN DIGIT ONE", + direction="l", + linebreak="al", + unicodeslot=0x16E81, + }, + [0x16E82]={ + category="no", + description="MEDEFAIDRIN DIGIT TWO", + direction="l", + linebreak="al", + unicodeslot=0x16E82, + }, + [0x16E83]={ + category="no", + description="MEDEFAIDRIN DIGIT THREE", + direction="l", + linebreak="al", + unicodeslot=0x16E83, + }, + [0x16E84]={ + category="no", + description="MEDEFAIDRIN DIGIT FOUR", + direction="l", + linebreak="al", + unicodeslot=0x16E84, + }, + [0x16E85]={ + category="no", + description="MEDEFAIDRIN DIGIT FIVE", + direction="l", + linebreak="al", + unicodeslot=0x16E85, + }, + [0x16E86]={ + category="no", + description="MEDEFAIDRIN DIGIT SIX", + direction="l", + linebreak="al", + unicodeslot=0x16E86, + }, + [0x16E87]={ + category="no", + description="MEDEFAIDRIN DIGIT SEVEN", + direction="l", + linebreak="al", + unicodeslot=0x16E87, + }, + [0x16E88]={ + category="no", + description="MEDEFAIDRIN DIGIT EIGHT", + direction="l", + linebreak="al", + unicodeslot=0x16E88, + }, + [0x16E89]={ + category="no", + description="MEDEFAIDRIN DIGIT NINE", + direction="l", + linebreak="al", + unicodeslot=0x16E89, + }, + [0x16E8A]={ + category="no", + description="MEDEFAIDRIN NUMBER TEN", + direction="l", + linebreak="al", + unicodeslot=0x16E8A, + }, + [0x16E8B]={ + category="no", + description="MEDEFAIDRIN NUMBER ELEVEN", + direction="l", + linebreak="al", + unicodeslot=0x16E8B, + }, + [0x16E8C]={ + category="no", + description="MEDEFAIDRIN NUMBER TWELVE", + direction="l", + linebreak="al", + unicodeslot=0x16E8C, + }, + [0x16E8D]={ + category="no", + description="MEDEFAIDRIN NUMBER THIRTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E8D, + }, + [0x16E8E]={ + category="no", + description="MEDEFAIDRIN NUMBER FOURTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E8E, + }, + [0x16E8F]={ + category="no", + description="MEDEFAIDRIN NUMBER FIFTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E8F, + }, + [0x16E90]={ + category="no", + description="MEDEFAIDRIN NUMBER SIXTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E90, + }, + [0x16E91]={ + category="no", + description="MEDEFAIDRIN NUMBER SEVENTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E91, + }, + [0x16E92]={ + category="no", + description="MEDEFAIDRIN NUMBER EIGHTEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E92, + }, + [0x16E93]={ + category="no", + description="MEDEFAIDRIN NUMBER NINETEEN", + direction="l", + linebreak="al", + unicodeslot=0x16E93, + }, + [0x16E94]={ + category="no", + description="MEDEFAIDRIN DIGIT ONE ALTERNATE FORM", + direction="l", + linebreak="al", + unicodeslot=0x16E94, + }, + [0x16E95]={ + category="no", + description="MEDEFAIDRIN DIGIT TWO ALTERNATE FORM", + direction="l", + linebreak="al", + unicodeslot=0x16E95, + }, + [0x16E96]={ + category="no", + description="MEDEFAIDRIN DIGIT THREE ALTERNATE FORM", + direction="l", + linebreak="al", + unicodeslot=0x16E96, + }, + [0x16E97]={ + category="po", + description="MEDEFAIDRIN COMMA", + direction="l", + linebreak="ba", + unicodeslot=0x16E97, + }, + [0x16E98]={ + category="po", + description="MEDEFAIDRIN FULL STOP", + direction="l", + linebreak="ba", + unicodeslot=0x16E98, + }, + [0x16E99]={ + category="po", + description="MEDEFAIDRIN SYMBOL AIVA", + direction="l", + linebreak="al", + unicodeslot=0x16E99, + }, + [0x16E9A]={ + category="po", + description="MEDEFAIDRIN EXCLAMATION OH", + direction="l", + linebreak="al", + unicodeslot=0x16E9A, + }, [0x16F00]={ category="lo", description="MIAO LETTER PA", @@ -209493,6 +213384,146 @@ characters.data={ linebreak="al", unicodeslot=0x1D245, }, + [0x1D2E0]={ + category="no", + description="MAYAN NUMERAL ZERO", + direction="l", + linebreak="al", + unicodeslot=0x1D2E0, + }, + [0x1D2E1]={ + category="no", + description="MAYAN NUMERAL ONE", + direction="l", + linebreak="al", + unicodeslot=0x1D2E1, + }, + [0x1D2E2]={ + category="no", + description="MAYAN NUMERAL TWO", + direction="l", + linebreak="al", + unicodeslot=0x1D2E2, + }, + [0x1D2E3]={ + category="no", + description="MAYAN NUMERAL THREE", + direction="l", + linebreak="al", + unicodeslot=0x1D2E3, + }, + [0x1D2E4]={ + category="no", + description="MAYAN NUMERAL FOUR", + direction="l", + linebreak="al", + unicodeslot=0x1D2E4, + }, + [0x1D2E5]={ + category="no", + description="MAYAN NUMERAL FIVE", + direction="l", + linebreak="al", + unicodeslot=0x1D2E5, + }, + [0x1D2E6]={ + category="no", + description="MAYAN NUMERAL SIX", + direction="l", + linebreak="al", + unicodeslot=0x1D2E6, + }, + [0x1D2E7]={ + category="no", + description="MAYAN NUMERAL SEVEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2E7, + }, + [0x1D2E8]={ + category="no", + description="MAYAN NUMERAL EIGHT", + direction="l", + linebreak="al", + unicodeslot=0x1D2E8, + }, + [0x1D2E9]={ + category="no", + description="MAYAN NUMERAL NINE", + direction="l", + linebreak="al", + unicodeslot=0x1D2E9, + }, + [0x1D2EA]={ + category="no", + description="MAYAN NUMERAL TEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2EA, + }, + [0x1D2EB]={ + category="no", + description="MAYAN NUMERAL ELEVEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2EB, + }, + [0x1D2EC]={ + category="no", + description="MAYAN NUMERAL TWELVE", + direction="l", + linebreak="al", + unicodeslot=0x1D2EC, + }, + [0x1D2ED]={ + category="no", + description="MAYAN NUMERAL THIRTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2ED, + }, + [0x1D2EE]={ + category="no", + description="MAYAN NUMERAL FOURTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2EE, + }, + [0x1D2EF]={ + category="no", + description="MAYAN NUMERAL FIFTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2EF, + }, + [0x1D2F0]={ + category="no", + description="MAYAN NUMERAL SIXTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2F0, + }, + [0x1D2F1]={ + category="no", + description="MAYAN NUMERAL SEVENTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2F1, + }, + [0x1D2F2]={ + category="no", + description="MAYAN NUMERAL EIGHTEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2F2, + }, + [0x1D2F3]={ + category="no", + description="MAYAN NUMERAL NINETEEN", + direction="l", + linebreak="al", + unicodeslot=0x1D2F3, + }, [0x1D300]={ category="so", description="MONOGRAM FOR EARTH", @@ -210228,6 +214259,55 @@ characters.data={ linebreak="al", unicodeslot=0x1D371, }, + [0x1D372]={ + category="no", + description="IDEOGRAPHIC TALLY MARK ONE", + direction="l", + linebreak="al", + unicodeslot=0x1D372, + }, + [0x1D373]={ + category="no", + description="IDEOGRAPHIC TALLY MARK TWO", + direction="l", + linebreak="al", + unicodeslot=0x1D373, + }, + [0x1D374]={ + category="no", + description="IDEOGRAPHIC TALLY MARK THREE", + direction="l", + linebreak="al", + unicodeslot=0x1D374, + }, + [0x1D375]={ + category="no", + description="IDEOGRAPHIC TALLY MARK FOUR", + direction="l", + linebreak="al", + unicodeslot=0x1D375, + }, + [0x1D376]={ + category="no", + description="IDEOGRAPHIC TALLY MARK FIVE", + direction="l", + linebreak="al", + unicodeslot=0x1D376, + }, + [0x1D377]={ + category="no", + description="TALLY MARK ONE", + direction="l", + linebreak="al", + unicodeslot=0x1D377, + }, + [0x1D378]={ + category="no", + description="TALLY MARK FIVE", + direction="l", + linebreak="al", + unicodeslot=0x1D378, + }, [0x1D400]={ category="lu", description="MATHEMATICAL BOLD CAPITAL A", @@ -226170,6 +230250,482 @@ characters.data={ linebreak="op", unicodeslot=0x1E95F, }, + [0x1EC71]={ + category="no", + description="INDIC SIYAQ NUMBER ONE", + direction="al", + linebreak="al", + unicodeslot=0x1EC71, + }, + [0x1EC72]={ + category="no", + description="INDIC SIYAQ NUMBER TWO", + direction="al", + linebreak="al", + unicodeslot=0x1EC72, + }, + [0x1EC73]={ + category="no", + description="INDIC SIYAQ NUMBER THREE", + direction="al", + linebreak="al", + unicodeslot=0x1EC73, + }, + [0x1EC74]={ + category="no", + description="INDIC SIYAQ NUMBER FOUR", + direction="al", + linebreak="al", + unicodeslot=0x1EC74, + }, + [0x1EC75]={ + category="no", + description="INDIC SIYAQ NUMBER FIVE", + direction="al", + linebreak="al", + unicodeslot=0x1EC75, + }, + [0x1EC76]={ + category="no", + description="INDIC SIYAQ NUMBER SIX", + direction="al", + linebreak="al", + unicodeslot=0x1EC76, + }, + [0x1EC77]={ + category="no", + description="INDIC SIYAQ NUMBER SEVEN", + direction="al", + linebreak="al", + unicodeslot=0x1EC77, + }, + [0x1EC78]={ + category="no", + description="INDIC SIYAQ NUMBER EIGHT", + direction="al", + linebreak="al", + unicodeslot=0x1EC78, + }, + [0x1EC79]={ + category="no", + description="INDIC SIYAQ NUMBER NINE", + direction="al", + linebreak="al", + unicodeslot=0x1EC79, + }, + [0x1EC7A]={ + category="no", + description="INDIC SIYAQ NUMBER TEN", + direction="al", + linebreak="al", + unicodeslot=0x1EC7A, + }, + [0x1EC7B]={ + category="no", + description="INDIC SIYAQ NUMBER TWENTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC7B, + }, + [0x1EC7C]={ + category="no", + description="INDIC SIYAQ NUMBER THIRTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC7C, + }, + [0x1EC7D]={ + category="no", + description="INDIC SIYAQ NUMBER FORTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC7D, + }, + [0x1EC7E]={ + category="no", + description="INDIC SIYAQ NUMBER FIFTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC7E, + }, + [0x1EC7F]={ + category="no", + description="INDIC SIYAQ NUMBER SIXTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC7F, + }, + [0x1EC80]={ + category="no", + description="INDIC SIYAQ NUMBER SEVENTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC80, + }, + [0x1EC81]={ + category="no", + description="INDIC SIYAQ NUMBER EIGHTY", + direction="al", + linebreak="al", + unicodeslot=0x1EC81, + }, + [0x1EC82]={ + category="no", + description="INDIC SIYAQ NUMBER NINETY", + direction="al", + linebreak="al", + unicodeslot=0x1EC82, + }, + [0x1EC83]={ + category="no", + description="INDIC SIYAQ NUMBER ONE HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC83, + }, + [0x1EC84]={ + category="no", + description="INDIC SIYAQ NUMBER TWO HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC84, + }, + [0x1EC85]={ + category="no", + description="INDIC SIYAQ NUMBER THREE HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC85, + }, + [0x1EC86]={ + category="no", + description="INDIC SIYAQ NUMBER FOUR HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC86, + }, + [0x1EC87]={ + category="no", + description="INDIC SIYAQ NUMBER FIVE HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC87, + }, + [0x1EC88]={ + category="no", + description="INDIC SIYAQ NUMBER SIX HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC88, + }, + [0x1EC89]={ + category="no", + description="INDIC SIYAQ NUMBER SEVEN HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC89, + }, + [0x1EC8A]={ + category="no", + description="INDIC SIYAQ NUMBER EIGHT HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC8A, + }, + [0x1EC8B]={ + category="no", + description="INDIC SIYAQ NUMBER NINE HUNDRED", + direction="al", + linebreak="al", + unicodeslot=0x1EC8B, + }, + [0x1EC8C]={ + category="no", + description="INDIC SIYAQ NUMBER ONE THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC8C, + }, + [0x1EC8D]={ + category="no", + description="INDIC SIYAQ NUMBER TWO THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC8D, + }, + [0x1EC8E]={ + category="no", + description="INDIC SIYAQ NUMBER THREE THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC8E, + }, + [0x1EC8F]={ + category="no", + description="INDIC SIYAQ NUMBER FOUR THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC8F, + }, + [0x1EC90]={ + category="no", + description="INDIC SIYAQ NUMBER FIVE THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC90, + }, + [0x1EC91]={ + category="no", + description="INDIC SIYAQ NUMBER SIX THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC91, + }, + [0x1EC92]={ + category="no", + description="INDIC SIYAQ NUMBER SEVEN THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC92, + }, + [0x1EC93]={ + category="no", + description="INDIC SIYAQ NUMBER EIGHT THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC93, + }, + [0x1EC94]={ + category="no", + description="INDIC SIYAQ NUMBER NINE THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC94, + }, + [0x1EC95]={ + category="no", + description="INDIC SIYAQ NUMBER TEN THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC95, + }, + [0x1EC96]={ + category="no", + description="INDIC SIYAQ NUMBER TWENTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC96, + }, + [0x1EC97]={ + category="no", + description="INDIC SIYAQ NUMBER THIRTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC97, + }, + [0x1EC98]={ + category="no", + description="INDIC SIYAQ NUMBER FORTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC98, + }, + [0x1EC99]={ + category="no", + description="INDIC SIYAQ NUMBER FIFTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC99, + }, + [0x1EC9A]={ + category="no", + description="INDIC SIYAQ NUMBER SIXTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC9A, + }, + [0x1EC9B]={ + category="no", + description="INDIC SIYAQ NUMBER SEVENTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC9B, + }, + [0x1EC9C]={ + category="no", + description="INDIC SIYAQ NUMBER EIGHTY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC9C, + }, + [0x1EC9D]={ + category="no", + description="INDIC SIYAQ NUMBER NINETY THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1EC9D, + }, + [0x1EC9E]={ + category="no", + description="INDIC SIYAQ NUMBER LAKH", + direction="al", + linebreak="al", + unicodeslot=0x1EC9E, + }, + [0x1EC9F]={ + category="no", + description="INDIC SIYAQ NUMBER LAKHAN", + direction="al", + linebreak="al", + unicodeslot=0x1EC9F, + }, + [0x1ECA0]={ + category="no", + description="INDIC SIYAQ LAKH MARK", + direction="al", + linebreak="al", + unicodeslot=0x1ECA0, + }, + [0x1ECA1]={ + category="no", + description="INDIC SIYAQ NUMBER KAROR", + direction="al", + linebreak="al", + unicodeslot=0x1ECA1, + }, + [0x1ECA2]={ + category="no", + description="INDIC SIYAQ NUMBER KARORAN", + direction="al", + linebreak="al", + unicodeslot=0x1ECA2, + }, + [0x1ECA3]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED ONE", + direction="al", + linebreak="al", + unicodeslot=0x1ECA3, + }, + [0x1ECA4]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED TWO", + direction="al", + linebreak="al", + unicodeslot=0x1ECA4, + }, + [0x1ECA5]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED THREE", + direction="al", + linebreak="al", + unicodeslot=0x1ECA5, + }, + [0x1ECA6]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED FOUR", + direction="al", + linebreak="al", + unicodeslot=0x1ECA6, + }, + [0x1ECA7]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED FIVE", + direction="al", + linebreak="al", + unicodeslot=0x1ECA7, + }, + [0x1ECA8]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED SIX", + direction="al", + linebreak="al", + unicodeslot=0x1ECA8, + }, + [0x1ECA9]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED SEVEN", + direction="al", + linebreak="al", + unicodeslot=0x1ECA9, + }, + [0x1ECAA]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED EIGHT", + direction="al", + linebreak="al", + unicodeslot=0x1ECAA, + }, + [0x1ECAB]={ + category="no", + description="INDIC SIYAQ NUMBER PREFIXED NINE", + direction="al", + linebreak="al", + unicodeslot=0x1ECAB, + }, + [0x1ECAC]={ + category="so", + description="INDIC SIYAQ PLACEHOLDER", + direction="al", + linebreak="po", + unicodeslot=0x1ECAC, + }, + [0x1ECAD]={ + category="no", + description="INDIC SIYAQ FRACTION ONE QUARTER", + direction="al", + linebreak="al", + unicodeslot=0x1ECAD, + }, + [0x1ECAE]={ + category="no", + description="INDIC SIYAQ FRACTION ONE HALF", + direction="al", + linebreak="al", + unicodeslot=0x1ECAE, + }, + [0x1ECAF]={ + category="no", + description="INDIC SIYAQ FRACTION THREE QUARTERS", + direction="al", + linebreak="al", + unicodeslot=0x1ECAF, + }, + [0x1ECB0]={ + category="sc", + description="INDIC SIYAQ RUPEE MARK", + direction="al", + linebreak="po", + unicodeslot=0x1ECB0, + }, + [0x1ECB1]={ + category="no", + description="INDIC SIYAQ NUMBER ALTERNATE ONE", + direction="al", + linebreak="al", + unicodeslot=0x1ECB1, + }, + [0x1ECB2]={ + category="no", + description="INDIC SIYAQ NUMBER ALTERNATE TWO", + direction="al", + linebreak="al", + unicodeslot=0x1ECB2, + }, + [0x1ECB3]={ + category="no", + description="INDIC SIYAQ NUMBER ALTERNATE TEN THOUSAND", + direction="al", + linebreak="al", + unicodeslot=0x1ECB3, + }, + [0x1ECB4]={ + category="no", + description="INDIC SIYAQ ALTERNATE LAKH MARK", + direction="al", + linebreak="al", + unicodeslot=0x1ECB4, + }, [0x1EE00]={ category="lo", comment="check math properties", @@ -229431,6 +233987,13 @@ characters.data={ specials={ "circle", 0x57, 0x5A }, unicodeslot=0x1F12E, }, + [0x1F12F]={ + category="so", + description="COPYLEFT SYMBOL", + direction="on", + linebreak="al", + unicodeslot=0x1F12F, + }, [0x1F130]={ category="so", cjkwd="a", @@ -239053,6 +243616,14 @@ characters.data={ linebreak="id", unicodeslot=0x1F6F8, }, + [0x1F6F9]={ + category="so", + cjkwd="w", + description="SKATEBOARD", + direction="on", + linebreak="id", + unicodeslot=0x1F6F9, + }, [0x1F700]={ category="so", description="ALCHEMICAL SYMBOL FOR QUINTESSENCE", @@ -240461,6 +245032,34 @@ characters.data={ linebreak="al", unicodeslot=0x1F7D4, }, + [0x1F7D5]={ + category="so", + description="CIRCLED TRIANGLE", + direction="on", + linebreak="id", + unicodeslot=0x1F7D5, + }, + [0x1F7D6]={ + category="so", + description="NEGATIVE CIRCLED TRIANGLE", + direction="on", + linebreak="id", + unicodeslot=0x1F7D6, + }, + [0x1F7D7]={ + category="so", + description="CIRCLED SQUARE", + direction="on", + linebreak="id", + unicodeslot=0x1F7D7, + }, + [0x1F7D8]={ + category="so", + description="NEGATIVE CIRCLED SQUARE", + direction="on", + linebreak="id", + unicodeslot=0x1F7D8, + }, [0x1F800]={ category="so", description="LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD", @@ -242067,6 +246666,30 @@ characters.data={ linebreak="id", unicodeslot=0x1F94C, }, + [0x1F94D]={ + category="so", + cjkwd="w", + description="LACROSSE STICK AND BALL", + direction="on", + linebreak="id", + unicodeslot=0x1F94D, + }, + [0x1F94E]={ + category="so", + cjkwd="w", + description="SOFTBALL", + direction="on", + linebreak="id", + unicodeslot=0x1F94E, + }, + [0x1F94F]={ + category="so", + cjkwd="w", + description="FLYING DISC", + direction="on", + linebreak="id", + unicodeslot=0x1F94F, + }, [0x1F950]={ category="so", cjkwd="w", @@ -242292,6 +246915,118 @@ characters.data={ linebreak="id", unicodeslot=0x1F96B, }, + [0x1F96C]={ + category="so", + cjkwd="w", + description="LEAFY GREEN", + direction="on", + linebreak="id", + unicodeslot=0x1F96C, + }, + [0x1F96D]={ + category="so", + cjkwd="w", + description="MANGO", + direction="on", + linebreak="id", + unicodeslot=0x1F96D, + }, + [0x1F96E]={ + category="so", + cjkwd="w", + description="MOON CAKE", + direction="on", + linebreak="id", + unicodeslot=0x1F96E, + }, + [0x1F96F]={ + category="so", + cjkwd="w", + description="BAGEL", + direction="on", + linebreak="id", + unicodeslot=0x1F96F, + }, + [0x1F970]={ + category="so", + cjkwd="w", + description="SMILING FACE WITH SMILING EYES AND THREE HEARTS", + direction="on", + linebreak="id", + unicodeslot=0x1F970, + }, + [0x1F973]={ + category="so", + cjkwd="w", + description="FACE WITH PARTY HORN AND PARTY HAT", + direction="on", + linebreak="id", + unicodeslot=0x1F973, + }, + [0x1F974]={ + category="so", + cjkwd="w", + description="FACE WITH UNEVEN EYES AND WAVY MOUTH", + direction="on", + linebreak="id", + unicodeslot=0x1F974, + }, + [0x1F975]={ + category="so", + cjkwd="w", + description="OVERHEATED FACE", + direction="on", + linebreak="id", + unicodeslot=0x1F975, + }, + [0x1F976]={ + category="so", + cjkwd="w", + description="FREEZING FACE", + direction="on", + linebreak="id", + unicodeslot=0x1F976, + }, + [0x1F97A]={ + category="so", + cjkwd="w", + description="FACE WITH PLEADING EYES", + direction="on", + linebreak="id", + unicodeslot=0x1F97A, + }, + [0x1F97C]={ + category="so", + cjkwd="w", + description="LAB COAT", + direction="on", + linebreak="id", + unicodeslot=0x1F97C, + }, + [0x1F97D]={ + category="so", + cjkwd="w", + description="GOGGLES", + direction="on", + linebreak="id", + unicodeslot=0x1F97D, + }, + [0x1F97E]={ + category="so", + cjkwd="w", + description="HIKING BOOT", + direction="on", + linebreak="id", + unicodeslot=0x1F97E, + }, + [0x1F97F]={ + category="so", + cjkwd="w", + description="FLAT SHOE", + direction="on", + linebreak="id", + unicodeslot=0x1F97F, + }, [0x1F980]={ category="so", cjkwd="w", @@ -242485,6 +247220,174 @@ characters.data={ linebreak="id", unicodeslot=0x1F997, }, + [0x1F998]={ + category="so", + cjkwd="w", + description="KANGAROO", + direction="on", + linebreak="id", + unicodeslot=0x1F998, + }, + [0x1F999]={ + category="so", + cjkwd="w", + description="LLAMA", + direction="on", + linebreak="id", + unicodeslot=0x1F999, + }, + [0x1F99A]={ + category="so", + cjkwd="w", + description="PEACOCK", + direction="on", + linebreak="id", + unicodeslot=0x1F99A, + }, + [0x1F99B]={ + category="so", + cjkwd="w", + description="HIPPOPOTAMUS", + direction="on", + linebreak="id", + unicodeslot=0x1F99B, + }, + [0x1F99C]={ + category="so", + cjkwd="w", + description="PARROT", + direction="on", + linebreak="id", + unicodeslot=0x1F99C, + }, + [0x1F99D]={ + category="so", + cjkwd="w", + description="RACCOON", + direction="on", + linebreak="id", + unicodeslot=0x1F99D, + }, + [0x1F99E]={ + category="so", + cjkwd="w", + description="LOBSTER", + direction="on", + linebreak="id", + unicodeslot=0x1F99E, + }, + [0x1F99F]={ + category="so", + cjkwd="w", + description="MOSQUITO", + direction="on", + linebreak="id", + unicodeslot=0x1F99F, + }, + [0x1F9A0]={ + category="so", + cjkwd="w", + description="MICROBE", + direction="on", + linebreak="id", + unicodeslot=0x1F9A0, + }, + [0x1F9A1]={ + category="so", + cjkwd="w", + description="BADGER", + direction="on", + linebreak="id", + unicodeslot=0x1F9A1, + }, + [0x1F9A2]={ + category="so", + cjkwd="w", + description="SWAN", + direction="on", + linebreak="id", + unicodeslot=0x1F9A2, + }, + [0x1F9B0]={ + category="so", + cjkwd="w", + description="EMOJI COMPONENT RED HAIR", + direction="on", + linebreak="id", + unicodeslot=0x1F9B0, + }, + [0x1F9B1]={ + category="so", + cjkwd="w", + description="EMOJI COMPONENT CURLY HAIR", + direction="on", + linebreak="id", + unicodeslot=0x1F9B1, + }, + [0x1F9B2]={ + category="so", + cjkwd="w", + description="EMOJI COMPONENT BALD", + direction="on", + linebreak="id", + unicodeslot=0x1F9B2, + }, + [0x1F9B3]={ + category="so", + cjkwd="w", + description="EMOJI COMPONENT WHITE HAIR", + direction="on", + linebreak="id", + unicodeslot=0x1F9B3, + }, + [0x1F9B4]={ + category="so", + cjkwd="w", + description="BONE", + direction="on", + linebreak="id", + unicodeslot=0x1F9B4, + }, + [0x1F9B5]={ + category="so", + cjkwd="w", + description="LEG", + direction="on", + linebreak="eb", + unicodeslot=0x1F9B5, + }, + [0x1F9B6]={ + category="so", + cjkwd="w", + description="FOOT", + direction="on", + linebreak="eb", + unicodeslot=0x1F9B6, + }, + [0x1F9B7]={ + category="so", + cjkwd="w", + description="TOOTH", + direction="on", + linebreak="id", + unicodeslot=0x1F9B7, + }, + [0x1F9B8]={ + category="so", + cjkwd="w", + description="SUPERHERO", + direction="on", + linebreak="eb", + unicodeslot=0x1F9B8, + }, + [0x1F9B9]={ + category="so", + cjkwd="w", + description="SUPERVILLAIN", + direction="on", + linebreak="eb", + unicodeslot=0x1F9B9, + }, [0x1F9C0]={ category="so", cjkwd="w", @@ -242493,6 +247396,22 @@ characters.data={ linebreak="id", unicodeslot=0x1F9C0, }, + [0x1F9C1]={ + category="so", + cjkwd="w", + description="CUPCAKE", + direction="on", + linebreak="id", + unicodeslot=0x1F9C1, + }, + [0x1F9C2]={ + category="so", + cjkwd="w", + description="SALT SHAKER", + direction="on", + linebreak="id", + unicodeslot=0x1F9C2, + }, [0x1F9D0]={ category="so", cjkwd="w", @@ -242677,6 +247596,304 @@ characters.data={ linebreak="id", unicodeslot=0x1F9E6, }, + [0x1F9E7]={ + category="so", + cjkwd="w", + description="RED GIFT ENVELOPE", + direction="on", + linebreak="id", + unicodeslot=0x1F9E7, + }, + [0x1F9E8]={ + category="so", + cjkwd="w", + description="FIRECRACKER", + direction="on", + linebreak="id", + unicodeslot=0x1F9E8, + }, + [0x1F9E9]={ + category="so", + cjkwd="w", + description="JIGSAW PUZZLE PIECE", + direction="on", + linebreak="id", + unicodeslot=0x1F9E9, + }, + [0x1F9EA]={ + category="so", + cjkwd="w", + description="TEST TUBE", + direction="on", + linebreak="id", + unicodeslot=0x1F9EA, + }, + [0x1F9EB]={ + category="so", + cjkwd="w", + description="PETRI DISH", + direction="on", + linebreak="id", + unicodeslot=0x1F9EB, + }, + [0x1F9EC]={ + category="so", + cjkwd="w", + description="DNA DOUBLE HELIX", + direction="on", + linebreak="id", + unicodeslot=0x1F9EC, + }, + [0x1F9ED]={ + category="so", + cjkwd="w", + description="COMPASS", + direction="on", + linebreak="id", + unicodeslot=0x1F9ED, + }, + [0x1F9EE]={ + category="so", + cjkwd="w", + description="ABACUS", + direction="on", + linebreak="id", + unicodeslot=0x1F9EE, + }, + [0x1F9EF]={ + category="so", + cjkwd="w", + description="FIRE EXTINGUISHER", + direction="on", + linebreak="id", + unicodeslot=0x1F9EF, + }, + [0x1F9F0]={ + category="so", + cjkwd="w", + description="TOOLBOX", + direction="on", + linebreak="id", + unicodeslot=0x1F9F0, + }, + [0x1F9F1]={ + category="so", + cjkwd="w", + description="BRICK", + direction="on", + linebreak="id", + unicodeslot=0x1F9F1, + }, + [0x1F9F2]={ + category="so", + cjkwd="w", + description="MAGNET", + direction="on", + linebreak="id", + unicodeslot=0x1F9F2, + }, + [0x1F9F3]={ + category="so", + cjkwd="w", + description="LUGGAGE", + direction="on", + linebreak="id", + unicodeslot=0x1F9F3, + }, + [0x1F9F4]={ + category="so", + cjkwd="w", + description="LOTION BOTTLE", + direction="on", + linebreak="id", + unicodeslot=0x1F9F4, + }, + [0x1F9F5]={ + category="so", + cjkwd="w", + description="SPOOL OF THREAD", + direction="on", + linebreak="id", + unicodeslot=0x1F9F5, + }, + [0x1F9F6]={ + category="so", + cjkwd="w", + description="BALL OF YARN", + direction="on", + linebreak="id", + unicodeslot=0x1F9F6, + }, + [0x1F9F7]={ + category="so", + cjkwd="w", + description="SAFETY PIN", + direction="on", + linebreak="id", + unicodeslot=0x1F9F7, + }, + [0x1F9F8]={ + category="so", + cjkwd="w", + description="TEDDY BEAR", + direction="on", + linebreak="id", + unicodeslot=0x1F9F8, + }, + [0x1F9F9]={ + category="so", + cjkwd="w", + description="BROOM", + direction="on", + linebreak="id", + unicodeslot=0x1F9F9, + }, + [0x1F9FA]={ + category="so", + cjkwd="w", + description="BASKET", + direction="on", + linebreak="id", + unicodeslot=0x1F9FA, + }, + [0x1F9FB]={ + category="so", + cjkwd="w", + description="ROLL OF PAPER", + direction="on", + linebreak="id", + unicodeslot=0x1F9FB, + }, + [0x1F9FC]={ + category="so", + cjkwd="w", + description="BAR OF SOAP", + direction="on", + linebreak="id", + unicodeslot=0x1F9FC, + }, + [0x1F9FD]={ + category="so", + cjkwd="w", + description="SPONGE", + direction="on", + linebreak="id", + unicodeslot=0x1F9FD, + }, + [0x1F9FE]={ + category="so", + cjkwd="w", + description="RECEIPT", + direction="on", + linebreak="id", + unicodeslot=0x1F9FE, + }, + [0x1F9FF]={ + category="so", + cjkwd="w", + description="NAZAR AMULET", + direction="on", + linebreak="id", + unicodeslot=0x1F9FF, + }, + [0x1FA60]={ + category="so", + description="XIANGQI RED GENERAL", + direction="on", + linebreak="id", + unicodeslot=0x1FA60, + }, + [0x1FA61]={ + category="so", + description="XIANGQI RED MANDARIN", + direction="on", + linebreak="id", + unicodeslot=0x1FA61, + }, + [0x1FA62]={ + category="so", + description="XIANGQI RED ELEPHANT", + direction="on", + linebreak="id", + unicodeslot=0x1FA62, + }, + [0x1FA63]={ + category="so", + description="XIANGQI RED HORSE", + direction="on", + linebreak="id", + unicodeslot=0x1FA63, + }, + [0x1FA64]={ + category="so", + description="XIANGQI RED CHARIOT", + direction="on", + linebreak="id", + unicodeslot=0x1FA64, + }, + [0x1FA65]={ + category="so", + description="XIANGQI RED CANNON", + direction="on", + linebreak="id", + unicodeslot=0x1FA65, + }, + [0x1FA66]={ + category="so", + description="XIANGQI RED SOLDIER", + direction="on", + linebreak="id", + unicodeslot=0x1FA66, + }, + [0x1FA67]={ + category="so", + description="XIANGQI BLACK GENERAL", + direction="on", + linebreak="id", + unicodeslot=0x1FA67, + }, + [0x1FA68]={ + category="so", + description="XIANGQI BLACK MANDARIN", + direction="on", + linebreak="id", + unicodeslot=0x1FA68, + }, + [0x1FA69]={ + category="so", + description="XIANGQI BLACK ELEPHANT", + direction="on", + linebreak="id", + unicodeslot=0x1FA69, + }, + [0x1FA6A]={ + category="so", + description="XIANGQI BLACK HORSE", + direction="on", + linebreak="id", + unicodeslot=0x1FA6A, + }, + [0x1FA6B]={ + category="so", + description="XIANGQI BLACK CHARIOT", + direction="on", + linebreak="id", + unicodeslot=0x1FA6B, + }, + [0x1FA6C]={ + category="so", + description="XIANGQI BLACK CANNON", + direction="on", + linebreak="id", + unicodeslot=0x1FA6C, + }, + [0x1FA6D]={ + category="so", + description="XIANGQI BLACK SOLDIER", + direction="on", + linebreak="id", + unicodeslot=0x1FA6D, + }, [0x2F800]={ category="lo", cjkwd="w", diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-emj.lua b/Master/texmf-dist/tex/context/base/mkiv/char-emj.lua index 718d3bc6efb..b00e9ebf809 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-emj.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-emj.lua @@ -13,60 +13,42 @@ return { ["1st place medal"]={ 0x1F947 }, ["2nd place medal"]={ 0x1F948 }, ["3rd place medal"]={ 0x1F949 }, - ["a button (blood type)"]={ 0x1F170 }, + ["a button (blood type)"]={ 0x1F170, 0xFE0F }, ["ab button (blood type)"]={ 0x1F18E }, - ["admission tickets"]={ 0x1F39F }, - ["adult"]={ 0x1F9D1 }, - ["adult: dark skin tone"]={ 0x1F9D1, 0x1F3FF }, - ["adult: light skin tone"]={ 0x1F9D1, 0x1F3FB }, - ["adult: medium skin tone"]={ 0x1F9D1, 0x1F3FD }, - ["adult: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE }, - ["adult: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC }, + ["abacus"]={ 0x1F9EE }, + ["adhesive bandage"]={ 0x1FA79 }, + ["admission tickets"]={ 0x1F39F, 0xFE0F }, ["aerial tramway"]={ 0x1F6A1 }, - ["afghanistan"]={ 0x1F1E6, 0x1F1EB }, - ["airplane"]={ 0x2708 }, + ["airplane"]={ 0x2708, 0xFE0F }, ["airplane arrival"]={ 0x1F6EC }, ["airplane departure"]={ 0x1F6EB }, ["alarm clock"]={ 0x23F0 }, - ["albania"]={ 0x1F1E6, 0x1F1F1 }, - ["alembic"]={ 0x2697 }, - ["algeria"]={ 0x1F1E9, 0x1F1FF }, + ["alembic"]={ 0x2697, 0xFE0F }, ["alien"]={ 0x1F47D }, ["alien monster"]={ 0x1F47E }, ["ambulance"]={ 0x1F691 }, ["american football"]={ 0x1F3C8 }, - ["american samoa"]={ 0x1F1E6, 0x1F1F8 }, ["amphora"]={ 0x1F3FA }, ["anchor"]={ 0x2693 }, - ["andorra"]={ 0x1F1E6, 0x1F1E9 }, ["anger symbol"]={ 0x1F4A2 }, - ["angola"]={ 0x1F1E6, 0x1F1F4 }, ["angry face"]={ 0x1F620 }, ["angry face with horns"]={ 0x1F47F }, - ["anguilla"]={ 0x1F1E6, 0x1F1EE }, ["anguished face"]={ 0x1F627 }, ["ant"]={ 0x1F41C }, - ["antarctica"]={ 0x1F1E6, 0x1F1F6 }, ["antenna bars"]={ 0x1F4F6 }, - ["anticlockwise arrows button"]={ 0x1F504 }, - ["antigua & barbuda"]={ 0x1F1E6, 0x1F1EC }, + ["anxious face with sweat"]={ 0x1F630 }, ["aquarius"]={ 0x2652 }, - ["argentina"]={ 0x1F1E6, 0x1F1F7 }, ["aries"]={ 0x2648 }, - ["armenia"]={ 0x1F1E6, 0x1F1F2 }, ["articulated lorry"]={ 0x1F69B }, ["artist palette"]={ 0x1F3A8 }, - ["aruba"]={ 0x1F1E6, 0x1F1FC }, - ["ascension island"]={ 0x1F1E6, 0x1F1E8 }, ["astonished face"]={ 0x1F632 }, ["atm sign"]={ 0x1F3E7 }, - ["atom symbol"]={ 0x269B }, - ["australia"]={ 0x1F1E6, 0x1F1FA }, - ["austria"]={ 0x1F1E6, 0x1F1F9 }, + ["atom symbol"]={ 0x269B, 0xFE0F }, + ["auto rickshaw"]={ 0x1F6FA }, ["automobile"]={ 0x1F697 }, ["avocado"]={ 0x1F951 }, - ["azerbaijan"]={ 0x1F1E6, 0x1F1FF }, - ["b button (blood type)"]={ 0x1F171 }, + ["axe"]={ 0x1FA93 }, + ["b button (blood type)"]={ 0x1F171, 0xFE0F }, ["baby"]={ 0x1F476 }, ["baby angel"]={ 0x1F47C }, ["baby angel: dark skin tone"]={ 0x1F47C, 0x1F3FF }, @@ -107,97 +89,68 @@ return { ["backhand index pointing up: medium skin tone"]={ 0x1F446, 0x1F3FD }, ["backhand index pointing up: medium-dark skin tone"]={ 0x1F446, 0x1F3FE }, ["backhand index pointing up: medium-light skin tone"]={ 0x1F446, 0x1F3FC }, + ["backpack"]={ 0x1F392 }, ["bacon"]={ 0x1F953 }, + ["badger"]={ 0x1F9A1 }, ["badminton"]={ 0x1F3F8 }, + ["bagel"]={ 0x1F96F }, ["baggage claim"]={ 0x1F6C4 }, ["baguette bread"]={ 0x1F956 }, - ["bahamas"]={ 0x1F1E7, 0x1F1F8 }, - ["bahrain"]={ 0x1F1E7, 0x1F1ED }, - ["balance scale"]={ 0x2696 }, + ["balance scale"]={ 0x2696, 0xFE0F }, + ["ballet shoes"]={ 0x1FA70 }, ["balloon"]={ 0x1F388 }, - ["ballot box with ballot"]={ 0x1F5F3 }, - ["ballot box with check"]={ 0x2611 }, + ["ballot box with ballot"]={ 0x1F5F3, 0xFE0F }, ["banana"]={ 0x1F34C }, - ["bangladesh"]={ 0x1F1E7, 0x1F1E9 }, + ["banjo"]={ 0x1FA95 }, ["bank"]={ 0x1F3E6 }, ["bar chart"]={ 0x1F4CA }, - ["barbados"]={ 0x1F1E7, 0x1F1E7 }, ["barber pole"]={ 0x1F488 }, ["baseball"]={ 0x26BE }, + ["basket"]={ 0x1F9FA }, ["basketball"]={ 0x1F3C0 }, ["bat"]={ 0x1F987 }, ["bathtub"]={ 0x1F6C1 }, ["battery"]={ 0x1F50B }, - ["beach with umbrella"]={ 0x1F3D6 }, - ["bear face"]={ 0x1F43B }, - ["bearded person"]={ 0x1F9D4 }, - ["bearded person: dark skin tone"]={ 0x1F9D4, 0x1F3FF }, - ["bearded person: light skin tone"]={ 0x1F9D4, 0x1F3FB }, - ["bearded person: medium skin tone"]={ 0x1F9D4, 0x1F3FD }, - ["bearded person: medium-dark skin tone"]={ 0x1F9D4, 0x1F3FE }, - ["bearded person: medium-light skin tone"]={ 0x1F9D4, 0x1F3FC }, + ["beach with umbrella"]={ 0x1F3D6, 0xFE0F }, + ["beaming face with smiling eyes"]={ 0x1F601 }, + ["bear"]={ 0x1F43B }, ["beating heart"]={ 0x1F493 }, - ["bed"]={ 0x1F6CF }, + ["bed"]={ 0x1F6CF, 0xFE0F }, ["beer mug"]={ 0x1F37A }, - ["belarus"]={ 0x1F1E7, 0x1F1FE }, - ["belgium"]={ 0x1F1E7, 0x1F1EA }, - ["belize"]={ 0x1F1E7, 0x1F1FF }, ["bell"]={ 0x1F514 }, ["bell with slash"]={ 0x1F515 }, - ["bellhop bell"]={ 0x1F6CE }, - ["benin"]={ 0x1F1E7, 0x1F1EF }, + ["bellhop bell"]={ 0x1F6CE, 0xFE0F }, ["bento box"]={ 0x1F371 }, - ["bermuda"]={ 0x1F1E7, 0x1F1F2 }, - ["bhutan"]={ 0x1F1E7, 0x1F1F9 }, + ["beverage box"]={ 0x1F9C3 }, ["bicycle"]={ 0x1F6B2 }, ["bikini"]={ 0x1F459 }, ["billed cap"]={ 0x1F9E2 }, - ["biohazard"]={ 0x2623 }, + ["biohazard"]={ 0x2623, 0xFE0F }, ["bird"]={ 0x1F426 }, ["birthday cake"]={ 0x1F382 }, ["black circle"]={ 0x26AB }, ["black flag"]={ 0x1F3F4 }, ["black heart"]={ 0x1F5A4 }, ["black large square"]={ 0x2B1B }, - ["black medium square"]={ 0x25FC }, + ["black medium square"]={ 0x25FC, 0xFE0F }, ["black medium-small square"]={ 0x25FE }, - ["black nib"]={ 0x2712 }, - ["black small square"]={ 0x25AA }, + ["black nib"]={ 0x2712, 0xFE0F }, + ["black small square"]={ 0x25AA, 0xFE0F }, ["black square button"]={ 0x1F532 }, - ["blond-haired man"]={ 0x1F471, 0x200D, 0x2642 }, - ["blond-haired man: dark skin tone"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2642 }, - ["blond-haired man: light skin tone"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2642 }, - ["blond-haired man: medium skin tone"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2642 }, - ["blond-haired man: medium-dark skin tone"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2642 }, - ["blond-haired man: medium-light skin tone"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2642 }, - ["blond-haired person"]={ 0x1F471 }, - ["blond-haired person: dark skin tone"]={ 0x1F471, 0x1F3FF }, - ["blond-haired person: light skin tone"]={ 0x1F471, 0x1F3FB }, - ["blond-haired person: medium skin tone"]={ 0x1F471, 0x1F3FD }, - ["blond-haired person: medium-dark skin tone"]={ 0x1F471, 0x1F3FE }, - ["blond-haired person: medium-light skin tone"]={ 0x1F471, 0x1F3FC }, - ["blond-haired woman"]={ 0x1F471, 0x200D, 0x2640 }, - ["blond-haired woman: dark skin tone"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2640 }, - ["blond-haired woman: light skin tone"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2640 }, - ["blond-haired woman: medium skin tone"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2640 }, - ["blond-haired woman: medium-dark skin tone"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2640 }, - ["blond-haired woman: medium-light skin tone"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2640 }, ["blossom"]={ 0x1F33C }, ["blowfish"]={ 0x1F421 }, ["blue book"]={ 0x1F4D8 }, ["blue circle"]={ 0x1F535 }, ["blue heart"]={ 0x1F499 }, + ["blue square"]={ 0x1F7E6 }, ["boar"]={ 0x1F417 }, - ["bolivia"]={ 0x1F1E7, 0x1F1F4 }, ["bomb"]={ 0x1F4A3 }, + ["bone"]={ 0x1F9B4 }, ["bookmark"]={ 0x1F516 }, ["bookmark tabs"]={ 0x1F4D1 }, ["books"]={ 0x1F4DA }, - ["bosnia & herzegovina"]={ 0x1F1E7, 0x1F1E6 }, - ["botswana"]={ 0x1F1E7, 0x1F1FC }, ["bottle with popping cork"]={ 0x1F37E }, ["bouquet"]={ 0x1F490 }, - ["bouvet island"]={ 0x1F1E7, 0x1F1FB }, ["bow and arrow"]={ 0x1F3F9 }, ["bowl with spoon"]={ 0x1F963 }, ["bowling"]={ 0x1F3B3 }, @@ -209,7 +162,6 @@ return { ["boy: medium-dark skin tone"]={ 0x1F466, 0x1F3FE }, ["boy: medium-light skin tone"]={ 0x1F466, 0x1F3FC }, ["brain"]={ 0x1F9E0 }, - ["brazil"]={ 0x1F1E7, 0x1F1F7 }, ["bread"]={ 0x1F35E }, ["breast-feeding"]={ 0x1F931 }, ["breast-feeding: dark skin tone"]={ 0x1F931, 0x1F3FF }, @@ -217,6 +169,7 @@ return { ["breast-feeding: medium skin tone"]={ 0x1F931, 0x1F3FD }, ["breast-feeding: medium-dark skin tone"]={ 0x1F931, 0x1F3FE }, ["breast-feeding: medium-light skin tone"]={ 0x1F931, 0x1F3FC }, + ["brick"]={ 0x1F9F1 }, ["bride with veil"]={ 0x1F470 }, ["bride with veil: dark skin tone"]={ 0x1F470, 0x1F3FF }, ["bride with veil: light skin tone"]={ 0x1F470, 0x1F3FB }, @@ -226,21 +179,21 @@ return { ["bridge at night"]={ 0x1F309 }, ["briefcase"]={ 0x1F4BC }, ["bright button"]={ 0x1F506 }, - ["british indian ocean territory"]={ 0x1F1EE, 0x1F1F4 }, - ["british virgin islands"]={ 0x1F1FB, 0x1F1EC }, ["broccoli"]={ 0x1F966 }, ["broken heart"]={ 0x1F494 }, - ["brunei"]={ 0x1F1E7, 0x1F1F3 }, + ["broom"]={ 0x1F9F9 }, + ["brown circle"]={ 0x1F7E4 }, + ["brown heart"]={ 0x1F90E }, + ["brown square"]={ 0x1F7EB }, ["bug"]={ 0x1F41B }, - ["building construction"]={ 0x1F3D7 }, - ["bulgaria"]={ 0x1F1E7, 0x1F1EC }, - ["burkina faso"]={ 0x1F1E7, 0x1F1EB }, + ["building construction"]={ 0x1F3D7, 0xFE0F }, + ["bullet train"]={ 0x1F685 }, ["burrito"]={ 0x1F32F }, - ["burundi"]={ 0x1F1E7, 0x1F1EE }, ["bus"]={ 0x1F68C }, ["bus stop"]={ 0x1F68F }, ["bust in silhouette"]={ 0x1F464 }, ["busts in silhouette"]={ 0x1F465 }, + ["butter"]={ 0x1F9C8 }, ["butterfly"]={ 0x1F98B }, ["cactus"]={ 0x1F335 }, ["calendar"]={ 0x1F4C5 }, @@ -250,45 +203,40 @@ return { ["call me hand: medium skin tone"]={ 0x1F919, 0x1F3FD }, ["call me hand: medium-dark skin tone"]={ 0x1F919, 0x1F3FE }, ["call me hand: medium-light skin tone"]={ 0x1F919, 0x1F3FC }, - ["cambodia"]={ 0x1F1F0, 0x1F1ED }, ["camel"]={ 0x1F42A }, ["camera"]={ 0x1F4F7 }, ["camera with flash"]={ 0x1F4F8 }, - ["cameroon"]={ 0x1F1E8, 0x1F1F2 }, - ["camping"]={ 0x1F3D5 }, - ["canada"]={ 0x1F1E8, 0x1F1E6 }, - ["canary islands"]={ 0x1F1EE, 0x1F1E8 }, + ["camping"]={ 0x1F3D5, 0xFE0F }, ["cancer"]={ 0x264B }, - ["candle"]={ 0x1F56F }, + ["candle"]={ 0x1F56F, 0xFE0F }, ["candy"]={ 0x1F36C }, ["canned food"]={ 0x1F96B }, ["canoe"]={ 0x1F6F6 }, - ["cape verde"]={ 0x1F1E8, 0x1F1FB }, ["capricorn"]={ 0x2651 }, - ["card file box"]={ 0x1F5C3 }, + ["card file box"]={ 0x1F5C3, 0xFE0F }, ["card index"]={ 0x1F4C7 }, - ["card index dividers"]={ 0x1F5C2 }, - ["caribbean netherlands"]={ 0x1F1E7, 0x1F1F6 }, + ["card index dividers"]={ 0x1F5C2, 0xFE0F }, ["carousel horse"]={ 0x1F3A0 }, ["carp streamer"]={ 0x1F38F }, ["carrot"]={ 0x1F955 }, ["castle"]={ 0x1F3F0 }, ["cat"]={ 0x1F408 }, ["cat face"]={ 0x1F431 }, - ["cat face with tears of joy"]={ 0x1F639 }, - ["cat face with wry smile"]={ 0x1F63C }, - ["cayman islands"]={ 0x1F1F0, 0x1F1FE }, - ["central african republic"]={ 0x1F1E8, 0x1F1EB }, - ["ceuta & melilla"]={ 0x1F1EA, 0x1F1E6 }, - ["chad"]={ 0x1F1F9, 0x1F1E9 }, - ["chains"]={ 0x26D3 }, + ["cat with tears of joy"]={ 0x1F639 }, + ["cat with wry smile"]={ 0x1F63C }, + ["chains"]={ 0x26D3, 0xFE0F }, + ["chair"]={ 0x1FA91 }, ["chart decreasing"]={ 0x1F4C9 }, ["chart increasing"]={ 0x1F4C8 }, ["chart increasing with yen"]={ 0x1F4B9 }, + ["check box with check"]={ 0x2611, 0xFE0F }, + ["check mark"]={ 0x2714, 0xFE0F }, + ["check mark button"]={ 0x2705 }, ["cheese wedge"]={ 0x1F9C0 }, ["chequered flag"]={ 0x1F3C1 }, ["cherries"]={ 0x1F352 }, ["cherry blossom"]={ 0x1F338 }, + ["chess pawn"]={ 0x265F, 0xFE0F }, ["chestnut"]={ 0x1F330 }, ["chicken"]={ 0x1F414 }, ["child"]={ 0x1F9D2 }, @@ -298,22 +246,19 @@ return { ["child: medium-dark skin tone"]={ 0x1F9D2, 0x1F3FE }, ["child: medium-light skin tone"]={ 0x1F9D2, 0x1F3FC }, ["children crossing"]={ 0x1F6B8 }, - ["chile"]={ 0x1F1E8, 0x1F1F1 }, - ["china"]={ 0x1F1E8, 0x1F1F3 }, - ["chipmunk"]={ 0x1F43F }, + ["chipmunk"]={ 0x1F43F, 0xFE0F }, ["chocolate bar"]={ 0x1F36B }, ["chopsticks"]={ 0x1F962 }, - ["christmas island"]={ 0x1F1E8, 0x1F1FD }, ["christmas tree"]={ 0x1F384 }, ["church"]={ 0x26EA }, ["cigarette"]={ 0x1F6AC }, ["cinema"]={ 0x1F3A6 }, - ["circled m"]={ 0x24C2 }, + ["circled m"]={ 0x24C2, 0xFE0F }, ["circus tent"]={ 0x1F3AA }, - ["cityscape"]={ 0x1F3D9 }, + ["cityscape"]={ 0x1F3D9, 0xFE0F }, ["cityscape at dusk"]={ 0x1F306 }, ["cl button"]={ 0x1F191 }, - ["clamp"]={ 0x1F5DC }, + ["clamp"]={ 0x1F5DC, 0xFE0F }, ["clapper board"]={ 0x1F3AC }, ["clapping hands"]={ 0x1F44F }, ["clapping hands: dark skin tone"]={ 0x1F44F, 0x1F3FF }, @@ -321,40 +266,36 @@ return { ["clapping hands: medium skin tone"]={ 0x1F44F, 0x1F3FD }, ["clapping hands: medium-dark skin tone"]={ 0x1F44F, 0x1F3FE }, ["clapping hands: medium-light skin tone"]={ 0x1F44F, 0x1F3FC }, - ["classical building"]={ 0x1F3DB }, + ["classical building"]={ 0x1F3DB, 0xFE0F }, ["clinking beer mugs"]={ 0x1F37B }, ["clinking glasses"]={ 0x1F942 }, ["clipboard"]={ 0x1F4CB }, - ["clipperton island"]={ 0x1F1E8, 0x1F1F5 }, ["clockwise vertical arrows"]={ 0x1F503 }, ["closed book"]={ 0x1F4D5 }, ["closed mailbox with lowered flag"]={ 0x1F4EA }, ["closed mailbox with raised flag"]={ 0x1F4EB }, ["closed umbrella"]={ 0x1F302 }, - ["cloud"]={ 0x2601 }, - ["cloud with lightning"]={ 0x1F329 }, - ["cloud with lightning and rain"]={ 0x26C8 }, - ["cloud with rain"]={ 0x1F327 }, - ["cloud with snow"]={ 0x1F328 }, + ["cloud"]={ 0x2601, 0xFE0F }, + ["cloud with lightning"]={ 0x1F329, 0xFE0F }, + ["cloud with lightning and rain"]={ 0x26C8, 0xFE0F }, + ["cloud with rain"]={ 0x1F327, 0xFE0F }, + ["cloud with snow"]={ 0x1F328, 0xFE0F }, ["clown face"]={ 0x1F921 }, - ["club suit"]={ 0x2663 }, + ["club suit"]={ 0x2663, 0xFE0F }, ["clutch bag"]={ 0x1F45D }, ["coat"]={ 0x1F9E5 }, ["cocktail glass"]={ 0x1F378 }, ["coconut"]={ 0x1F965 }, - ["cocos (keeling) islands"]={ 0x1F1E8, 0x1F1E8 }, - ["coffin"]={ 0x26B0 }, + ["coffin"]={ 0x26B0, 0xFE0F }, + ["cold face"]={ 0x1F976 }, ["collision"]={ 0x1F4A5 }, - ["colombia"]={ 0x1F1E8, 0x1F1F4 }, - ["comet"]={ 0x2604 }, - ["comoros"]={ 0x1F1F0, 0x1F1F2 }, + ["comet"]={ 0x2604, 0xFE0F }, + ["compass"]={ 0x1F9ED }, ["computer disk"]={ 0x1F4BD }, - ["computer mouse"]={ 0x1F5B1 }, + ["computer mouse"]={ 0x1F5B1, 0xFE0F }, ["confetti ball"]={ 0x1F38A }, ["confounded face"]={ 0x1F616 }, ["confused face"]={ 0x1F615 }, - ["congo - brazzaville"]={ 0x1F1E8, 0x1F1EC }, - ["congo - kinshasa"]={ 0x1F1E8, 0x1F1E9 }, ["construction"]={ 0x1F6A7 }, ["construction worker"]={ 0x1F477 }, ["construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF }, @@ -362,30 +303,28 @@ return { ["construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD }, ["construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE }, ["construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC }, - ["control knobs"]={ 0x1F39B }, + ["control knobs"]={ 0x1F39B, 0xFE0F }, ["convenience store"]={ 0x1F3EA }, - ["cook islands"]={ 0x1F1E8, 0x1F1F0 }, ["cooked rice"]={ 0x1F35A }, ["cookie"]={ 0x1F36A }, ["cooking"]={ 0x1F373 }, ["cool button"]={ 0x1F192 }, - ["copyright"]={ 0xA9 }, - ["costa rica"]={ 0x1F1E8, 0x1F1F7 }, - ["couch and lamp"]={ 0x1F6CB }, + ["copyright"]={ 0xA9, 0xFE0F }, + ["couch and lamp"]={ 0x1F6CB, 0xFE0F }, + ["counterclockwise arrows button"]={ 0x1F504 }, ["couple with heart"]={ 0x1F491 }, - ["couple with heart: man, man"]={ 0x1F468, 0x200D, 0x2764, 0x200D, 0x1F468 }, - ["couple with heart: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F468 }, - ["couple with heart: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F469 }, + ["couple with heart: man, man"]={ 0x1F468, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F468 }, + ["couple with heart: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F468 }, + ["couple with heart: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F469 }, ["cow"]={ 0x1F404 }, ["cow face"]={ 0x1F42E }, ["cowboy hat face"]={ 0x1F920 }, ["crab"]={ 0x1F980 }, - ["crayon"]={ 0x1F58D }, - ["crazy face"]={ 0x1F92A }, + ["crayon"]={ 0x1F58D, 0xFE0F }, ["credit card"]={ 0x1F4B3 }, ["crescent moon"]={ 0x1F319 }, - ["cricket"]={ 0x1F3CF }, - ["croatia"]={ 0x1F1ED, 0x1F1F7 }, + ["cricket"]={ 0x1F997 }, + ["cricket game"]={ 0x1F3CF }, ["crocodile"]={ 0x1F40A }, ["croissant"]={ 0x1F950 }, ["cross mark"]={ 0x274C }, @@ -397,15 +336,14 @@ return { ["crossed fingers: medium-dark skin tone"]={ 0x1F91E, 0x1F3FE }, ["crossed fingers: medium-light skin tone"]={ 0x1F91E, 0x1F3FC }, ["crossed flags"]={ 0x1F38C }, - ["crossed swords"]={ 0x2694 }, + ["crossed swords"]={ 0x2694, 0xFE0F }, ["crown"]={ 0x1F451 }, - ["crying cat face"]={ 0x1F63F }, + ["crying cat"]={ 0x1F63F }, ["crying face"]={ 0x1F622 }, ["crystal ball"]={ 0x1F52E }, - ["cuba"]={ 0x1F1E8, 0x1F1FA }, ["cucumber"]={ 0x1F952 }, ["cup with straw"]={ 0x1F964 }, - ["curaçao"]={ 0x1F1E8, 0x1F1FC }, + ["cupcake"]={ 0x1F9C1 }, ["curling stone"]={ 0x1F94C }, ["curly loop"]={ 0x27B0 }, ["currency exchange"]={ 0x1F4B1 }, @@ -414,57 +352,72 @@ return { ["customs"]={ 0x1F6C3 }, ["cut of meat"]={ 0x1F969 }, ["cyclone"]={ 0x1F300 }, - ["cyprus"]={ 0x1F1E8, 0x1F1FE }, - ["czechia"]={ 0x1F1E8, 0x1F1FF }, - ["côte d’ivoire"]={ 0x1F1E8, 0x1F1EE }, - ["dagger"]={ 0x1F5E1 }, + ["dagger"]={ 0x1F5E1, 0xFE0F }, ["dango"]={ 0x1F361 }, ["dashing away"]={ 0x1F4A8 }, + ["deaf man"]={ 0x1F9CF, 0x200D, 0x2642, 0xFE0F }, + ["deaf man: dark skin tone"]={ 0x1F9CF, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["deaf man: light skin tone"]={ 0x1F9CF, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["deaf man: medium skin tone"]={ 0x1F9CF, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["deaf man: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["deaf man: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["deaf person"]={ 0x1F9CF }, + ["deaf person: dark skin tone"]={ 0x1F9CF, 0x1F3FF }, + ["deaf person: light skin tone"]={ 0x1F9CF, 0x1F3FB }, + ["deaf person: medium skin tone"]={ 0x1F9CF, 0x1F3FD }, + ["deaf person: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE }, + ["deaf person: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC }, + ["deaf woman"]={ 0x1F9CF, 0x200D, 0x2640, 0xFE0F }, + ["deaf woman: dark skin tone"]={ 0x1F9CF, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["deaf woman: light skin tone"]={ 0x1F9CF, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["deaf woman: medium skin tone"]={ 0x1F9CF, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["deaf woman: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["deaf woman: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["deciduous tree"]={ 0x1F333 }, ["deer"]={ 0x1F98C }, ["delivery truck"]={ 0x1F69A }, - ["denmark"]={ 0x1F1E9, 0x1F1F0 }, ["department store"]={ 0x1F3EC }, - ["derelict house"]={ 0x1F3DA }, - ["desert"]={ 0x1F3DC }, - ["desert island"]={ 0x1F3DD }, - ["desktop computer"]={ 0x1F5A5 }, - ["detective"]={ 0x1F575 }, + ["derelict house"]={ 0x1F3DA, 0xFE0F }, + ["desert"]={ 0x1F3DC, 0xFE0F }, + ["desert island"]={ 0x1F3DD, 0xFE0F }, + ["desktop computer"]={ 0x1F5A5, 0xFE0F }, + ["detective"]={ 0x1F575, 0xFE0F }, ["detective: dark skin tone"]={ 0x1F575, 0x1F3FF }, ["detective: light skin tone"]={ 0x1F575, 0x1F3FB }, ["detective: medium skin tone"]={ 0x1F575, 0x1F3FD }, ["detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE }, ["detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC }, - ["diamond suit"]={ 0x2666 }, + ["diamond suit"]={ 0x2666, 0xFE0F }, ["diamond with a dot"]={ 0x1F4A0 }, - ["diego garcia"]={ 0x1F1E9, 0x1F1EC }, ["dim button"]={ 0x1F505 }, ["direct hit"]={ 0x1F3AF }, - ["disappointed but relieved face"]={ 0x1F625 }, ["disappointed face"]={ 0x1F61E }, + ["diving mask"]={ 0x1F93F }, + ["division sign"]={ 0x2797 }, + ["diya lamp"]={ 0x1FA94 }, ["dizzy"]={ 0x1F4AB }, ["dizzy face"]={ 0x1F635 }, - ["djibouti"]={ 0x1F1E9, 0x1F1EF }, + ["dna"]={ 0x1F9EC }, ["dog"]={ 0x1F415 }, ["dog face"]={ 0x1F436 }, ["dollar banknote"]={ 0x1F4B5 }, ["dolphin"]={ 0x1F42C }, - ["dominica"]={ 0x1F1E9, 0x1F1F2 }, - ["dominican republic"]={ 0x1F1E9, 0x1F1F4 }, ["door"]={ 0x1F6AA }, ["dotted six-pointed star"]={ 0x1F52F }, ["double curly loop"]={ 0x27BF }, - ["double exclamation mark"]={ 0x203C }, + ["double exclamation mark"]={ 0x203C, 0xFE0F }, ["doughnut"]={ 0x1F369 }, - ["dove"]={ 0x1F54A }, - ["down arrow"]={ 0x2B07 }, - ["down button"]={ 0x1F53D }, - ["down-left arrow"]={ 0x2199 }, - ["down-right arrow"]={ 0x2198 }, + ["dove"]={ 0x1F54A, 0xFE0F }, + ["down arrow"]={ 0x2B07, 0xFE0F }, + ["down-left arrow"]={ 0x2199, 0xFE0F }, + ["down-right arrow"]={ 0x2198, 0xFE0F }, + ["downcast face with sweat"]={ 0x1F613 }, + ["downwards button"]={ 0x1F53D }, ["dragon"]={ 0x1F409 }, ["dragon face"]={ 0x1F432 }, ["dress"]={ 0x1F457 }, ["drooling face"]={ 0x1F924 }, + ["drop of blood"]={ 0x1FA78 }, ["droplet"]={ 0x1F4A7 }, ["drum"]={ 0x1F941 }, ["duck"]={ 0x1F986 }, @@ -474,21 +427,24 @@ return { ["eagle"]={ 0x1F985 }, ["ear"]={ 0x1F442 }, ["ear of corn"]={ 0x1F33D }, + ["ear with hearing aid"]={ 0x1F9BB }, + ["ear with hearing aid: dark skin tone"]={ 0x1F9BB, 0x1F3FF }, + ["ear with hearing aid: light skin tone"]={ 0x1F9BB, 0x1F3FB }, + ["ear with hearing aid: medium skin tone"]={ 0x1F9BB, 0x1F3FD }, + ["ear with hearing aid: medium-dark skin tone"]={ 0x1F9BB, 0x1F3FE }, + ["ear with hearing aid: medium-light skin tone"]={ 0x1F9BB, 0x1F3FC }, ["ear: dark skin tone"]={ 0x1F442, 0x1F3FF }, ["ear: light skin tone"]={ 0x1F442, 0x1F3FB }, ["ear: medium skin tone"]={ 0x1F442, 0x1F3FD }, ["ear: medium-dark skin tone"]={ 0x1F442, 0x1F3FE }, ["ear: medium-light skin tone"]={ 0x1F442, 0x1F3FC }, - ["ecuador"]={ 0x1F1EA, 0x1F1E8 }, ["egg"]={ 0x1F95A }, ["eggplant"]={ 0x1F346 }, - ["egypt"]={ 0x1F1EA, 0x1F1EC }, ["eight o’clock"]={ 0x1F557 }, - ["eight-pointed star"]={ 0x2734 }, - ["eight-spoked asterisk"]={ 0x2733 }, + ["eight-pointed star"]={ 0x2734, 0xFE0F }, + ["eight-spoked asterisk"]={ 0x2733, 0xFE0F }, ["eight-thirty"]={ 0x1F563 }, - ["eject button"]={ 0x23CF }, - ["el salvador"]={ 0x1F1F8, 0x1F1FB }, + ["eject button"]={ 0x23CF, 0xFE0F }, ["electric plug"]={ 0x1F50C }, ["elephant"]={ 0x1F418 }, ["eleven o’clock"]={ 0x1F55A }, @@ -500,44 +456,34 @@ return { ["elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE }, ["elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC }, ["end arrow"]={ 0x1F51A }, - ["england"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0065, 0xE006E, 0xE0067, 0xE007F }, - ["envelope"]={ 0x2709 }, + ["envelope"]={ 0x2709, 0xFE0F }, ["envelope with arrow"]={ 0x1F4E9 }, - ["equatorial guinea"]={ 0x1F1EC, 0x1F1F6 }, - ["eritrea"]={ 0x1F1EA, 0x1F1F7 }, - ["estonia"]={ 0x1F1EA, 0x1F1EA }, - ["ethiopia"]={ 0x1F1EA, 0x1F1F9 }, ["euro banknote"]={ 0x1F4B6 }, - ["european union"]={ 0x1F1EA, 0x1F1FA }, ["evergreen tree"]={ 0x1F332 }, ["ewe"]={ 0x1F411 }, ["exclamation mark"]={ 0x2757 }, - ["exclamation question mark"]={ 0x2049 }, + ["exclamation question mark"]={ 0x2049, 0xFE0F }, ["exploding head"]={ 0x1F92F }, ["expressionless face"]={ 0x1F611 }, - ["eye"]={ 0x1F441 }, - ["eye in speech bubble"]={ 0x1F441, 0x200D, 0x1F5E8 }, + ["eye"]={ 0x1F441, 0xFE0F }, + ["eye in speech bubble"]={ 0x1F441, 0xFE0F, 0x200D, 0x1F5E8, 0xFE0F }, ["eyes"]={ 0x1F440 }, ["face blowing a kiss"]={ 0x1F618 }, - ["face savouring delicious food"]={ 0x1F60B }, + ["face savoring food"]={ 0x1F60B }, ["face screaming in fear"]={ 0x1F631 }, ["face vomiting"]={ 0x1F92E }, - ["face with cold sweat"]={ 0x1F613 }, ["face with hand over mouth"]={ 0x1F92D }, ["face with head-bandage"]={ 0x1F915 }, ["face with medical mask"]={ 0x1F637 }, ["face with monocle"]={ 0x1F9D0 }, ["face with open mouth"]={ 0x1F62E }, - ["face with open mouth & cold sweat"]={ 0x1F630 }, ["face with raised eyebrow"]={ 0x1F928 }, ["face with rolling eyes"]={ 0x1F644 }, ["face with steam from nose"]={ 0x1F624 }, - ["face with stuck-out tongue"]={ 0x1F61B }, - ["face with stuck-out tongue & closed eyes"]={ 0x1F61D }, - ["face with stuck-out tongue & winking eye"]={ 0x1F61C }, - ["face with symbols over mouth"]={ 0x1F92C }, + ["face with symbols on mouth"]={ 0x1F92C }, ["face with tears of joy"]={ 0x1F602 }, ["face with thermometer"]={ 0x1F912 }, + ["face with tongue"]={ 0x1F61B }, ["face without mouth"]={ 0x1F636 }, ["factory"]={ 0x1F3ED }, ["fairy"]={ 0x1F9DA }, @@ -546,7 +492,7 @@ return { ["fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD }, ["fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE }, ["fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC }, - ["falkland islands"]={ 0x1F1EB, 0x1F1F0 }, + ["falafel"]={ 0x1F9C6 }, ["fallen leaf"]={ 0x1F342 }, ["family"]={ 0x1F46A }, ["family: man, boy"]={ 0x1F468, 0x200D, 0x1F466 }, @@ -574,36 +520,298 @@ return { ["family: woman, woman, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467 }, ["family: woman, woman, girl, boy"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F466 }, ["family: woman, woman, girl, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F467 }, - ["faroe islands"]={ 0x1F1EB, 0x1F1F4 }, ["fast down button"]={ 0x23EC }, ["fast reverse button"]={ 0x23EA }, ["fast up button"]={ 0x23EB }, ["fast-forward button"]={ 0x23E9 }, ["fax machine"]={ 0x1F4E0 }, ["fearful face"]={ 0x1F628 }, - ["female sign"]={ 0x2640 }, + ["female sign"]={ 0x2640, 0xFE0F }, ["ferris wheel"]={ 0x1F3A1 }, - ["ferry"]={ 0x26F4 }, + ["ferry"]={ 0x26F4, 0xFE0F }, ["field hockey"]={ 0x1F3D1 }, - ["fiji"]={ 0x1F1EB, 0x1F1EF }, - ["file cabinet"]={ 0x1F5C4 }, + ["file cabinet"]={ 0x1F5C4, 0xFE0F }, ["file folder"]={ 0x1F4C1 }, - ["film frames"]={ 0x1F39E }, - ["film projector"]={ 0x1F4FD }, - ["finland"]={ 0x1F1EB, 0x1F1EE }, + ["film frames"]={ 0x1F39E, 0xFE0F }, + ["film projector"]={ 0x1F4FD, 0xFE0F }, ["fire"]={ 0x1F525 }, ["fire engine"]={ 0x1F692 }, + ["fire extinguisher"]={ 0x1F9EF }, + ["firecracker"]={ 0x1F9E8 }, ["fireworks"]={ 0x1F386 }, ["first quarter moon"]={ 0x1F313 }, - ["first quarter moon with face"]={ 0x1F31B }, + ["first quarter moon face"]={ 0x1F31B }, ["fish"]={ 0x1F41F }, ["fish cake with swirl"]={ 0x1F365 }, ["fishing pole"]={ 0x1F3A3 }, ["five o’clock"]={ 0x1F554 }, ["five-thirty"]={ 0x1F560 }, ["flag in hole"]={ 0x26F3 }, + ["flag: afghanistan"]={ 0x1F1E6, 0x1F1EB }, + ["flag: albania"]={ 0x1F1E6, 0x1F1F1 }, + ["flag: algeria"]={ 0x1F1E9, 0x1F1FF }, + ["flag: american samoa"]={ 0x1F1E6, 0x1F1F8 }, + ["flag: andorra"]={ 0x1F1E6, 0x1F1E9 }, + ["flag: angola"]={ 0x1F1E6, 0x1F1F4 }, + ["flag: anguilla"]={ 0x1F1E6, 0x1F1EE }, + ["flag: antarctica"]={ 0x1F1E6, 0x1F1F6 }, + ["flag: antigua & barbuda"]={ 0x1F1E6, 0x1F1EC }, + ["flag: argentina"]={ 0x1F1E6, 0x1F1F7 }, + ["flag: armenia"]={ 0x1F1E6, 0x1F1F2 }, + ["flag: aruba"]={ 0x1F1E6, 0x1F1FC }, + ["flag: ascension island"]={ 0x1F1E6, 0x1F1E8 }, + ["flag: australia"]={ 0x1F1E6, 0x1F1FA }, + ["flag: austria"]={ 0x1F1E6, 0x1F1F9 }, + ["flag: azerbaijan"]={ 0x1F1E6, 0x1F1FF }, + ["flag: bahamas"]={ 0x1F1E7, 0x1F1F8 }, + ["flag: bahrain"]={ 0x1F1E7, 0x1F1ED }, + ["flag: bangladesh"]={ 0x1F1E7, 0x1F1E9 }, + ["flag: barbados"]={ 0x1F1E7, 0x1F1E7 }, + ["flag: belarus"]={ 0x1F1E7, 0x1F1FE }, + ["flag: belgium"]={ 0x1F1E7, 0x1F1EA }, + ["flag: belize"]={ 0x1F1E7, 0x1F1FF }, + ["flag: benin"]={ 0x1F1E7, 0x1F1EF }, + ["flag: bermuda"]={ 0x1F1E7, 0x1F1F2 }, + ["flag: bhutan"]={ 0x1F1E7, 0x1F1F9 }, + ["flag: bolivia"]={ 0x1F1E7, 0x1F1F4 }, + ["flag: bosnia & herzegovina"]={ 0x1F1E7, 0x1F1E6 }, + ["flag: botswana"]={ 0x1F1E7, 0x1F1FC }, + ["flag: bouvet island"]={ 0x1F1E7, 0x1F1FB }, + ["flag: brazil"]={ 0x1F1E7, 0x1F1F7 }, + ["flag: british indian ocean territory"]={ 0x1F1EE, 0x1F1F4 }, + ["flag: british virgin islands"]={ 0x1F1FB, 0x1F1EC }, + ["flag: brunei"]={ 0x1F1E7, 0x1F1F3 }, + ["flag: bulgaria"]={ 0x1F1E7, 0x1F1EC }, + ["flag: burkina faso"]={ 0x1F1E7, 0x1F1EB }, + ["flag: burundi"]={ 0x1F1E7, 0x1F1EE }, + ["flag: cambodia"]={ 0x1F1F0, 0x1F1ED }, + ["flag: cameroon"]={ 0x1F1E8, 0x1F1F2 }, + ["flag: canada"]={ 0x1F1E8, 0x1F1E6 }, + ["flag: canary islands"]={ 0x1F1EE, 0x1F1E8 }, + ["flag: cape verde"]={ 0x1F1E8, 0x1F1FB }, + ["flag: caribbean netherlands"]={ 0x1F1E7, 0x1F1F6 }, + ["flag: cayman islands"]={ 0x1F1F0, 0x1F1FE }, + ["flag: central african republic"]={ 0x1F1E8, 0x1F1EB }, + ["flag: ceuta & melilla"]={ 0x1F1EA, 0x1F1E6 }, + ["flag: chad"]={ 0x1F1F9, 0x1F1E9 }, + ["flag: chile"]={ 0x1F1E8, 0x1F1F1 }, + ["flag: china"]={ 0x1F1E8, 0x1F1F3 }, + ["flag: christmas island"]={ 0x1F1E8, 0x1F1FD }, + ["flag: clipperton island"]={ 0x1F1E8, 0x1F1F5 }, + ["flag: cocos (keeling) islands"]={ 0x1F1E8, 0x1F1E8 }, + ["flag: colombia"]={ 0x1F1E8, 0x1F1F4 }, + ["flag: comoros"]={ 0x1F1F0, 0x1F1F2 }, + ["flag: congo - brazzaville"]={ 0x1F1E8, 0x1F1EC }, + ["flag: congo - kinshasa"]={ 0x1F1E8, 0x1F1E9 }, + ["flag: cook islands"]={ 0x1F1E8, 0x1F1F0 }, + ["flag: costa rica"]={ 0x1F1E8, 0x1F1F7 }, + ["flag: croatia"]={ 0x1F1ED, 0x1F1F7 }, + ["flag: cuba"]={ 0x1F1E8, 0x1F1FA }, + ["flag: curaçao"]={ 0x1F1E8, 0x1F1FC }, + ["flag: cyprus"]={ 0x1F1E8, 0x1F1FE }, + ["flag: czechia"]={ 0x1F1E8, 0x1F1FF }, + ["flag: côte d’ivoire"]={ 0x1F1E8, 0x1F1EE }, + ["flag: denmark"]={ 0x1F1E9, 0x1F1F0 }, + ["flag: diego garcia"]={ 0x1F1E9, 0x1F1EC }, + ["flag: djibouti"]={ 0x1F1E9, 0x1F1EF }, + ["flag: dominica"]={ 0x1F1E9, 0x1F1F2 }, + ["flag: dominican republic"]={ 0x1F1E9, 0x1F1F4 }, + ["flag: ecuador"]={ 0x1F1EA, 0x1F1E8 }, + ["flag: egypt"]={ 0x1F1EA, 0x1F1EC }, + ["flag: el salvador"]={ 0x1F1F8, 0x1F1FB }, + ["flag: england"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0065, 0xE006E, 0xE0067, 0xE007F }, + ["flag: equatorial guinea"]={ 0x1F1EC, 0x1F1F6 }, + ["flag: eritrea"]={ 0x1F1EA, 0x1F1F7 }, + ["flag: estonia"]={ 0x1F1EA, 0x1F1EA }, + ["flag: eswatini"]={ 0x1F1F8, 0x1F1FF }, + ["flag: ethiopia"]={ 0x1F1EA, 0x1F1F9 }, + ["flag: european union"]={ 0x1F1EA, 0x1F1FA }, + ["flag: falkland islands"]={ 0x1F1EB, 0x1F1F0 }, + ["flag: faroe islands"]={ 0x1F1EB, 0x1F1F4 }, + ["flag: fiji"]={ 0x1F1EB, 0x1F1EF }, + ["flag: finland"]={ 0x1F1EB, 0x1F1EE }, + ["flag: france"]={ 0x1F1EB, 0x1F1F7 }, + ["flag: french guiana"]={ 0x1F1EC, 0x1F1EB }, + ["flag: french polynesia"]={ 0x1F1F5, 0x1F1EB }, + ["flag: french southern territories"]={ 0x1F1F9, 0x1F1EB }, + ["flag: gabon"]={ 0x1F1EC, 0x1F1E6 }, + ["flag: gambia"]={ 0x1F1EC, 0x1F1F2 }, + ["flag: georgia"]={ 0x1F1EC, 0x1F1EA }, + ["flag: germany"]={ 0x1F1E9, 0x1F1EA }, + ["flag: ghana"]={ 0x1F1EC, 0x1F1ED }, + ["flag: gibraltar"]={ 0x1F1EC, 0x1F1EE }, + ["flag: greece"]={ 0x1F1EC, 0x1F1F7 }, + ["flag: greenland"]={ 0x1F1EC, 0x1F1F1 }, + ["flag: grenada"]={ 0x1F1EC, 0x1F1E9 }, + ["flag: guadeloupe"]={ 0x1F1EC, 0x1F1F5 }, + ["flag: guam"]={ 0x1F1EC, 0x1F1FA }, + ["flag: guatemala"]={ 0x1F1EC, 0x1F1F9 }, + ["flag: guernsey"]={ 0x1F1EC, 0x1F1EC }, + ["flag: guinea"]={ 0x1F1EC, 0x1F1F3 }, + ["flag: guinea-bissau"]={ 0x1F1EC, 0x1F1FC }, + ["flag: guyana"]={ 0x1F1EC, 0x1F1FE }, + ["flag: haiti"]={ 0x1F1ED, 0x1F1F9 }, + ["flag: heard & mcdonald islands"]={ 0x1F1ED, 0x1F1F2 }, + ["flag: honduras"]={ 0x1F1ED, 0x1F1F3 }, + ["flag: hong kong sar china"]={ 0x1F1ED, 0x1F1F0 }, + ["flag: hungary"]={ 0x1F1ED, 0x1F1FA }, + ["flag: iceland"]={ 0x1F1EE, 0x1F1F8 }, + ["flag: india"]={ 0x1F1EE, 0x1F1F3 }, + ["flag: indonesia"]={ 0x1F1EE, 0x1F1E9 }, + ["flag: iran"]={ 0x1F1EE, 0x1F1F7 }, + ["flag: iraq"]={ 0x1F1EE, 0x1F1F6 }, + ["flag: ireland"]={ 0x1F1EE, 0x1F1EA }, + ["flag: isle of man"]={ 0x1F1EE, 0x1F1F2 }, + ["flag: israel"]={ 0x1F1EE, 0x1F1F1 }, + ["flag: italy"]={ 0x1F1EE, 0x1F1F9 }, + ["flag: jamaica"]={ 0x1F1EF, 0x1F1F2 }, + ["flag: japan"]={ 0x1F1EF, 0x1F1F5 }, + ["flag: jersey"]={ 0x1F1EF, 0x1F1EA }, + ["flag: jordan"]={ 0x1F1EF, 0x1F1F4 }, + ["flag: kazakhstan"]={ 0x1F1F0, 0x1F1FF }, + ["flag: kenya"]={ 0x1F1F0, 0x1F1EA }, + ["flag: kiribati"]={ 0x1F1F0, 0x1F1EE }, + ["flag: kosovo"]={ 0x1F1FD, 0x1F1F0 }, + ["flag: kuwait"]={ 0x1F1F0, 0x1F1FC }, + ["flag: kyrgyzstan"]={ 0x1F1F0, 0x1F1EC }, + ["flag: laos"]={ 0x1F1F1, 0x1F1E6 }, + ["flag: latvia"]={ 0x1F1F1, 0x1F1FB }, + ["flag: lebanon"]={ 0x1F1F1, 0x1F1E7 }, + ["flag: lesotho"]={ 0x1F1F1, 0x1F1F8 }, + ["flag: liberia"]={ 0x1F1F1, 0x1F1F7 }, + ["flag: libya"]={ 0x1F1F1, 0x1F1FE }, + ["flag: liechtenstein"]={ 0x1F1F1, 0x1F1EE }, + ["flag: lithuania"]={ 0x1F1F1, 0x1F1F9 }, + ["flag: luxembourg"]={ 0x1F1F1, 0x1F1FA }, + ["flag: macao sar china"]={ 0x1F1F2, 0x1F1F4 }, + ["flag: macedonia"]={ 0x1F1F2, 0x1F1F0 }, + ["flag: madagascar"]={ 0x1F1F2, 0x1F1EC }, + ["flag: malawi"]={ 0x1F1F2, 0x1F1FC }, + ["flag: malaysia"]={ 0x1F1F2, 0x1F1FE }, + ["flag: maldives"]={ 0x1F1F2, 0x1F1FB }, + ["flag: mali"]={ 0x1F1F2, 0x1F1F1 }, + ["flag: malta"]={ 0x1F1F2, 0x1F1F9 }, + ["flag: marshall islands"]={ 0x1F1F2, 0x1F1ED }, + ["flag: martinique"]={ 0x1F1F2, 0x1F1F6 }, + ["flag: mauritania"]={ 0x1F1F2, 0x1F1F7 }, + ["flag: mauritius"]={ 0x1F1F2, 0x1F1FA }, + ["flag: mayotte"]={ 0x1F1FE, 0x1F1F9 }, + ["flag: mexico"]={ 0x1F1F2, 0x1F1FD }, + ["flag: micronesia"]={ 0x1F1EB, 0x1F1F2 }, + ["flag: moldova"]={ 0x1F1F2, 0x1F1E9 }, + ["flag: monaco"]={ 0x1F1F2, 0x1F1E8 }, + ["flag: mongolia"]={ 0x1F1F2, 0x1F1F3 }, + ["flag: montenegro"]={ 0x1F1F2, 0x1F1EA }, + ["flag: montserrat"]={ 0x1F1F2, 0x1F1F8 }, + ["flag: morocco"]={ 0x1F1F2, 0x1F1E6 }, + ["flag: mozambique"]={ 0x1F1F2, 0x1F1FF }, + ["flag: myanmar (burma)"]={ 0x1F1F2, 0x1F1F2 }, + ["flag: namibia"]={ 0x1F1F3, 0x1F1E6 }, + ["flag: nauru"]={ 0x1F1F3, 0x1F1F7 }, + ["flag: nepal"]={ 0x1F1F3, 0x1F1F5 }, + ["flag: netherlands"]={ 0x1F1F3, 0x1F1F1 }, + ["flag: new caledonia"]={ 0x1F1F3, 0x1F1E8 }, + ["flag: new zealand"]={ 0x1F1F3, 0x1F1FF }, + ["flag: nicaragua"]={ 0x1F1F3, 0x1F1EE }, + ["flag: niger"]={ 0x1F1F3, 0x1F1EA }, + ["flag: nigeria"]={ 0x1F1F3, 0x1F1EC }, + ["flag: niue"]={ 0x1F1F3, 0x1F1FA }, + ["flag: norfolk island"]={ 0x1F1F3, 0x1F1EB }, + ["flag: north korea"]={ 0x1F1F0, 0x1F1F5 }, + ["flag: northern mariana islands"]={ 0x1F1F2, 0x1F1F5 }, + ["flag: norway"]={ 0x1F1F3, 0x1F1F4 }, + ["flag: oman"]={ 0x1F1F4, 0x1F1F2 }, + ["flag: pakistan"]={ 0x1F1F5, 0x1F1F0 }, + ["flag: palau"]={ 0x1F1F5, 0x1F1FC }, + ["flag: palestinian territories"]={ 0x1F1F5, 0x1F1F8 }, + ["flag: panama"]={ 0x1F1F5, 0x1F1E6 }, + ["flag: papua new guinea"]={ 0x1F1F5, 0x1F1EC }, + ["flag: paraguay"]={ 0x1F1F5, 0x1F1FE }, + ["flag: peru"]={ 0x1F1F5, 0x1F1EA }, + ["flag: philippines"]={ 0x1F1F5, 0x1F1ED }, + ["flag: pitcairn islands"]={ 0x1F1F5, 0x1F1F3 }, + ["flag: poland"]={ 0x1F1F5, 0x1F1F1 }, + ["flag: portugal"]={ 0x1F1F5, 0x1F1F9 }, + ["flag: puerto rico"]={ 0x1F1F5, 0x1F1F7 }, + ["flag: qatar"]={ 0x1F1F6, 0x1F1E6 }, + ["flag: romania"]={ 0x1F1F7, 0x1F1F4 }, + ["flag: russia"]={ 0x1F1F7, 0x1F1FA }, + ["flag: rwanda"]={ 0x1F1F7, 0x1F1FC }, + ["flag: réunion"]={ 0x1F1F7, 0x1F1EA }, + ["flag: samoa"]={ 0x1F1FC, 0x1F1F8 }, + ["flag: san marino"]={ 0x1F1F8, 0x1F1F2 }, + ["flag: saudi arabia"]={ 0x1F1F8, 0x1F1E6 }, + ["flag: scotland"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0073, 0xE0063, 0xE0074, 0xE007F }, + ["flag: senegal"]={ 0x1F1F8, 0x1F1F3 }, + ["flag: serbia"]={ 0x1F1F7, 0x1F1F8 }, + ["flag: seychelles"]={ 0x1F1F8, 0x1F1E8 }, + ["flag: sierra leone"]={ 0x1F1F8, 0x1F1F1 }, + ["flag: singapore"]={ 0x1F1F8, 0x1F1EC }, + ["flag: sint maarten"]={ 0x1F1F8, 0x1F1FD }, + ["flag: slovakia"]={ 0x1F1F8, 0x1F1F0 }, + ["flag: slovenia"]={ 0x1F1F8, 0x1F1EE }, + ["flag: solomon islands"]={ 0x1F1F8, 0x1F1E7 }, + ["flag: somalia"]={ 0x1F1F8, 0x1F1F4 }, + ["flag: south africa"]={ 0x1F1FF, 0x1F1E6 }, + ["flag: south georgia & south sandwich islands"]={ 0x1F1EC, 0x1F1F8 }, + ["flag: south korea"]={ 0x1F1F0, 0x1F1F7 }, + ["flag: south sudan"]={ 0x1F1F8, 0x1F1F8 }, + ["flag: spain"]={ 0x1F1EA, 0x1F1F8 }, + ["flag: sri lanka"]={ 0x1F1F1, 0x1F1F0 }, + ["flag: st. barthélemy"]={ 0x1F1E7, 0x1F1F1 }, + ["flag: st. helena"]={ 0x1F1F8, 0x1F1ED }, + ["flag: st. kitts & nevis"]={ 0x1F1F0, 0x1F1F3 }, + ["flag: st. lucia"]={ 0x1F1F1, 0x1F1E8 }, + ["flag: st. martin"]={ 0x1F1F2, 0x1F1EB }, + ["flag: st. pierre & miquelon"]={ 0x1F1F5, 0x1F1F2 }, + ["flag: st. vincent & grenadines"]={ 0x1F1FB, 0x1F1E8 }, + ["flag: sudan"]={ 0x1F1F8, 0x1F1E9 }, + ["flag: suriname"]={ 0x1F1F8, 0x1F1F7 }, + ["flag: svalbard & jan mayen"]={ 0x1F1F8, 0x1F1EF }, + ["flag: sweden"]={ 0x1F1F8, 0x1F1EA }, + ["flag: switzerland"]={ 0x1F1E8, 0x1F1ED }, + ["flag: syria"]={ 0x1F1F8, 0x1F1FE }, + ["flag: são tomé & príncipe"]={ 0x1F1F8, 0x1F1F9 }, + ["flag: taiwan"]={ 0x1F1F9, 0x1F1FC }, + ["flag: tajikistan"]={ 0x1F1F9, 0x1F1EF }, + ["flag: tanzania"]={ 0x1F1F9, 0x1F1FF }, + ["flag: thailand"]={ 0x1F1F9, 0x1F1ED }, + ["flag: timor-leste"]={ 0x1F1F9, 0x1F1F1 }, + ["flag: togo"]={ 0x1F1F9, 0x1F1EC }, + ["flag: tokelau"]={ 0x1F1F9, 0x1F1F0 }, + ["flag: tonga"]={ 0x1F1F9, 0x1F1F4 }, + ["flag: trinidad & tobago"]={ 0x1F1F9, 0x1F1F9 }, + ["flag: tristan da cunha"]={ 0x1F1F9, 0x1F1E6 }, + ["flag: tunisia"]={ 0x1F1F9, 0x1F1F3 }, + ["flag: turkey"]={ 0x1F1F9, 0x1F1F7 }, + ["flag: turkmenistan"]={ 0x1F1F9, 0x1F1F2 }, + ["flag: turks & caicos islands"]={ 0x1F1F9, 0x1F1E8 }, + ["flag: tuvalu"]={ 0x1F1F9, 0x1F1FB }, + ["flag: u.s. outlying islands"]={ 0x1F1FA, 0x1F1F2 }, + ["flag: u.s. virgin islands"]={ 0x1F1FB, 0x1F1EE }, + ["flag: uganda"]={ 0x1F1FA, 0x1F1EC }, + ["flag: ukraine"]={ 0x1F1FA, 0x1F1E6 }, + ["flag: united arab emirates"]={ 0x1F1E6, 0x1F1EA }, + ["flag: united kingdom"]={ 0x1F1EC, 0x1F1E7 }, + ["flag: united nations"]={ 0x1F1FA, 0x1F1F3 }, + ["flag: united states"]={ 0x1F1FA, 0x1F1F8 }, + ["flag: uruguay"]={ 0x1F1FA, 0x1F1FE }, + ["flag: uzbekistan"]={ 0x1F1FA, 0x1F1FF }, + ["flag: vanuatu"]={ 0x1F1FB, 0x1F1FA }, + ["flag: vatican city"]={ 0x1F1FB, 0x1F1E6 }, + ["flag: venezuela"]={ 0x1F1FB, 0x1F1EA }, + ["flag: vietnam"]={ 0x1F1FB, 0x1F1F3 }, + ["flag: wales"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0077, 0xE006C, 0xE0073, 0xE007F }, + ["flag: wallis & futuna"]={ 0x1F1FC, 0x1F1EB }, + ["flag: western sahara"]={ 0x1F1EA, 0x1F1ED }, + ["flag: yemen"]={ 0x1F1FE, 0x1F1EA }, + ["flag: zambia"]={ 0x1F1FF, 0x1F1F2 }, + ["flag: zimbabwe"]={ 0x1F1FF, 0x1F1FC }, + ["flag: Åland islands"]={ 0x1F1E6, 0x1F1FD }, + ["flamingo"]={ 0x1F9A9 }, ["flashlight"]={ 0x1F526 }, - ["fleur-de-lis"]={ 0x269C }, + ["flat shoe"]={ 0x1F97F }, + ["fleur-de-lis"]={ 0x269C, 0xFE0F }, ["flexed biceps"]={ 0x1F4AA }, ["flexed biceps: dark skin tone"]={ 0x1F4AA, 0x1F3FF }, ["flexed biceps: light skin tone"]={ 0x1F4AA, 0x1F3FB }, @@ -613,8 +821,9 @@ return { ["floppy disk"]={ 0x1F4BE }, ["flower playing cards"]={ 0x1F3B4 }, ["flushed face"]={ 0x1F633 }, + ["flying disc"]={ 0x1F94F }, ["flying saucer"]={ 0x1F6F8 }, - ["fog"]={ 0x1F32B }, + ["fog"]={ 0x1F32B, 0xFE0F }, ["foggy"]={ 0x1F301 }, ["folded hands"]={ 0x1F64F }, ["folded hands: dark skin tone"]={ 0x1F64F, 0x1F3FF }, @@ -622,44 +831,41 @@ return { ["folded hands: medium skin tone"]={ 0x1F64F, 0x1F3FD }, ["folded hands: medium-dark skin tone"]={ 0x1F64F, 0x1F3FE }, ["folded hands: medium-light skin tone"]={ 0x1F64F, 0x1F3FC }, + ["foot"]={ 0x1F9B6 }, + ["foot: dark skin tone"]={ 0x1F9B6, 0x1F3FF }, + ["foot: light skin tone"]={ 0x1F9B6, 0x1F3FB }, + ["foot: medium skin tone"]={ 0x1F9B6, 0x1F3FD }, + ["foot: medium-dark skin tone"]={ 0x1F9B6, 0x1F3FE }, + ["foot: medium-light skin tone"]={ 0x1F9B6, 0x1F3FC }, ["footprints"]={ 0x1F463 }, ["fork and knife"]={ 0x1F374 }, - ["fork and knife with plate"]={ 0x1F37D }, + ["fork and knife with plate"]={ 0x1F37D, 0xFE0F }, ["fortune cookie"]={ 0x1F960 }, ["fountain"]={ 0x26F2 }, - ["fountain pen"]={ 0x1F58B }, + ["fountain pen"]={ 0x1F58B, 0xFE0F }, ["four leaf clover"]={ 0x1F340 }, ["four o’clock"]={ 0x1F553 }, ["four-thirty"]={ 0x1F55F }, - ["fox face"]={ 0x1F98A }, - ["framed picture"]={ 0x1F5BC }, - ["france"]={ 0x1F1EB, 0x1F1F7 }, + ["fox"]={ 0x1F98A }, + ["framed picture"]={ 0x1F5BC, 0xFE0F }, ["free button"]={ 0x1F193 }, ["french fries"]={ 0x1F35F }, - ["french guiana"]={ 0x1F1EC, 0x1F1EB }, - ["french polynesia"]={ 0x1F1F5, 0x1F1EB }, - ["french southern territories"]={ 0x1F1F9, 0x1F1EB }, ["fried shrimp"]={ 0x1F364 }, - ["frog face"]={ 0x1F438 }, + ["frog"]={ 0x1F438 }, ["front-facing baby chick"]={ 0x1F425 }, - ["frowning face"]={ 0x2639 }, + ["frowning face"]={ 0x2639, 0xFE0F }, ["frowning face with open mouth"]={ 0x1F626 }, ["fuel pump"]={ 0x26FD }, ["full moon"]={ 0x1F315 }, - ["full moon with face"]={ 0x1F31D }, - ["funeral urn"]={ 0x26B1 }, - ["gabon"]={ 0x1F1EC, 0x1F1E6 }, - ["gambia"]={ 0x1F1EC, 0x1F1F2 }, + ["full moon face"]={ 0x1F31D }, + ["funeral urn"]={ 0x26B1, 0xFE0F }, ["game die"]={ 0x1F3B2 }, - ["gear"]={ 0x2699 }, + ["garlic"]={ 0x1F9C4 }, + ["gear"]={ 0x2699, 0xFE0F }, ["gem stone"]={ 0x1F48E }, ["gemini"]={ 0x264A }, ["genie"]={ 0x1F9DE }, - ["georgia"]={ 0x1F1EC, 0x1F1EA }, - ["germany"]={ 0x1F1E9, 0x1F1EA }, - ["ghana"]={ 0x1F1EC, 0x1F1ED }, ["ghost"]={ 0x1F47B }, - ["gibraltar"]={ 0x1F1EC, 0x1F1EE }, ["giraffe"]={ 0x1F992 }, ["girl"]={ 0x1F467 }, ["girl: dark skin tone"]={ 0x1F467, 0x1F3FF }, @@ -678,59 +884,55 @@ return { ["goal net"]={ 0x1F945 }, ["goat"]={ 0x1F410 }, ["goblin"]={ 0x1F47A }, + ["goggles"]={ 0x1F97D }, ["gorilla"]={ 0x1F98D }, ["graduation cap"]={ 0x1F393 }, ["grapes"]={ 0x1F347 }, - ["greece"]={ 0x1F1EC, 0x1F1F7 }, ["green apple"]={ 0x1F34F }, ["green book"]={ 0x1F4D7 }, + ["green circle"]={ 0x1F7E2 }, ["green heart"]={ 0x1F49A }, ["green salad"]={ 0x1F957 }, - ["greenland"]={ 0x1F1EC, 0x1F1F1 }, - ["grenada"]={ 0x1F1EC, 0x1F1E9 }, + ["green square"]={ 0x1F7E9 }, ["grimacing face"]={ 0x1F62C }, - ["grinning cat face with smiling eyes"]={ 0x1F638 }, + ["grinning cat"]={ 0x1F63A }, + ["grinning cat with smiling eyes"]={ 0x1F638 }, ["grinning face"]={ 0x1F600 }, - ["grinning face with smiling eyes"]={ 0x1F601 }, + ["grinning face with big eyes"]={ 0x1F603 }, + ["grinning face with smiling eyes"]={ 0x1F604 }, + ["grinning face with sweat"]={ 0x1F605 }, + ["grinning squinting face"]={ 0x1F606 }, ["growing heart"]={ 0x1F497 }, - ["guadeloupe"]={ 0x1F1EC, 0x1F1F5 }, - ["guam"]={ 0x1F1EC, 0x1F1FA }, ["guard"]={ 0x1F482 }, ["guard: dark skin tone"]={ 0x1F482, 0x1F3FF }, ["guard: light skin tone"]={ 0x1F482, 0x1F3FB }, ["guard: medium skin tone"]={ 0x1F482, 0x1F3FD }, ["guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE }, ["guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC }, - ["guatemala"]={ 0x1F1EC, 0x1F1F9 }, - ["guernsey"]={ 0x1F1EC, 0x1F1EC }, - ["guinea"]={ 0x1F1EC, 0x1F1F3 }, - ["guinea-bissau"]={ 0x1F1EC, 0x1F1FC }, + ["guide dog"]={ 0x1F9AE }, ["guitar"]={ 0x1F3B8 }, - ["guyana"]={ 0x1F1EC, 0x1F1FE }, - ["haiti"]={ 0x1F1ED, 0x1F1F9 }, ["hamburger"]={ 0x1F354 }, ["hammer"]={ 0x1F528 }, - ["hammer and pick"]={ 0x2692 }, - ["hammer and wrench"]={ 0x1F6E0 }, - ["hamster face"]={ 0x1F439 }, + ["hammer and pick"]={ 0x2692, 0xFE0F }, + ["hammer and wrench"]={ 0x1F6E0, 0xFE0F }, + ["hamster"]={ 0x1F439 }, + ["hand with fingers splayed"]={ 0x1F590, 0xFE0F }, + ["hand with fingers splayed: dark skin tone"]={ 0x1F590, 0x1F3FF }, + ["hand with fingers splayed: light skin tone"]={ 0x1F590, 0x1F3FB }, + ["hand with fingers splayed: medium skin tone"]={ 0x1F590, 0x1F3FD }, + ["hand with fingers splayed: medium-dark skin tone"]={ 0x1F590, 0x1F3FE }, + ["hand with fingers splayed: medium-light skin tone"]={ 0x1F590, 0x1F3FC }, ["handbag"]={ 0x1F45C }, ["handshake"]={ 0x1F91D }, ["hatching chick"]={ 0x1F423 }, ["headphone"]={ 0x1F3A7 }, ["hear-no-evil monkey"]={ 0x1F649 }, - ["heard & mcdonald islands"]={ 0x1F1ED, 0x1F1F2 }, ["heart decoration"]={ 0x1F49F }, - ["heart suit"]={ 0x2665 }, + ["heart exclamation"]={ 0x2763, 0xFE0F }, + ["heart suit"]={ 0x2665, 0xFE0F }, ["heart with arrow"]={ 0x1F498 }, ["heart with ribbon"]={ 0x1F49D }, - ["heavy check mark"]={ 0x2714 }, - ["heavy division sign"]={ 0x2797 }, ["heavy dollar sign"]={ 0x1F4B2 }, - ["heavy heart exclamation"]={ 0x2763 }, - ["heavy large circle"]={ 0x2B55 }, - ["heavy minus sign"]={ 0x2796 }, - ["heavy multiplication x"]={ 0x2716 }, - ["heavy plus sign"]={ 0x2795 }, ["hedgehog"]={ 0x1F994 }, ["helicopter"]={ 0x1F681 }, ["herb"]={ 0x1F33F }, @@ -738,12 +940,13 @@ return { ["high voltage"]={ 0x26A1 }, ["high-heeled shoe"]={ 0x1F460 }, ["high-speed train"]={ 0x1F684 }, - ["high-speed train with bullet nose"]={ 0x1F685 }, - ["hole"]={ 0x1F573 }, - ["honduras"]={ 0x1F1ED, 0x1F1F3 }, + ["hiking boot"]={ 0x1F97E }, + ["hindu temple"]={ 0x1F6D5 }, + ["hippopotamus"]={ 0x1F99B }, + ["hole"]={ 0x1F573, 0xFE0F }, + ["hollow red circle"]={ 0x2B55 }, ["honey pot"]={ 0x1F36F }, ["honeybee"]={ 0x1F41D }, - ["hong kong sar china"]={ 0x1F1ED, 0x1F1F0 }, ["horizontal traffic light"]={ 0x1F6A5 }, ["horse"]={ 0x1F40E }, ["horse face"]={ 0x1F434 }, @@ -756,47 +959,39 @@ return { ["hospital"]={ 0x1F3E5 }, ["hot beverage"]={ 0x2615 }, ["hot dog"]={ 0x1F32D }, - ["hot pepper"]={ 0x1F336 }, - ["hot springs"]={ 0x2668 }, + ["hot face"]={ 0x1F975 }, + ["hot pepper"]={ 0x1F336, 0xFE0F }, + ["hot springs"]={ 0x2668, 0xFE0F }, ["hotel"]={ 0x1F3E8 }, - ["hourglass"]={ 0x231B }, - ["hourglass with flowing sand"]={ 0x23F3 }, + ["hourglass done"]={ 0x231B }, + ["hourglass not done"]={ 0x23F3 }, ["house"]={ 0x1F3E0 }, ["house with garden"]={ 0x1F3E1 }, + ["houses"]={ 0x1F3D8, 0xFE0F }, ["hugging face"]={ 0x1F917 }, ["hundred points"]={ 0x1F4AF }, - ["hungary"]={ 0x1F1ED, 0x1F1FA }, ["hushed face"]={ 0x1F62F }, ["ice cream"]={ 0x1F368 }, + ["ice cube"]={ 0x1F9CA }, ["ice hockey"]={ 0x1F3D2 }, - ["ice skate"]={ 0x26F8 }, - ["iceland"]={ 0x1F1EE, 0x1F1F8 }, + ["ice skate"]={ 0x26F8, 0xFE0F }, ["id button"]={ 0x1F194 }, ["inbox tray"]={ 0x1F4E5 }, ["incoming envelope"]={ 0x1F4E8 }, - ["index pointing up"]={ 0x261D }, + ["index pointing up"]={ 0x261D, 0xFE0F }, ["index pointing up: dark skin tone"]={ 0x261D, 0x1F3FF }, ["index pointing up: light skin tone"]={ 0x261D, 0x1F3FB }, ["index pointing up: medium skin tone"]={ 0x261D, 0x1F3FD }, ["index pointing up: medium-dark skin tone"]={ 0x261D, 0x1F3FE }, ["index pointing up: medium-light skin tone"]={ 0x261D, 0x1F3FC }, - ["india"]={ 0x1F1EE, 0x1F1F3 }, - ["indonesia"]={ 0x1F1EE, 0x1F1E9 }, - ["information"]={ 0x2139 }, + ["infinity"]={ 0x267E, 0xFE0F }, + ["information"]={ 0x2139, 0xFE0F }, ["input latin letters"]={ 0x1F524 }, ["input latin lowercase"]={ 0x1F521 }, ["input latin uppercase"]={ 0x1F520 }, ["input numbers"]={ 0x1F522 }, ["input symbols"]={ 0x1F523 }, - ["iran"]={ 0x1F1EE, 0x1F1F7 }, - ["iraq"]={ 0x1F1EE, 0x1F1F6 }, - ["ireland"]={ 0x1F1EE, 0x1F1EA }, - ["isle of man"]={ 0x1F1EE, 0x1F1F2 }, - ["israel"]={ 0x1F1EE, 0x1F1F1 }, - ["italy"]={ 0x1F1EE, 0x1F1F9 }, ["jack-o-lantern"]={ 0x1F383 }, - ["jamaica"]={ 0x1F1EF, 0x1F1F2 }, - ["japan"]={ 0x1F1EF, 0x1F1F5 }, ["japanese castle"]={ 0x1F3EF }, ["japanese dolls"]={ 0x1F38E }, ["japanese post office"]={ 0x1F3E3 }, @@ -804,110 +999,107 @@ return { ["japanese “acceptable” button"]={ 0x1F251 }, ["japanese “application” button"]={ 0x1F238 }, ["japanese “bargain” button"]={ 0x1F250 }, - ["japanese “congratulations” button"]={ 0x3297 }, + ["japanese “congratulations” button"]={ 0x3297, 0xFE0F }, ["japanese “discount” button"]={ 0x1F239 }, ["japanese “free of charge” button"]={ 0x1F21A }, ["japanese “here” button"]={ 0x1F201 }, - ["japanese “monthly amount” button"]={ 0x1F237 }, + ["japanese “monthly amount” button"]={ 0x1F237, 0xFE0F }, ["japanese “no vacancy” button"]={ 0x1F235 }, ["japanese “not free of charge” button"]={ 0x1F236 }, ["japanese “open for business” button"]={ 0x1F23A }, ["japanese “passing grade” button"]={ 0x1F234 }, ["japanese “prohibited” button"]={ 0x1F232 }, ["japanese “reserved” button"]={ 0x1F22F }, - ["japanese “secret” button"]={ 0x3299 }, - ["japanese “service charge” button"]={ 0x1F202 }, + ["japanese “secret” button"]={ 0x3299, 0xFE0F }, + ["japanese “service charge” button"]={ 0x1F202, 0xFE0F }, ["japanese “vacancy” button"]={ 0x1F233 }, ["jeans"]={ 0x1F456 }, - ["jersey"]={ 0x1F1EF, 0x1F1EA }, ["joker"]={ 0x1F0CF }, - ["jordan"]={ 0x1F1EF, 0x1F1F4 }, - ["joystick"]={ 0x1F579 }, + ["joystick"]={ 0x1F579, 0xFE0F }, ["kaaba"]={ 0x1F54B }, - ["kazakhstan"]={ 0x1F1F0, 0x1F1FF }, - ["kenya"]={ 0x1F1F0, 0x1F1EA }, + ["kangaroo"]={ 0x1F998 }, ["key"]={ 0x1F511 }, - ["keyboard"]={ 0x2328 }, - ["keycap 10"]={ 0x1F51F }, - ["keycap: 0"]={ 0x30, 0x20E3 }, - ["keycap: 1"]={ 0x31, 0x20E3 }, - ["keycap: 2"]={ 0x32, 0x20E3 }, - ["keycap: 3"]={ 0x33, 0x20E3 }, - ["keycap: 4"]={ 0x34, 0x20E3 }, - ["keycap: 5"]={ 0x35, 0x20E3 }, - ["keycap: 6"]={ 0x36, 0x20E3 }, - ["keycap: 7"]={ 0x37, 0x20E3 }, - ["keycap: 8"]={ 0x38, 0x20E3 }, - ["keycap: 9"]={ 0x39, 0x20E3 }, - ["keycap: asterisk"]={ 0x2A, 0x20E3 }, - ["keycap: hash"]={ 0x23, 0x20E3 }, + ["keyboard"]={ 0x2328, 0xFE0F }, + ["keycap: 0"]={ 0x30, 0xFE0F, 0x20E3 }, + ["keycap: 1"]={ 0x31, 0xFE0F, 0x20E3 }, + ["keycap: 10"]={ 0x1F51F }, + ["keycap: 2"]={ 0x32, 0xFE0F, 0x20E3 }, + ["keycap: 3"]={ 0x33, 0xFE0F, 0x20E3 }, + ["keycap: 4"]={ 0x34, 0xFE0F, 0x20E3 }, + ["keycap: 5"]={ 0x35, 0xFE0F, 0x20E3 }, + ["keycap: 6"]={ 0x36, 0xFE0F, 0x20E3 }, + ["keycap: 7"]={ 0x37, 0xFE0F, 0x20E3 }, + ["keycap: 8"]={ 0x38, 0xFE0F, 0x20E3 }, + ["keycap: 9"]={ 0x39, 0xFE0F, 0x20E3 }, + ["keycap: asterisk"]={ 0x2A, 0xFE0F, 0x20E3 }, + ["keycap: hash"]={ 0x23, 0xFE0F, 0x20E3 }, ["kick scooter"]={ 0x1F6F4 }, ["kimono"]={ 0x1F458 }, - ["kiribati"]={ 0x1F1F0, 0x1F1EE }, ["kiss"]={ 0x1F48F }, ["kiss mark"]={ 0x1F48B }, - ["kiss: man, man"]={ 0x1F468, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468 }, - ["kiss: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468 }, - ["kiss: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F469 }, - ["kissing cat face with closed eyes"]={ 0x1F63D }, + ["kiss: man, man"]={ 0x1F468, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F468 }, + ["kiss: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F468 }, + ["kiss: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F469 }, + ["kissing cat"]={ 0x1F63D }, ["kissing face"]={ 0x1F617 }, ["kissing face with closed eyes"]={ 0x1F61A }, ["kissing face with smiling eyes"]={ 0x1F619 }, ["kitchen knife"]={ 0x1F52A }, + ["kite"]={ 0x1FA81 }, ["kiwi fruit"]={ 0x1F95D }, ["koala"]={ 0x1F428 }, - ["kosovo"]={ 0x1F1FD, 0x1F1F0 }, - ["kuwait"]={ 0x1F1F0, 0x1F1FC }, - ["kyrgyzstan"]={ 0x1F1F0, 0x1F1EC }, - ["label"]={ 0x1F3F7 }, + ["lab coat"]={ 0x1F97C }, + ["label"]={ 0x1F3F7, 0xFE0F }, + ["lacrosse"]={ 0x1F94D }, ["lady beetle"]={ 0x1F41E }, - ["laos"]={ 0x1F1F1, 0x1F1E6 }, ["laptop computer"]={ 0x1F4BB }, ["large blue diamond"]={ 0x1F537 }, ["large orange diamond"]={ 0x1F536 }, ["last quarter moon"]={ 0x1F317 }, - ["last quarter moon with face"]={ 0x1F31C }, - ["last track button"]={ 0x23EE }, - ["latin cross"]={ 0x271D }, - ["latvia"]={ 0x1F1F1, 0x1F1FB }, + ["last quarter moon face"]={ 0x1F31C }, + ["last track button"]={ 0x23EE, 0xFE0F }, + ["latin cross"]={ 0x271D, 0xFE0F }, ["leaf fluttering in wind"]={ 0x1F343 }, - ["lebanon"]={ 0x1F1F1, 0x1F1E7 }, + ["leafy green"]={ 0x1F96C }, ["ledger"]={ 0x1F4D2 }, - ["left arrow"]={ 0x2B05 }, - ["left arrow curving right"]={ 0x21AA }, + ["left arrow"]={ 0x2B05, 0xFE0F }, + ["left arrow curving right"]={ 0x21AA, 0xFE0F }, ["left luggage"]={ 0x1F6C5 }, - ["left speech bubble"]={ 0x1F5E8 }, + ["left speech bubble"]={ 0x1F5E8, 0xFE0F }, ["left-facing fist"]={ 0x1F91B }, ["left-facing fist: dark skin tone"]={ 0x1F91B, 0x1F3FF }, ["left-facing fist: light skin tone"]={ 0x1F91B, 0x1F3FB }, ["left-facing fist: medium skin tone"]={ 0x1F91B, 0x1F3FD }, ["left-facing fist: medium-dark skin tone"]={ 0x1F91B, 0x1F3FE }, ["left-facing fist: medium-light skin tone"]={ 0x1F91B, 0x1F3FC }, - ["left-pointing magnifying glass"]={ 0x1F50D }, - ["left-right arrow"]={ 0x2194 }, + ["left-right arrow"]={ 0x2194, 0xFE0F }, + ["leg"]={ 0x1F9B5 }, + ["leg: dark skin tone"]={ 0x1F9B5, 0x1F3FF }, + ["leg: light skin tone"]={ 0x1F9B5, 0x1F3FB }, + ["leg: medium skin tone"]={ 0x1F9B5, 0x1F3FD }, + ["leg: medium-dark skin tone"]={ 0x1F9B5, 0x1F3FE }, + ["leg: medium-light skin tone"]={ 0x1F9B5, 0x1F3FC }, ["lemon"]={ 0x1F34B }, ["leo"]={ 0x264C }, ["leopard"]={ 0x1F406 }, - ["lesotho"]={ 0x1F1F1, 0x1F1F8 }, - ["level slider"]={ 0x1F39A }, - ["liberia"]={ 0x1F1F1, 0x1F1F7 }, + ["level slider"]={ 0x1F39A, 0xFE0F }, ["libra"]={ 0x264E }, - ["libya"]={ 0x1F1F1, 0x1F1FE }, - ["liechtenstein"]={ 0x1F1F1, 0x1F1EE }, ["light bulb"]={ 0x1F4A1 }, ["light rail"]={ 0x1F688 }, ["link"]={ 0x1F517 }, - ["linked paperclips"]={ 0x1F587 }, - ["lion face"]={ 0x1F981 }, + ["linked paperclips"]={ 0x1F587, 0xFE0F }, + ["lion"]={ 0x1F981 }, ["lipstick"]={ 0x1F484 }, - ["lithuania"]={ 0x1F1F1, 0x1F1F9 }, ["litter in bin sign"]={ 0x1F6AE }, ["lizard"]={ 0x1F98E }, + ["llama"]={ 0x1F999 }, + ["lobster"]={ 0x1F99E }, ["locked"]={ 0x1F512 }, ["locked with key"]={ 0x1F510 }, ["locked with pen"]={ 0x1F50F }, ["locomotive"]={ 0x1F682 }, ["lollipop"]={ 0x1F36D }, + ["lotion bottle"]={ 0x1F9F4 }, ["loudly crying face"]={ 0x1F62D }, ["loudspeaker"]={ 0x1F4E2 }, ["love hotel"]={ 0x1F3E9 }, @@ -918,26 +1110,20 @@ return { ["love-you gesture: medium skin tone"]={ 0x1F91F, 0x1F3FD }, ["love-you gesture: medium-dark skin tone"]={ 0x1F91F, 0x1F3FE }, ["love-you gesture: medium-light skin tone"]={ 0x1F91F, 0x1F3FC }, - ["luxembourg"]={ 0x1F1F1, 0x1F1FA }, + ["luggage"]={ 0x1F9F3 }, ["lying face"]={ 0x1F925 }, - ["macau sar china"]={ 0x1F1F2, 0x1F1F4 }, - ["macedonia"]={ 0x1F1F2, 0x1F1F0 }, - ["madagascar"]={ 0x1F1F2, 0x1F1EC }, ["mage"]={ 0x1F9D9 }, ["mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF }, ["mage: light skin tone"]={ 0x1F9D9, 0x1F3FB }, ["mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD }, ["mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE }, ["mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC }, + ["magnet"]={ 0x1F9F2 }, + ["magnifying glass tilted left"]={ 0x1F50D }, + ["magnifying glass tilted right"]={ 0x1F50E }, ["mahjong red dragon"]={ 0x1F004 }, - ["malawi"]={ 0x1F1F2, 0x1F1FC }, - ["malaysia"]={ 0x1F1F2, 0x1F1FE }, - ["maldives"]={ 0x1F1F2, 0x1F1FB }, - ["male sign"]={ 0x2642 }, - ["mali"]={ 0x1F1F2, 0x1F1F1 }, - ["malta"]={ 0x1F1F2, 0x1F1F9 }, + ["male sign"]={ 0x2642, 0xFE0F }, ["man"]={ 0x1F468 }, - ["man and woman holding hands"]={ 0x1F46B }, ["man artist"]={ 0x1F468, 0x200D, 0x1F3A8 }, ["man artist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A8 }, ["man artist: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3A8 }, @@ -950,42 +1136,42 @@ return { ["man astronaut: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F680 }, ["man astronaut: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F680 }, ["man astronaut: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F680 }, - ["man biking"]={ 0x1F6B4, 0x200D, 0x2642 }, - ["man biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2642 }, - ["man biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2642 }, - ["man biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2642 }, - ["man biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2642 }, - ["man biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2642 }, - ["man bouncing ball"]={ 0x26F9, 0x200D, 0x2642 }, - ["man bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2642 }, - ["man bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2642 }, - ["man bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2642 }, - ["man bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2642 }, - ["man bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2642 }, - ["man bowing"]={ 0x1F647, 0x200D, 0x2642 }, - ["man bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2642 }, - ["man bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2642 }, - ["man bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2642 }, - ["man bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2642 }, - ["man bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2642 }, - ["man cartwheeling"]={ 0x1F938, 0x200D, 0x2642 }, - ["man cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2642 }, - ["man cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2642 }, - ["man cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2642 }, - ["man cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2642 }, - ["man cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2642 }, - ["man climbing"]={ 0x1F9D7, 0x200D, 0x2642 }, - ["man climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2642 }, - ["man climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2642 }, - ["man climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2642 }, - ["man climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2642 }, - ["man climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2642 }, - ["man construction worker"]={ 0x1F477, 0x200D, 0x2642 }, - ["man construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2642 }, - ["man construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2642 }, - ["man construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2642 }, - ["man construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2642 }, - ["man construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2642 }, + ["man biking"]={ 0x1F6B4, 0x200D, 0x2642, 0xFE0F }, + ["man biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball"]={ 0x26F9, 0xFE0F, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man bowing"]={ 0x1F647, 0x200D, 0x2642, 0xFE0F }, + ["man bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling"]={ 0x1F938, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man climbing"]={ 0x1F9D7, 0x200D, 0x2642, 0xFE0F }, + ["man climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker"]={ 0x1F477, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man cook"]={ 0x1F468, 0x200D, 0x1F373 }, ["man cook: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F373 }, ["man cook: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F373 }, @@ -998,36 +1184,36 @@ return { ["man dancing: medium skin tone"]={ 0x1F57A, 0x1F3FD }, ["man dancing: medium-dark skin tone"]={ 0x1F57A, 0x1F3FE }, ["man dancing: medium-light skin tone"]={ 0x1F57A, 0x1F3FC }, - ["man detective"]={ 0x1F575, 0x200D, 0x2642 }, - ["man detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2642 }, - ["man detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2642 }, - ["man detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2642 }, - ["man detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2642 }, - ["man detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2642 }, - ["man elf"]={ 0x1F9DD, 0x200D, 0x2642 }, - ["man elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2642 }, - ["man elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2642 }, - ["man elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2642 }, - ["man elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2642 }, - ["man elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2642 }, - ["man facepalming"]={ 0x1F926, 0x200D, 0x2642 }, - ["man facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2642 }, - ["man facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2642 }, - ["man facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2642 }, - ["man facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2642 }, - ["man facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2642 }, + ["man detective"]={ 0x1F575, 0xFE0F, 0x200D, 0x2642, 0xFE0F }, + ["man detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man elf"]={ 0x1F9DD, 0x200D, 0x2642, 0xFE0F }, + ["man elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming"]={ 0x1F926, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man factory worker"]={ 0x1F468, 0x200D, 0x1F3ED }, ["man factory worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3ED }, ["man factory worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3ED }, ["man factory worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F3ED }, ["man factory worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F3ED }, ["man factory worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F3ED }, - ["man fairy"]={ 0x1F9DA, 0x200D, 0x2642 }, - ["man fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2642 }, - ["man fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2642 }, - ["man fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2642 }, - ["man fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2642 }, - ["man fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2642 }, + ["man fairy"]={ 0x1F9DA, 0x200D, 0x2642, 0xFE0F }, + ["man fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man farmer"]={ 0x1F468, 0x200D, 0x1F33E }, ["man farmer: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F33E }, ["man farmer: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F33E }, @@ -1040,205 +1226,241 @@ return { ["man firefighter: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F692 }, ["man firefighter: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F692 }, ["man firefighter: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F692 }, - ["man frowning"]={ 0x1F64D, 0x200D, 0x2642 }, - ["man frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2642 }, - ["man frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2642 }, - ["man frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2642 }, - ["man frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2642 }, - ["man frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2642 }, - ["man genie"]={ 0x1F9DE, 0x200D, 0x2642 }, - ["man gesturing no"]={ 0x1F645, 0x200D, 0x2642 }, - ["man gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2642 }, - ["man gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2642 }, - ["man gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2642 }, - ["man gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2642 }, - ["man gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2642 }, - ["man gesturing ok"]={ 0x1F646, 0x200D, 0x2642 }, - ["man gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2642 }, - ["man gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2642 }, - ["man gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2642 }, - ["man gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2642 }, - ["man gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2642 }, - ["man getting haircut"]={ 0x1F487, 0x200D, 0x2642 }, - ["man getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2642 }, - ["man getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2642 }, - ["man getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2642 }, - ["man getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2642 }, - ["man getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2642 }, - ["man getting massage"]={ 0x1F486, 0x200D, 0x2642 }, - ["man getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2642 }, - ["man getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2642 }, - ["man getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2642 }, - ["man getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2642 }, - ["man getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2642 }, - ["man golfing"]={ 0x1F3CC, 0x200D, 0x2642 }, - ["man golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2642 }, - ["man golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2642 }, - ["man golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2642 }, - ["man golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2642 }, - ["man golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2642 }, - ["man guard"]={ 0x1F482, 0x200D, 0x2642 }, - ["man guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2642 }, - ["man guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2642 }, - ["man guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2642 }, - ["man guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2642 }, - ["man guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2642 }, - ["man health worker"]={ 0x1F468, 0x200D, 0x2695 }, - ["man health worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2695 }, - ["man health worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2695 }, - ["man health worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2695 }, - ["man health worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2695 }, - ["man health worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2695 }, - ["man in business suit levitating"]={ 0x1F574 }, - ["man in business suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, - ["man in business suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, - ["man in business suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, - ["man in business suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, - ["man in business suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, - ["man in lotus position"]={ 0x1F9D8, 0x200D, 0x2642 }, - ["man in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2642 }, - ["man in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2642 }, - ["man in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2642 }, - ["man in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2642 }, - ["man in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2642 }, - ["man in steamy room"]={ 0x1F9D6, 0x200D, 0x2642 }, - ["man in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2642 }, - ["man in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2642 }, - ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642 }, - ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642 }, - ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642 }, + ["man frowning"]={ 0x1F64D, 0x200D, 0x2642, 0xFE0F }, + ["man frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man genie"]={ 0x1F9DE, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no"]={ 0x1F645, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok"]={ 0x1F646, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut"]={ 0x1F487, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage"]={ 0x1F486, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man golfing"]={ 0x1F3CC, 0xFE0F, 0x200D, 0x2642, 0xFE0F }, + ["man golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man guard"]={ 0x1F482, 0x200D, 0x2642, 0xFE0F }, + ["man guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man health worker"]={ 0x1F468, 0x200D, 0x2695, 0xFE0F }, + ["man health worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2695, 0xFE0F }, + ["man health worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2695, 0xFE0F }, + ["man health worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2695, 0xFE0F }, + ["man health worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2695, 0xFE0F }, + ["man health worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2695, 0xFE0F }, + ["man in lotus position"]={ 0x1F9D8, 0x200D, 0x2642, 0xFE0F }, + ["man in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man in manual wheelchair"]={ 0x1F468, 0x200D, 0x1F9BD }, + ["man in manual wheelchair: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9BD }, + ["man in manual wheelchair: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9BD }, + ["man in manual wheelchair: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9BD }, + ["man in manual wheelchair: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9BD }, + ["man in manual wheelchair: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9BD }, + ["man in motorized wheelchair"]={ 0x1F468, 0x200D, 0x1F9BC }, + ["man in motorized wheelchair: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9BC }, + ["man in motorized wheelchair: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9BC }, + ["man in motorized wheelchair: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9BC }, + ["man in motorized wheelchair: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9BC }, + ["man in motorized wheelchair: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9BC }, + ["man in steamy room"]={ 0x1F9D6, 0x200D, 0x2642, 0xFE0F }, + ["man in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man in suit levitating"]={ 0x1F574, 0xFE0F }, + ["man in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, + ["man in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, + ["man in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, + ["man in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, + ["man in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, ["man in tuxedo"]={ 0x1F935 }, ["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF }, ["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB }, ["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD }, ["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE }, ["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC }, - ["man judge"]={ 0x1F468, 0x200D, 0x2696 }, - ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696 }, - ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696 }, - ["man judge: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2696 }, - ["man judge: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2696 }, - ["man judge: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2696 }, - ["man juggling"]={ 0x1F939, 0x200D, 0x2642 }, - ["man juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2642 }, - ["man juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2642 }, - ["man juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2642 }, - ["man juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2642 }, - ["man juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2642 }, - ["man lifting weights"]={ 0x1F3CB, 0x200D, 0x2642 }, - ["man lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2642 }, - ["man lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2642 }, - ["man lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2642 }, - ["man lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2642 }, - ["man lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2642 }, - ["man mage"]={ 0x1F9D9, 0x200D, 0x2642 }, - ["man mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2642 }, - ["man mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2642 }, - ["man mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2642 }, - ["man mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2642 }, - ["man mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2642 }, + ["man judge"]={ 0x1F468, 0x200D, 0x2696, 0xFE0F }, + ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, + ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, + ["man judge: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2696, 0xFE0F }, + ["man judge: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2696, 0xFE0F }, + ["man judge: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2696, 0xFE0F }, + ["man juggling"]={ 0x1F939, 0x200D, 0x2642, 0xFE0F }, + ["man juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling"]={ 0x1F9CE, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights"]={ 0x1F3CB, 0xFE0F, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man mage"]={ 0x1F9D9, 0x200D, 0x2642, 0xFE0F }, + ["man mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man mechanic"]={ 0x1F468, 0x200D, 0x1F527 }, ["man mechanic: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F527 }, ["man mechanic: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F527 }, ["man mechanic: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F527 }, ["man mechanic: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F527 }, ["man mechanic: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F527 }, - ["man mountain biking"]={ 0x1F6B5, 0x200D, 0x2642 }, - ["man mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2642 }, - ["man mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2642 }, - ["man mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2642 }, - ["man mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2642 }, - ["man mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2642 }, + ["man mountain biking"]={ 0x1F6B5, 0x200D, 0x2642, 0xFE0F }, + ["man mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man office worker"]={ 0x1F468, 0x200D, 0x1F4BC }, ["man office worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F4BC }, ["man office worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F4BC }, ["man office worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F4BC }, ["man office worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F4BC }, ["man office worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F4BC }, - ["man pilot"]={ 0x1F468, 0x200D, 0x2708 }, - ["man pilot: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2708 }, - ["man pilot: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2708 }, - ["man pilot: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2708 }, - ["man pilot: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2708 }, - ["man pilot: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2708 }, - ["man playing handball"]={ 0x1F93E, 0x200D, 0x2642 }, - ["man playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2642 }, - ["man playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2642 }, - ["man playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2642 }, - ["man playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2642 }, - ["man playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2642 }, - ["man playing water polo"]={ 0x1F93D, 0x200D, 0x2642 }, - ["man playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2642 }, - ["man playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2642 }, - ["man playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2642 }, - ["man playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2642 }, - ["man playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2642 }, - ["man police officer"]={ 0x1F46E, 0x200D, 0x2642 }, - ["man police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2642 }, - ["man police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2642 }, - ["man police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2642 }, - ["man police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2642 }, - ["man police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2642 }, - ["man pouting"]={ 0x1F64E, 0x200D, 0x2642 }, - ["man pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2642 }, - ["man pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2642 }, - ["man pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2642 }, - ["man pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2642 }, - ["man pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2642 }, - ["man raising hand"]={ 0x1F64B, 0x200D, 0x2642 }, - ["man raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2642 }, - ["man raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2642 }, - ["man raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2642 }, - ["man raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2642 }, - ["man raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2642 }, - ["man rowing boat"]={ 0x1F6A3, 0x200D, 0x2642 }, - ["man rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2642 }, - ["man rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2642 }, - ["man rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2642 }, - ["man rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2642 }, - ["man rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2642 }, - ["man running"]={ 0x1F3C3, 0x200D, 0x2642 }, - ["man running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2642 }, - ["man running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2642 }, - ["man running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2642 }, - ["man running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2642 }, - ["man running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2642 }, + ["man pilot"]={ 0x1F468, 0x200D, 0x2708, 0xFE0F }, + ["man pilot: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2708, 0xFE0F }, + ["man pilot: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2708, 0xFE0F }, + ["man pilot: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2708, 0xFE0F }, + ["man pilot: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2708, 0xFE0F }, + ["man pilot: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2708, 0xFE0F }, + ["man playing handball"]={ 0x1F93E, 0x200D, 0x2642, 0xFE0F }, + ["man playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo"]={ 0x1F93D, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man police officer"]={ 0x1F46E, 0x200D, 0x2642, 0xFE0F }, + ["man police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man pouting"]={ 0x1F64E, 0x200D, 0x2642, 0xFE0F }, + ["man pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand"]={ 0x1F64B, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat"]={ 0x1F6A3, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man running"]={ 0x1F3C3, 0x200D, 0x2642, 0xFE0F }, + ["man running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man scientist"]={ 0x1F468, 0x200D, 0x1F52C }, ["man scientist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F52C }, ["man scientist: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F52C }, ["man scientist: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F52C }, ["man scientist: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F52C }, ["man scientist: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F52C }, - ["man shrugging"]={ 0x1F937, 0x200D, 0x2642 }, - ["man shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2642 }, - ["man shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2642 }, - ["man shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2642 }, - ["man shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2642 }, - ["man shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2642 }, + ["man shrugging"]={ 0x1F937, 0x200D, 0x2642, 0xFE0F }, + ["man shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man singer"]={ 0x1F468, 0x200D, 0x1F3A4 }, ["man singer: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A4 }, ["man singer: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3A4 }, ["man singer: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F3A4 }, ["man singer: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F3A4 }, ["man singer: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F3A4 }, + ["man standing"]={ 0x1F9CD, 0x200D, 0x2642, 0xFE0F }, + ["man standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man standing: light skin tone"]={ 0x1F9CD, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man student"]={ 0x1F468, 0x200D, 0x1F393 }, ["man student: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F393 }, ["man student: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F393 }, ["man student: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F393 }, ["man student: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F393 }, ["man student: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F393 }, - ["man surfing"]={ 0x1F3C4, 0x200D, 0x2642 }, - ["man surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2642 }, - ["man surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2642 }, - ["man surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2642 }, - ["man surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2642 }, - ["man surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2642 }, - ["man swimming"]={ 0x1F3CA, 0x200D, 0x2642 }, - ["man swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2642 }, - ["man swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2642 }, - ["man swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2642 }, - ["man swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2642 }, - ["man swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2642 }, + ["man superhero"]={ 0x1F9B8, 0x200D, 0x2642, 0xFE0F }, + ["man superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain"]={ 0x1F9B9, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man surfing"]={ 0x1F3C4, 0x200D, 0x2642, 0xFE0F }, + ["man surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man swimming"]={ 0x1F3CA, 0x200D, 0x2642, 0xFE0F }, + ["man swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man teacher"]={ 0x1F468, 0x200D, 0x1F3EB }, ["man teacher: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3EB }, ["man teacher: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3EB }, @@ -1251,73 +1473,131 @@ return { ["man technologist: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F4BB }, ["man technologist: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F4BB }, ["man technologist: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F4BB }, - ["man tipping hand"]={ 0x1F481, 0x200D, 0x2642 }, - ["man tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2642 }, - ["man tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2642 }, - ["man tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2642 }, - ["man tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2642 }, - ["man tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2642 }, - ["man vampire"]={ 0x1F9DB, 0x200D, 0x2642 }, - ["man vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2642 }, - ["man vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2642 }, - ["man vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2642 }, - ["man vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2642 }, - ["man vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2642 }, - ["man walking"]={ 0x1F6B6, 0x200D, 0x2642 }, - ["man walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2642 }, - ["man walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2642 }, - ["man walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2642 }, - ["man walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2642 }, - ["man walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2642 }, - ["man wearing turban"]={ 0x1F473, 0x200D, 0x2642 }, - ["man wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2642 }, - ["man wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2642 }, - ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642 }, - ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642 }, - ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642 }, + ["man tipping hand"]={ 0x1F481, 0x200D, 0x2642, 0xFE0F }, + ["man tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man vampire"]={ 0x1F9DB, 0x200D, 0x2642, 0xFE0F }, + ["man vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man walking"]={ 0x1F6B6, 0x200D, 0x2642, 0xFE0F }, + ["man walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban"]={ 0x1F473, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man with chinese cap"]={ 0x1F472 }, ["man with chinese cap: dark skin tone"]={ 0x1F472, 0x1F3FF }, ["man with chinese cap: light skin tone"]={ 0x1F472, 0x1F3FB }, ["man with chinese cap: medium skin tone"]={ 0x1F472, 0x1F3FD }, ["man with chinese cap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE }, ["man with chinese cap: medium-light skin tone"]={ 0x1F472, 0x1F3FC }, - ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642 }, + ["man with probing cane"]={ 0x1F468, 0x200D, 0x1F9AF }, + ["man with probing cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF }, + ["man with probing cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF }, + ["man with probing cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF }, + ["man with probing cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF }, + ["man with probing cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF }, + ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642, 0xFE0F }, + ["man: bald"]={ 0x1F468, 0x200D, 0x1F9B2 }, + ["man: beard"]={ 0x1F9D4 }, + ["man: blond hair"]={ 0x1F471, 0x200D, 0x2642, 0xFE0F }, + ["man: curly hair"]={ 0x1F468, 0x200D, 0x1F9B1 }, ["man: dark skin tone"]={ 0x1F468, 0x1F3FF }, + ["man: dark skin tone, bald"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B2 }, + ["man: dark skin tone, beard"]={ 0x1F9D4, 0x1F3FF }, + ["man: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man: dark skin tone, curly hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B1 }, + ["man: dark skin tone, red hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B0 }, + ["man: dark skin tone, white hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B3 }, ["man: light skin tone"]={ 0x1F468, 0x1F3FB }, + ["man: light skin tone, bald"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B2 }, + ["man: light skin tone, beard"]={ 0x1F9D4, 0x1F3FB }, + ["man: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man: light skin tone, curly hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B1 }, + ["man: light skin tone, red hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B0 }, + ["man: light skin tone, white hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B3 }, ["man: medium skin tone"]={ 0x1F468, 0x1F3FD }, + ["man: medium skin tone, bald"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B2 }, + ["man: medium skin tone, beard"]={ 0x1F9D4, 0x1F3FD }, + ["man: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man: medium skin tone, curly hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B1 }, + ["man: medium skin tone, red hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B0 }, + ["man: medium skin tone, white hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B3 }, ["man: medium-dark skin tone"]={ 0x1F468, 0x1F3FE }, + ["man: medium-dark skin tone, bald"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B2 }, + ["man: medium-dark skin tone, beard"]={ 0x1F9D4, 0x1F3FE }, + ["man: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man: medium-dark skin tone, curly hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B1 }, + ["man: medium-dark skin tone, red hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B0 }, + ["man: medium-dark skin tone, white hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B3 }, ["man: medium-light skin tone"]={ 0x1F468, 0x1F3FC }, - ["mantelpiece clock"]={ 0x1F570 }, + ["man: medium-light skin tone, bald"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B2 }, + ["man: medium-light skin tone, beard"]={ 0x1F9D4, 0x1F3FC }, + ["man: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man: medium-light skin tone, curly hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B1 }, + ["man: medium-light skin tone, red hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B0 }, + ["man: medium-light skin tone, white hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B3 }, + ["man: red hair"]={ 0x1F468, 0x200D, 0x1F9B0 }, + ["man: white hair"]={ 0x1F468, 0x200D, 0x1F9B3 }, + ["mango"]={ 0x1F96D }, + ["mantelpiece clock"]={ 0x1F570, 0xFE0F }, + ["manual wheelchair"]={ 0x1F9BD }, ["man’s shoe"]={ 0x1F45E }, ["map of japan"]={ 0x1F5FE }, ["maple leaf"]={ 0x1F341 }, - ["marshall islands"]={ 0x1F1F2, 0x1F1ED }, ["martial arts uniform"]={ 0x1F94B }, - ["martinique"]={ 0x1F1F2, 0x1F1F6 }, - ["mauritania"]={ 0x1F1F2, 0x1F1F7 }, - ["mauritius"]={ 0x1F1F2, 0x1F1FA }, - ["mayotte"]={ 0x1F1FE, 0x1F1F9 }, + ["mate"]={ 0x1F9C9 }, ["meat on bone"]={ 0x1F356 }, - ["medical symbol"]={ 0x2695 }, + ["mechanical arm"]={ 0x1F9BE }, + ["mechanical leg"]={ 0x1F9BF }, + ["medical symbol"]={ 0x2695, 0xFE0F }, ["megaphone"]={ 0x1F4E3 }, ["melon"]={ 0x1F348 }, ["memo"]={ 0x1F4DD }, - ["men with bunny ears partying"]={ 0x1F46F, 0x200D, 0x2642 }, - ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642 }, + ["men holding hands"]={ 0x1F46C }, + ["men holding hands: dark skin tone"]={ 0x1F46C, 0x1F3FF }, + ["men holding hands: dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["men holding hands: dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["men holding hands: light skin tone"]={ 0x1F46C, 0x1F3FB }, + ["men holding hands: medium skin tone"]={ 0x1F46C, 0x1F3FD }, + ["men holding hands: medium skin tone, light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["men holding hands: medium-dark skin tone"]={ 0x1F46C, 0x1F3FE }, + ["men holding hands: medium-dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["men holding hands: medium-light skin tone"]={ 0x1F46C, 0x1F3FC }, + ["men holding hands: medium-light skin tone, light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men with bunny ears"]={ 0x1F46F, 0x200D, 0x2642, 0xFE0F }, + ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642, 0xFE0F }, ["menorah"]={ 0x1F54E }, ["men’s room"]={ 0x1F6B9 }, - ["mermaid"]={ 0x1F9DC, 0x200D, 0x2640 }, - ["mermaid: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2640 }, - ["mermaid: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2640 }, - ["mermaid: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2640 }, - ["mermaid: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2640 }, - ["mermaid: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2640 }, - ["merman"]={ 0x1F9DC, 0x200D, 0x2642 }, - ["merman: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2642 }, - ["merman: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2642 }, - ["merman: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2642 }, - ["merman: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2642 }, - ["merman: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2642 }, + ["mermaid"]={ 0x1F9DC, 0x200D, 0x2640, 0xFE0F }, + ["mermaid: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["mermaid: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["mermaid: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["mermaid: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["mermaid: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["merman"]={ 0x1F9DC, 0x200D, 0x2642, 0xFE0F }, + ["merman: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["merman: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["merman: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["merman: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["merman: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["merperson"]={ 0x1F9DC }, ["merperson: dark skin tone"]={ 0x1F9DC, 0x1F3FF }, ["merperson: light skin tone"]={ 0x1F9DC, 0x1F3FB }, @@ -1325,8 +1605,7 @@ return { ["merperson: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE }, ["merperson: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC }, ["metro"]={ 0x1F687 }, - ["mexico"]={ 0x1F1F2, 0x1F1FD }, - ["micronesia"]={ 0x1F1EB, 0x1F1F2 }, + ["microbe"]={ 0x1F9A0 }, ["microphone"]={ 0x1F3A4 }, ["microscope"]={ 0x1F52C }, ["middle finger"]={ 0x1F595 }, @@ -1335,53 +1614,50 @@ return { ["middle finger: medium skin tone"]={ 0x1F595, 0x1F3FD }, ["middle finger: medium-dark skin tone"]={ 0x1F595, 0x1F3FE }, ["middle finger: medium-light skin tone"]={ 0x1F595, 0x1F3FC }, - ["military medal"]={ 0x1F396 }, + ["military medal"]={ 0x1F396, 0xFE0F }, ["milky way"]={ 0x1F30C }, ["minibus"]={ 0x1F690 }, + ["minus sign"]={ 0x2796 }, ["moai"]={ 0x1F5FF }, ["mobile phone"]={ 0x1F4F1 }, ["mobile phone off"]={ 0x1F4F4 }, ["mobile phone with arrow"]={ 0x1F4F2 }, - ["moldova"]={ 0x1F1F2, 0x1F1E9 }, - ["monaco"]={ 0x1F1F2, 0x1F1E8 }, ["money bag"]={ 0x1F4B0 }, ["money with wings"]={ 0x1F4B8 }, ["money-mouth face"]={ 0x1F911 }, - ["mongolia"]={ 0x1F1F2, 0x1F1F3 }, ["monkey"]={ 0x1F412 }, ["monkey face"]={ 0x1F435 }, ["monorail"]={ 0x1F69D }, - ["montenegro"]={ 0x1F1F2, 0x1F1EA }, - ["montserrat"]={ 0x1F1F2, 0x1F1F8 }, + ["moon cake"]={ 0x1F96E }, ["moon viewing ceremony"]={ 0x1F391 }, - ["morocco"]={ 0x1F1F2, 0x1F1E6 }, ["mosque"]={ 0x1F54C }, - ["motor boat"]={ 0x1F6E5 }, + ["mosquito"]={ 0x1F99F }, + ["motor boat"]={ 0x1F6E5, 0xFE0F }, ["motor scooter"]={ 0x1F6F5 }, - ["motorcycle"]={ 0x1F3CD }, - ["motorway"]={ 0x1F6E3 }, + ["motorcycle"]={ 0x1F3CD, 0xFE0F }, + ["motorized wheelchair"]={ 0x1F9BC }, + ["motorway"]={ 0x1F6E3, 0xFE0F }, ["mount fuji"]={ 0x1F5FB }, - ["mountain"]={ 0x26F0 }, + ["mountain"]={ 0x26F0, 0xFE0F }, ["mountain cableway"]={ 0x1F6A0 }, ["mountain railway"]={ 0x1F69E }, ["mouse"]={ 0x1F401 }, ["mouse face"]={ 0x1F42D }, ["mouth"]={ 0x1F444 }, ["movie camera"]={ 0x1F3A5 }, - ["mozambique"]={ 0x1F1F2, 0x1F1FF }, ["mrs. claus"]={ 0x1F936 }, ["mrs. claus: dark skin tone"]={ 0x1F936, 0x1F3FF }, ["mrs. claus: light skin tone"]={ 0x1F936, 0x1F3FB }, ["mrs. claus: medium skin tone"]={ 0x1F936, 0x1F3FD }, ["mrs. claus: medium-dark skin tone"]={ 0x1F936, 0x1F3FE }, ["mrs. claus: medium-light skin tone"]={ 0x1F936, 0x1F3FC }, + ["multiplication sign"]={ 0x2716, 0xFE0F }, ["mushroom"]={ 0x1F344 }, ["musical keyboard"]={ 0x1F3B9 }, ["musical note"]={ 0x1F3B5 }, ["musical notes"]={ 0x1F3B6 }, ["musical score"]={ 0x1F3BC }, ["muted speaker"]={ 0x1F507 }, - ["myanmar (burma)"]={ 0x1F1F2, 0x1F1F2 }, ["nail polish"]={ 0x1F485 }, ["nail polish: dark skin tone"]={ 0x1F485, 0x1F3FF }, ["nail polish: light skin tone"]={ 0x1F485, 0x1F3FB }, @@ -1389,30 +1665,21 @@ return { ["nail polish: medium-dark skin tone"]={ 0x1F485, 0x1F3FE }, ["nail polish: medium-light skin tone"]={ 0x1F485, 0x1F3FC }, ["name badge"]={ 0x1F4DB }, - ["namibia"]={ 0x1F1F3, 0x1F1E6 }, - ["national park"]={ 0x1F3DE }, - ["nauru"]={ 0x1F1F3, 0x1F1F7 }, + ["national park"]={ 0x1F3DE, 0xFE0F }, ["nauseated face"]={ 0x1F922 }, + ["nazar amulet"]={ 0x1F9FF }, ["necktie"]={ 0x1F454 }, - ["nepal"]={ 0x1F1F3, 0x1F1F5 }, ["nerd face"]={ 0x1F913 }, - ["netherlands"]={ 0x1F1F3, 0x1F1F1 }, ["neutral face"]={ 0x1F610 }, ["new button"]={ 0x1F195 }, - ["new caledonia"]={ 0x1F1F3, 0x1F1E8 }, ["new moon"]={ 0x1F311 }, ["new moon face"]={ 0x1F31A }, - ["new zealand"]={ 0x1F1F3, 0x1F1FF }, ["newspaper"]={ 0x1F4F0 }, - ["next track button"]={ 0x23ED }, + ["next track button"]={ 0x23ED, 0xFE0F }, ["ng button"]={ 0x1F196 }, - ["nicaragua"]={ 0x1F1F3, 0x1F1EE }, - ["niger"]={ 0x1F1F3, 0x1F1EA }, - ["nigeria"]={ 0x1F1F3, 0x1F1EC }, ["night with stars"]={ 0x1F303 }, ["nine o’clock"]={ 0x1F558 }, ["nine-thirty"]={ 0x1F564 }, - ["niue"]={ 0x1F1F3, 0x1F1FA }, ["no bicycles"]={ 0x1F6B3 }, ["no entry"]={ 0x26D4 }, ["no littering"]={ 0x1F6AF }, @@ -1421,10 +1688,6 @@ return { ["no pedestrians"]={ 0x1F6B7 }, ["no smoking"]={ 0x1F6AD }, ["non-potable water"]={ 0x1F6B1 }, - ["norfolk island"]={ 0x1F1F3, 0x1F1EB }, - ["north korea"]={ 0x1F1F0, 0x1F1F5 }, - ["northern mariana islands"]={ 0x1F1F2, 0x1F1F5 }, - ["norway"]={ 0x1F1F3, 0x1F1F4 }, ["nose"]={ 0x1F443 }, ["nose: dark skin tone"]={ 0x1F443, 0x1F3FF }, ["nose: light skin tone"]={ 0x1F443, 0x1F3FB }, @@ -1434,12 +1697,12 @@ return { ["notebook"]={ 0x1F4D3 }, ["notebook with decorative cover"]={ 0x1F4D4 }, ["nut and bolt"]={ 0x1F529 }, - ["o button (blood type)"]={ 0x1F17E }, + ["o button (blood type)"]={ 0x1F17E, 0xFE0F }, ["octopus"]={ 0x1F419 }, ["oden"]={ 0x1F362 }, ["office building"]={ 0x1F3E2 }, ["ogre"]={ 0x1F479 }, - ["oil drum"]={ 0x1F6E2 }, + ["oil drum"]={ 0x1F6E2, 0xFE0F }, ["ok button"]={ 0x1F197 }, ["ok hand"]={ 0x1F44C }, ["ok hand: dark skin tone"]={ 0x1F44C, 0x1F3FF }, @@ -1447,7 +1710,7 @@ return { ["ok hand: medium skin tone"]={ 0x1F44C, 0x1F3FD }, ["ok hand: medium-dark skin tone"]={ 0x1F44C, 0x1F3FE }, ["ok hand: medium-light skin tone"]={ 0x1F44C, 0x1F3FC }, - ["old key"]={ 0x1F5DD }, + ["old key"]={ 0x1F5DD, 0xFE0F }, ["old man"]={ 0x1F474 }, ["old man: dark skin tone"]={ 0x1F474, 0x1F3FF }, ["old man: light skin tone"]={ 0x1F474, 0x1F3FB }, @@ -1460,14 +1723,13 @@ return { ["old woman: medium skin tone"]={ 0x1F475, 0x1F3FD }, ["old woman: medium-dark skin tone"]={ 0x1F475, 0x1F3FE }, ["old woman: medium-light skin tone"]={ 0x1F475, 0x1F3FC }, - ["older adult"]={ 0x1F9D3 }, - ["older adult: dark skin tone"]={ 0x1F9D3, 0x1F3FF }, - ["older adult: light skin tone"]={ 0x1F9D3, 0x1F3FB }, - ["older adult: medium skin tone"]={ 0x1F9D3, 0x1F3FD }, - ["older adult: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE }, - ["older adult: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC }, - ["om"]={ 0x1F549 }, - ["oman"]={ 0x1F1F4, 0x1F1F2 }, + ["older person"]={ 0x1F9D3 }, + ["older person: dark skin tone"]={ 0x1F9D3, 0x1F3FF }, + ["older person: light skin tone"]={ 0x1F9D3, 0x1F3FB }, + ["older person: medium skin tone"]={ 0x1F9D3, 0x1F3FD }, + ["older person: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE }, + ["older person: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC }, + ["om"]={ 0x1F549, 0xFE0F }, ["on! arrow"]={ 0x1F51B }, ["oncoming automobile"]={ 0x1F698 }, ["oncoming bus"]={ 0x1F68D }, @@ -1480,7 +1742,9 @@ return { ["oncoming police car"]={ 0x1F694 }, ["oncoming taxi"]={ 0x1F696 }, ["one o’clock"]={ 0x1F550 }, + ["one-piece swimsuit"]={ 0x1FA71 }, ["one-thirty"]={ 0x1F55C }, + ["onion"]={ 0x1F9C5 }, ["open book"]={ 0x1F4D6 }, ["open file folder"]={ 0x1F4C2 }, ["open hands"]={ 0x1F450 }, @@ -1494,20 +1758,22 @@ return { ["ophiuchus"]={ 0x26CE }, ["optical disk"]={ 0x1F4BF }, ["orange book"]={ 0x1F4D9 }, + ["orange circle"]={ 0x1F7E0 }, ["orange heart"]={ 0x1F9E1 }, - ["orthodox cross"]={ 0x2626 }, + ["orange square"]={ 0x1F7E7 }, + ["orangutan"]={ 0x1F9A7 }, + ["orthodox cross"]={ 0x2626, 0xFE0F }, + ["otter"]={ 0x1F9A6 }, ["outbox tray"]={ 0x1F4E4 }, ["owl"]={ 0x1F989 }, ["ox"]={ 0x1F402 }, - ["p button"]={ 0x1F17F }, + ["oyster"]={ 0x1F9AA }, + ["p button"]={ 0x1F17F, 0xFE0F }, ["package"]={ 0x1F4E6 }, ["page facing up"]={ 0x1F4C4 }, ["page with curl"]={ 0x1F4C3 }, ["pager"]={ 0x1F4DF }, - ["paintbrush"]={ 0x1F58C }, - ["pakistan"]={ 0x1F1F5, 0x1F1F0 }, - ["palau"]={ 0x1F1F5, 0x1F1FC }, - ["palestinian territories"]={ 0x1F1F5, 0x1F1F8 }, + ["paintbrush"]={ 0x1F58C, 0xFE0F }, ["palm tree"]={ 0x1F334 }, ["palms up together"]={ 0x1F932 }, ["palms up together: dark skin tone"]={ 0x1F932, 0x1F3FF }, @@ -1515,37 +1781,55 @@ return { ["palms up together: medium skin tone"]={ 0x1F932, 0x1F3FD }, ["palms up together: medium-dark skin tone"]={ 0x1F932, 0x1F3FE }, ["palms up together: medium-light skin tone"]={ 0x1F932, 0x1F3FC }, - ["panama"]={ 0x1F1F5, 0x1F1E6 }, ["pancakes"]={ 0x1F95E }, - ["panda face"]={ 0x1F43C }, + ["panda"]={ 0x1F43C }, ["paperclip"]={ 0x1F4CE }, - ["papua new guinea"]={ 0x1F1F5, 0x1F1EC }, - ["paraguay"]={ 0x1F1F5, 0x1F1FE }, - ["part alternation mark"]={ 0x303D }, + ["parachute"]={ 0x1FA82 }, + ["parrot"]={ 0x1F99C }, + ["part alternation mark"]={ 0x303D, 0xFE0F }, ["party popper"]={ 0x1F389 }, - ["passenger ship"]={ 0x1F6F3 }, + ["partying face"]={ 0x1F973 }, + ["passenger ship"]={ 0x1F6F3, 0xFE0F }, ["passport control"]={ 0x1F6C2 }, - ["pause button"]={ 0x23F8 }, + ["pause button"]={ 0x23F8, 0xFE0F }, ["paw prints"]={ 0x1F43E }, - ["peace symbol"]={ 0x262E }, + ["peace symbol"]={ 0x262E, 0xFE0F }, ["peach"]={ 0x1F351 }, + ["peacock"]={ 0x1F99A }, ["peanuts"]={ 0x1F95C }, ["pear"]={ 0x1F350 }, - ["pen"]={ 0x1F58A }, - ["pencil"]={ 0x270F }, + ["pen"]={ 0x1F58A, 0xFE0F }, + ["pencil"]={ 0x270F, 0xFE0F }, ["penguin"]={ 0x1F427 }, ["pensive face"]={ 0x1F614 }, - ["people with bunny ears partying"]={ 0x1F46F }, + ["people holding hands"]={ 0x1F9D1, 0x200D, 0x1F91D, 0x200D, 0x1F9D1 }, + ["people holding hands: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, + ["people holding hands: dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: medium-dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: medium-light skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people with bunny ears"]={ 0x1F46F }, ["people wrestling"]={ 0x1F93C }, ["performing arts"]={ 0x1F3AD }, ["persevering face"]={ 0x1F623 }, + ["person"]={ 0x1F9D1 }, ["person biking"]={ 0x1F6B4 }, ["person biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF }, ["person biking: light skin tone"]={ 0x1F6B4, 0x1F3FB }, ["person biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD }, ["person biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE }, ["person biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC }, - ["person bouncing ball"]={ 0x26F9 }, + ["person bouncing ball"]={ 0x26F9, 0xFE0F }, ["person bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF }, ["person bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB }, ["person bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD }, @@ -1606,7 +1890,7 @@ return { ["person getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD }, ["person getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE }, ["person getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC }, - ["person golfing"]={ 0x1F3CC }, + ["person golfing"]={ 0x1F3CC, 0xFE0F }, ["person golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF }, ["person golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB }, ["person golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD }, @@ -1636,7 +1920,13 @@ return { ["person juggling: medium skin tone"]={ 0x1F939, 0x1F3FD }, ["person juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE }, ["person juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC }, - ["person lifting weights"]={ 0x1F3CB }, + ["person kneeling"]={ 0x1F9CE }, + ["person kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF }, + ["person kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB }, + ["person kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD }, + ["person kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE }, + ["person kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC }, + ["person lifting weights"]={ 0x1F3CB, 0xFE0F }, ["person lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF }, ["person lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB }, ["person lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD }, @@ -1690,6 +1980,12 @@ return { ["person shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD }, ["person shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE }, ["person shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC }, + ["person standing"]={ 0x1F9CD }, + ["person standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF }, + ["person standing: light skin tone"]={ 0x1F9CD, 0x1F3FB }, + ["person standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD }, + ["person standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE }, + ["person standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC }, ["person surfing"]={ 0x1F3C4 }, ["person surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF }, ["person surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB }, @@ -1726,26 +2022,43 @@ return { ["person wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD }, ["person wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE }, ["person wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC }, - ["peru"]={ 0x1F1F5, 0x1F1EA }, - ["philippines"]={ 0x1F1F5, 0x1F1ED }, - ["pick"]={ 0x26CF }, + ["person: blond hair"]={ 0x1F471 }, + ["person: dark skin tone"]={ 0x1F9D1, 0x1F3FF }, + ["person: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF }, + ["person: light skin tone"]={ 0x1F9D1, 0x1F3FB }, + ["person: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB }, + ["person: medium skin tone"]={ 0x1F9D1, 0x1F3FD }, + ["person: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD }, + ["person: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE }, + ["person: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE }, + ["person: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC }, + ["person: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC }, + ["petri dish"]={ 0x1F9EB }, + ["pick"]={ 0x26CF, 0xFE0F }, ["pie"]={ 0x1F967 }, ["pig"]={ 0x1F416 }, ["pig face"]={ 0x1F437 }, ["pig nose"]={ 0x1F43D }, ["pile of poo"]={ 0x1F4A9 }, ["pill"]={ 0x1F48A }, + ["pinching hand"]={ 0x1F90F }, + ["pinching hand: dark skin tone"]={ 0x1F90F, 0x1F3FF }, + ["pinching hand: light skin tone"]={ 0x1F90F, 0x1F3FB }, + ["pinching hand: medium skin tone"]={ 0x1F90F, 0x1F3FD }, + ["pinching hand: medium-dark skin tone"]={ 0x1F90F, 0x1F3FE }, + ["pinching hand: medium-light skin tone"]={ 0x1F90F, 0x1F3FC }, ["pine decoration"]={ 0x1F38D }, ["pineapple"]={ 0x1F34D }, ["ping pong"]={ 0x1F3D3 }, + ["pirate flag"]={ 0x1F3F4, 0x200D, 0x2620, 0xFE0F }, ["pisces"]={ 0x2653 }, ["pistol"]={ 0x1F52B }, - ["pitcairn islands"]={ 0x1F1F5, 0x1F1F3 }, ["pizza"]={ 0x1F355 }, ["place of worship"]={ 0x1F6D0 }, - ["play button"]={ 0x25B6 }, - ["play or pause button"]={ 0x23EF }, - ["poland"]={ 0x1F1F5, 0x1F1F1 }, + ["play button"]={ 0x25B6, 0xFE0F }, + ["play or pause button"]={ 0x23EF, 0xFE0F }, + ["pleading face"]={ 0x1F97A }, + ["plus sign"]={ 0x2795 }, ["police car"]={ 0x1F693 }, ["police car light"]={ 0x1F6A8 }, ["police officer"]={ 0x1F46E }, @@ -1757,7 +2070,6 @@ return { ["poodle"]={ 0x1F429 }, ["pool 8 ball"]={ 0x1F3B1 }, ["popcorn"]={ 0x1F37F }, - ["portugal"]={ 0x1F1F5, 0x1F1F9 }, ["post office"]={ 0x1F3E4 }, ["postal horn"]={ 0x1F4EF }, ["postbox"]={ 0x1F4EE }, @@ -1766,7 +2078,7 @@ return { ["potato"]={ 0x1F954 }, ["poultry leg"]={ 0x1F357 }, ["pound banknote"]={ 0x1F4B7 }, - ["pouting cat face"]={ 0x1F63E }, + ["pouting cat"]={ 0x1F63E }, ["pouting face"]={ 0x1F621 }, ["prayer beads"]={ 0x1F4FF }, ["pregnant woman"]={ 0x1F930 }, @@ -1788,24 +2100,27 @@ return { ["princess: medium skin tone"]={ 0x1F478, 0x1F3FD }, ["princess: medium-dark skin tone"]={ 0x1F478, 0x1F3FE }, ["princess: medium-light skin tone"]={ 0x1F478, 0x1F3FC }, - ["printer"]={ 0x1F5A8 }, + ["printer"]={ 0x1F5A8, 0xFE0F }, + ["probing cane"]={ 0x1F9AF }, ["prohibited"]={ 0x1F6AB }, - ["puerto rico"]={ 0x1F1F5, 0x1F1F7 }, + ["purple circle"]={ 0x1F7E3 }, ["purple heart"]={ 0x1F49C }, + ["purple square"]={ 0x1F7EA }, ["purse"]={ 0x1F45B }, ["pushpin"]={ 0x1F4CC }, - ["qatar"]={ 0x1F1F6, 0x1F1E6 }, + ["puzzle piece"]={ 0x1F9E9 }, ["question mark"]={ 0x2753 }, ["rabbit"]={ 0x1F407 }, ["rabbit face"]={ 0x1F430 }, - ["racing car"]={ 0x1F3CE }, + ["raccoon"]={ 0x1F99D }, + ["racing car"]={ 0x1F3CE, 0xFE0F }, ["radio"]={ 0x1F4FB }, ["radio button"]={ 0x1F518 }, - ["radioactive"]={ 0x2622 }, + ["radioactive"]={ 0x2622, 0xFE0F }, ["railway car"]={ 0x1F683 }, - ["railway track"]={ 0x1F6E4 }, + ["railway track"]={ 0x1F6E4, 0xFE0F }, ["rainbow"]={ 0x1F308 }, - ["rainbow flag"]={ 0x1F3F3, 0x200D, 0x1F308 }, + ["rainbow flag"]={ 0x1F3F3, 0xFE0F, 0x200D, 0x1F308 }, ["raised back of hand"]={ 0x1F91A }, ["raised back of hand: dark skin tone"]={ 0x1F91A, 0x1F3FF }, ["raised back of hand: light skin tone"]={ 0x1F91A, 0x1F3FB }, @@ -1819,12 +2134,6 @@ return { ["raised fist: medium-dark skin tone"]={ 0x270A, 0x1F3FE }, ["raised fist: medium-light skin tone"]={ 0x270A, 0x1F3FC }, ["raised hand"]={ 0x270B }, - ["raised hand with fingers splayed"]={ 0x1F590 }, - ["raised hand with fingers splayed: dark skin tone"]={ 0x1F590, 0x1F3FF }, - ["raised hand with fingers splayed: light skin tone"]={ 0x1F590, 0x1F3FB }, - ["raised hand with fingers splayed: medium skin tone"]={ 0x1F590, 0x1F3FD }, - ["raised hand with fingers splayed: medium-dark skin tone"]={ 0x1F590, 0x1F3FE }, - ["raised hand with fingers splayed: medium-light skin tone"]={ 0x1F590, 0x1F3FC }, ["raised hand: dark skin tone"]={ 0x270B, 0x1F3FF }, ["raised hand: light skin tone"]={ 0x270B, 0x1F3FB }, ["raised hand: medium skin tone"]={ 0x270B, 0x1F3FD }, @@ -1838,62 +2147,65 @@ return { ["raising hands: medium-light skin tone"]={ 0x1F64C, 0x1F3FC }, ["ram"]={ 0x1F40F }, ["rat"]={ 0x1F400 }, - ["record button"]={ 0x23FA }, - ["recycling symbol"]={ 0x267B }, + ["razor"]={ 0x1FA92 }, + ["receipt"]={ 0x1F9FE }, + ["record button"]={ 0x23FA, 0xFE0F }, + ["recycling symbol"]={ 0x267B, 0xFE0F }, ["red apple"]={ 0x1F34E }, ["red circle"]={ 0x1F534 }, - ["red heart"]={ 0x2764 }, + ["red envelope"]={ 0x1F9E7 }, + ["red heart"]={ 0x2764, 0xFE0F }, ["red paper lantern"]={ 0x1F3EE }, + ["red square"]={ 0x1F7E5 }, ["red triangle pointed down"]={ 0x1F53B }, ["red triangle pointed up"]={ 0x1F53A }, - ["registered"]={ 0xAE }, + ["registered"]={ 0xAE, 0xFE0F }, ["relieved face"]={ 0x1F60C }, - ["reminder ribbon"]={ 0x1F397 }, + ["reminder ribbon"]={ 0x1F397, 0xFE0F }, ["repeat button"]={ 0x1F501 }, ["repeat single button"]={ 0x1F502 }, - ["rescue worker’s helmet"]={ 0x26D1 }, + ["rescue worker’s helmet"]={ 0x26D1, 0xFE0F }, ["restroom"]={ 0x1F6BB }, - ["reverse button"]={ 0x25C0 }, + ["reverse button"]={ 0x25C0, 0xFE0F }, ["revolving hearts"]={ 0x1F49E }, ["rhinoceros"]={ 0x1F98F }, ["ribbon"]={ 0x1F380 }, ["rice ball"]={ 0x1F359 }, ["rice cracker"]={ 0x1F358 }, - ["right anger bubble"]={ 0x1F5EF }, - ["right arrow"]={ 0x27A1 }, - ["right arrow curving down"]={ 0x2935 }, - ["right arrow curving left"]={ 0x21A9 }, - ["right arrow curving up"]={ 0x2934 }, + ["right anger bubble"]={ 0x1F5EF, 0xFE0F }, + ["right arrow"]={ 0x27A1, 0xFE0F }, + ["right arrow curving down"]={ 0x2935, 0xFE0F }, + ["right arrow curving left"]={ 0x21A9, 0xFE0F }, + ["right arrow curving up"]={ 0x2934, 0xFE0F }, ["right-facing fist"]={ 0x1F91C }, ["right-facing fist: dark skin tone"]={ 0x1F91C, 0x1F3FF }, ["right-facing fist: light skin tone"]={ 0x1F91C, 0x1F3FB }, ["right-facing fist: medium skin tone"]={ 0x1F91C, 0x1F3FD }, ["right-facing fist: medium-dark skin tone"]={ 0x1F91C, 0x1F3FE }, ["right-facing fist: medium-light skin tone"]={ 0x1F91C, 0x1F3FC }, - ["right-pointing magnifying glass"]={ 0x1F50E }, ["ring"]={ 0x1F48D }, + ["ringed planet"]={ 0x1FA90 }, ["roasted sweet potato"]={ 0x1F360 }, - ["robot face"]={ 0x1F916 }, + ["robot"]={ 0x1F916 }, ["rocket"]={ 0x1F680 }, - ["rolled-up newspaper"]={ 0x1F5DE }, + ["roll of paper"]={ 0x1F9FB }, + ["rolled-up newspaper"]={ 0x1F5DE, 0xFE0F }, ["roller coaster"]={ 0x1F3A2 }, ["rolling on the floor laughing"]={ 0x1F923 }, - ["romania"]={ 0x1F1F7, 0x1F1F4 }, ["rooster"]={ 0x1F413 }, ["rose"]={ 0x1F339 }, - ["rosette"]={ 0x1F3F5 }, + ["rosette"]={ 0x1F3F5, 0xFE0F }, ["round pushpin"]={ 0x1F4CD }, ["rugby football"]={ 0x1F3C9 }, ["running shirt"]={ 0x1F3BD }, ["running shoe"]={ 0x1F45F }, - ["russia"]={ 0x1F1F7, 0x1F1FA }, - ["rwanda"]={ 0x1F1F7, 0x1F1FC }, - ["réunion"]={ 0x1F1F7, 0x1F1EA }, + ["sad but relieved face"]={ 0x1F625 }, + ["safety pin"]={ 0x1F9F7 }, + ["safety vest"]={ 0x1F9BA }, ["sagittarius"]={ 0x2650 }, ["sailboat"]={ 0x26F5 }, ["sake"]={ 0x1F376 }, - ["samoa"]={ 0x1F1FC, 0x1F1F8 }, - ["san marino"]={ 0x1F1F8, 0x1F1F2 }, + ["salt"]={ 0x1F9C2 }, ["sandwich"]={ 0x1F96A }, ["santa claus"]={ 0x1F385 }, ["santa claus: dark skin tone"]={ 0x1F385, 0x1F3FF }, @@ -1901,18 +2213,16 @@ return { ["santa claus: medium skin tone"]={ 0x1F385, 0x1F3FD }, ["santa claus: medium-dark skin tone"]={ 0x1F385, 0x1F3FE }, ["santa claus: medium-light skin tone"]={ 0x1F385, 0x1F3FC }, - ["satellite"]={ 0x1F6F0 }, + ["sari"]={ 0x1F97B }, + ["satellite"]={ 0x1F6F0, 0xFE0F }, ["satellite antenna"]={ 0x1F4E1 }, - ["saudi arabia"]={ 0x1F1F8, 0x1F1E6 }, ["sauropod"]={ 0x1F995 }, ["saxophone"]={ 0x1F3B7 }, ["scarf"]={ 0x1F9E3 }, ["school"]={ 0x1F3EB }, - ["school backpack"]={ 0x1F392 }, - ["scissors"]={ 0x2702 }, + ["scissors"]={ 0x2702, 0xFE0F }, + ["scorpio"]={ 0x264F }, ["scorpion"]={ 0x1F982 }, - ["scorpius"]={ 0x264F }, - ["scotland"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0073, 0xE0063, 0xE0074, 0xE007F }, ["scroll"]={ 0x1F4DC }, ["seat"]={ 0x1F4BA }, ["see-no-evil monkey"]={ 0x1F648 }, @@ -1923,94 +2233,82 @@ return { ["selfie: medium skin tone"]={ 0x1F933, 0x1F3FD }, ["selfie: medium-dark skin tone"]={ 0x1F933, 0x1F3FE }, ["selfie: medium-light skin tone"]={ 0x1F933, 0x1F3FC }, - ["senegal"]={ 0x1F1F8, 0x1F1F3 }, - ["serbia"]={ 0x1F1F7, 0x1F1F8 }, + ["service dog"]={ 0x1F415, 0x200D, 0x1F9BA }, ["seven o’clock"]={ 0x1F556 }, ["seven-thirty"]={ 0x1F562 }, - ["seychelles"]={ 0x1F1F8, 0x1F1E8 }, ["shallow pan of food"]={ 0x1F958 }, - ["shamrock"]={ 0x2618 }, + ["shamrock"]={ 0x2618, 0xFE0F }, ["shark"]={ 0x1F988 }, ["shaved ice"]={ 0x1F367 }, ["sheaf of rice"]={ 0x1F33E }, - ["shield"]={ 0x1F6E1 }, - ["shinto shrine"]={ 0x26E9 }, + ["shield"]={ 0x1F6E1, 0xFE0F }, + ["shinto shrine"]={ 0x26E9, 0xFE0F }, ["ship"]={ 0x1F6A2 }, ["shooting star"]={ 0x1F320 }, - ["shopping bags"]={ 0x1F6CD }, + ["shopping bags"]={ 0x1F6CD, 0xFE0F }, ["shopping cart"]={ 0x1F6D2 }, ["shortcake"]={ 0x1F370 }, + ["shorts"]={ 0x1FA73 }, ["shower"]={ 0x1F6BF }, ["shrimp"]={ 0x1F990 }, ["shuffle tracks button"]={ 0x1F500 }, ["shushing face"]={ 0x1F92B }, - ["sierra leone"]={ 0x1F1F8, 0x1F1F1 }, ["sign of the horns"]={ 0x1F918 }, ["sign of the horns: dark skin tone"]={ 0x1F918, 0x1F3FF }, ["sign of the horns: light skin tone"]={ 0x1F918, 0x1F3FB }, ["sign of the horns: medium skin tone"]={ 0x1F918, 0x1F3FD }, ["sign of the horns: medium-dark skin tone"]={ 0x1F918, 0x1F3FE }, ["sign of the horns: medium-light skin tone"]={ 0x1F918, 0x1F3FC }, - ["singapore"]={ 0x1F1F8, 0x1F1EC }, - ["sint maarten"]={ 0x1F1F8, 0x1F1FD }, ["six o’clock"]={ 0x1F555 }, ["six-thirty"]={ 0x1F561 }, - ["skier"]={ 0x26F7 }, + ["skateboard"]={ 0x1F6F9 }, + ["skier"]={ 0x26F7, 0xFE0F }, ["skis"]={ 0x1F3BF }, ["skull"]={ 0x1F480 }, - ["skull and crossbones"]={ 0x2620 }, + ["skull and crossbones"]={ 0x2620, 0xFE0F }, + ["skunk"]={ 0x1F9A8 }, ["sled"]={ 0x1F6F7 }, ["sleeping face"]={ 0x1F634 }, ["sleepy face"]={ 0x1F62A }, ["slightly frowning face"]={ 0x1F641 }, ["slightly smiling face"]={ 0x1F642 }, ["slot machine"]={ 0x1F3B0 }, - ["slovakia"]={ 0x1F1F8, 0x1F1F0 }, - ["slovenia"]={ 0x1F1F8, 0x1F1EE }, - ["small airplane"]={ 0x1F6E9 }, + ["sloth"]={ 0x1F9A5 }, + ["small airplane"]={ 0x1F6E9, 0xFE0F }, ["small blue diamond"]={ 0x1F539 }, ["small orange diamond"]={ 0x1F538 }, - ["smiling cat face with heart-eyes"]={ 0x1F63B }, - ["smiling cat face with open mouth"]={ 0x1F63A }, - ["smiling face"]={ 0x263A }, + ["smiling cat with heart-eyes"]={ 0x1F63B }, + ["smiling face"]={ 0x263A, 0xFE0F }, ["smiling face with halo"]={ 0x1F607 }, ["smiling face with heart-eyes"]={ 0x1F60D }, + ["smiling face with hearts"]={ 0x1F970 }, ["smiling face with horns"]={ 0x1F608 }, - ["smiling face with open mouth"]={ 0x1F603 }, - ["smiling face with open mouth & closed eyes"]={ 0x1F606 }, - ["smiling face with open mouth & cold sweat"]={ 0x1F605 }, - ["smiling face with open mouth & smiling eyes"]={ 0x1F604 }, ["smiling face with smiling eyes"]={ 0x1F60A }, ["smiling face with sunglasses"]={ 0x1F60E }, ["smirking face"]={ 0x1F60F }, ["snail"]={ 0x1F40C }, ["snake"]={ 0x1F40D }, ["sneezing face"]={ 0x1F927 }, - ["snow-capped mountain"]={ 0x1F3D4 }, + ["snow-capped mountain"]={ 0x1F3D4, 0xFE0F }, ["snowboarder"]={ 0x1F3C2 }, ["snowboarder: dark skin tone"]={ 0x1F3C2, 0x1F3FF }, ["snowboarder: light skin tone"]={ 0x1F3C2, 0x1F3FB }, ["snowboarder: medium skin tone"]={ 0x1F3C2, 0x1F3FD }, ["snowboarder: medium-dark skin tone"]={ 0x1F3C2, 0x1F3FE }, ["snowboarder: medium-light skin tone"]={ 0x1F3C2, 0x1F3FC }, - ["snowflake"]={ 0x2744 }, - ["snowman"]={ 0x2603 }, + ["snowflake"]={ 0x2744, 0xFE0F }, + ["snowman"]={ 0x2603, 0xFE0F }, ["snowman without snow"]={ 0x26C4 }, + ["soap"]={ 0x1F9FC }, ["soccer ball"]={ 0x26BD }, ["socks"]={ 0x1F9E6 }, ["soft ice cream"]={ 0x1F366 }, - ["solomon islands"]={ 0x1F1F8, 0x1F1E7 }, - ["somalia"]={ 0x1F1F8, 0x1F1F4 }, + ["softball"]={ 0x1F94E }, ["soon arrow"]={ 0x1F51C }, ["sos button"]={ 0x1F198 }, - ["south africa"]={ 0x1F1FF, 0x1F1E6 }, - ["south georgia & south sandwich islands"]={ 0x1F1EC, 0x1F1F8 }, - ["south korea"]={ 0x1F1F0, 0x1F1F7 }, - ["south sudan"]={ 0x1F1F8, 0x1F1F8 }, - ["spade suit"]={ 0x2660 }, + ["spade suit"]={ 0x2660, 0xFE0F }, ["spaghetti"]={ 0x1F35D }, - ["spain"]={ 0x1F1EA, 0x1F1F8 }, - ["sparkle"]={ 0x2747 }, + ["sparkle"]={ 0x2747, 0xFE0F }, ["sparkler"]={ 0x1F387 }, ["sparkles"]={ 0x2728 }, ["sparkling heart"]={ 0x1F496 }, @@ -2018,79 +2316,79 @@ return { ["speaker high volume"]={ 0x1F50A }, ["speaker low volume"]={ 0x1F508 }, ["speaker medium volume"]={ 0x1F509 }, - ["speaking head"]={ 0x1F5E3 }, + ["speaking head"]={ 0x1F5E3, 0xFE0F }, ["speech balloon"]={ 0x1F4AC }, ["speedboat"]={ 0x1F6A4 }, - ["spider"]={ 0x1F577 }, - ["spider web"]={ 0x1F578 }, - ["spiral calendar"]={ 0x1F5D3 }, - ["spiral notepad"]={ 0x1F5D2 }, + ["spider"]={ 0x1F577, 0xFE0F }, + ["spider web"]={ 0x1F578, 0xFE0F }, + ["spiral calendar"]={ 0x1F5D3, 0xFE0F }, + ["spiral notepad"]={ 0x1F5D2, 0xFE0F }, ["spiral shell"]={ 0x1F41A }, + ["sponge"]={ 0x1F9FD }, ["spoon"]={ 0x1F944 }, ["sport utility vehicle"]={ 0x1F699 }, ["sports medal"]={ 0x1F3C5 }, ["spouting whale"]={ 0x1F433 }, ["squid"]={ 0x1F991 }, - ["sri lanka"]={ 0x1F1F1, 0x1F1F0 }, - ["st. barthélemy"]={ 0x1F1E7, 0x1F1F1 }, - ["st. helena"]={ 0x1F1F8, 0x1F1ED }, - ["st. kitts & nevis"]={ 0x1F1F0, 0x1F1F3 }, - ["st. lucia"]={ 0x1F1F1, 0x1F1E8 }, - ["st. martin"]={ 0x1F1F2, 0x1F1EB }, - ["st. pierre & miquelon"]={ 0x1F1F5, 0x1F1F2 }, - ["st. vincent & grenadines"]={ 0x1F1FB, 0x1F1E8 }, - ["stadium"]={ 0x1F3DF }, - ["star and crescent"]={ 0x262A }, - ["star of david"]={ 0x2721 }, + ["squinting face with tongue"]={ 0x1F61D }, + ["stadium"]={ 0x1F3DF, 0xFE0F }, + ["star"]={ 0x2B50 }, + ["star and crescent"]={ 0x262A, 0xFE0F }, + ["star of david"]={ 0x2721, 0xFE0F }, ["star-struck"]={ 0x1F929 }, ["station"]={ 0x1F689 }, ["statue of liberty"]={ 0x1F5FD }, ["steaming bowl"]={ 0x1F35C }, - ["stop button"]={ 0x23F9 }, + ["stethoscope"]={ 0x1FA7A }, + ["stop button"]={ 0x23F9, 0xFE0F }, ["stop sign"]={ 0x1F6D1 }, - ["stopwatch"]={ 0x23F1 }, + ["stopwatch"]={ 0x23F1, 0xFE0F }, ["straight ruler"]={ 0x1F4CF }, ["strawberry"]={ 0x1F353 }, - ["studio microphone"]={ 0x1F399 }, + ["studio microphone"]={ 0x1F399, 0xFE0F }, ["stuffed flatbread"]={ 0x1F959 }, - ["sudan"]={ 0x1F1F8, 0x1F1E9 }, - ["sun"]={ 0x2600 }, + ["sun"]={ 0x2600, 0xFE0F }, ["sun behind cloud"]={ 0x26C5 }, - ["sun behind large cloud"]={ 0x1F325 }, - ["sun behind rain cloud"]={ 0x1F326 }, - ["sun behind small cloud"]={ 0x1F324 }, + ["sun behind large cloud"]={ 0x1F325, 0xFE0F }, + ["sun behind rain cloud"]={ 0x1F326, 0xFE0F }, + ["sun behind small cloud"]={ 0x1F324, 0xFE0F }, ["sun with face"]={ 0x1F31E }, ["sunflower"]={ 0x1F33B }, - ["sunglasses"]={ 0x1F576 }, + ["sunglasses"]={ 0x1F576, 0xFE0F }, ["sunrise"]={ 0x1F305 }, ["sunrise over mountains"]={ 0x1F304 }, ["sunset"]={ 0x1F307 }, - ["suriname"]={ 0x1F1F8, 0x1F1F7 }, + ["superhero"]={ 0x1F9B8 }, + ["superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF }, + ["superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB }, + ["superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD }, + ["superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE }, + ["superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC }, + ["supervillain"]={ 0x1F9B9 }, + ["supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF }, + ["supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB }, + ["supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD }, + ["supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE }, + ["supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC }, ["sushi"]={ 0x1F363 }, ["suspension railway"]={ 0x1F69F }, - ["svalbard & jan mayen"]={ 0x1F1F8, 0x1F1EF }, - ["swaziland"]={ 0x1F1F8, 0x1F1FF }, + ["swan"]={ 0x1F9A2 }, ["sweat droplets"]={ 0x1F4A6 }, - ["sweden"]={ 0x1F1F8, 0x1F1EA }, - ["switzerland"]={ 0x1F1E8, 0x1F1ED }, + ["swim brief"]={ 0x1FA72 }, ["synagogue"]={ 0x1F54D }, - ["syria"]={ 0x1F1F8, 0x1F1FE }, ["syringe"]={ 0x1F489 }, - ["são tomé & príncipe"]={ 0x1F1F8, 0x1F1F9 }, ["t-rex"]={ 0x1F996 }, ["t-shirt"]={ 0x1F455 }, ["taco"]={ 0x1F32E }, - ["taiwan"]={ 0x1F1F9, 0x1F1FC }, - ["tajikistan"]={ 0x1F1F9, 0x1F1EF }, ["takeout box"]={ 0x1F961 }, ["tanabata tree"]={ 0x1F38B }, ["tangerine"]={ 0x1F34A }, - ["tanzania"]={ 0x1F1F9, 0x1F1FF }, ["taurus"]={ 0x2649 }, ["taxi"]={ 0x1F695 }, ["teacup without handle"]={ 0x1F375 }, ["tear-off calendar"]={ 0x1F4C6 }, - ["telephone"]={ 0x260E }, + ["teddy bear"]={ 0x1F9F8 }, + ["telephone"]={ 0x260E, 0xFE0F }, ["telephone receiver"]={ 0x1F4DE }, ["telescope"]={ 0x1F52D }, ["television"]={ 0x1F4FA }, @@ -2098,10 +2396,11 @@ return { ["ten-thirty"]={ 0x1F565 }, ["tennis"]={ 0x1F3BE }, ["tent"]={ 0x26FA }, - ["thailand"]={ 0x1F1F9, 0x1F1ED }, - ["thermometer"]={ 0x1F321 }, + ["test tube"]={ 0x1F9EA }, + ["thermometer"]={ 0x1F321, 0xFE0F }, ["thinking face"]={ 0x1F914 }, ["thought balloon"]={ 0x1F4AD }, + ["thread"]={ 0x1F9F5 }, ["three o’clock"]={ 0x1F552 }, ["three-thirty"]={ 0x1F55E }, ["thumbs down"]={ 0x1F44E }, @@ -2119,30 +2418,26 @@ return { ["ticket"]={ 0x1F3AB }, ["tiger"]={ 0x1F405 }, ["tiger face"]={ 0x1F42F }, - ["timer clock"]={ 0x23F2 }, - ["timor-leste"]={ 0x1F1F9, 0x1F1F1 }, + ["timer clock"]={ 0x23F2, 0xFE0F }, ["tired face"]={ 0x1F62B }, - ["togo"]={ 0x1F1F9, 0x1F1EC }, ["toilet"]={ 0x1F6BD }, - ["tokelau"]={ 0x1F1F9, 0x1F1F0 }, ["tokyo tower"]={ 0x1F5FC }, ["tomato"]={ 0x1F345 }, - ["tonga"]={ 0x1F1F9, 0x1F1F4 }, ["tongue"]={ 0x1F445 }, + ["toolbox"]={ 0x1F9F0 }, + ["tooth"]={ 0x1F9B7 }, ["top arrow"]={ 0x1F51D }, ["top hat"]={ 0x1F3A9 }, - ["tornado"]={ 0x1F32A }, - ["trackball"]={ 0x1F5B2 }, + ["tornado"]={ 0x1F32A, 0xFE0F }, + ["trackball"]={ 0x1F5B2, 0xFE0F }, ["tractor"]={ 0x1F69C }, - ["trade mark"]={ 0x2122 }, + ["trade mark"]={ 0x2122, 0xFE0F }, ["train"]={ 0x1F686 }, ["tram"]={ 0x1F68A }, ["tram car"]={ 0x1F68B }, ["triangular flag"]={ 0x1F6A9 }, ["triangular ruler"]={ 0x1F4D0 }, ["trident emblem"]={ 0x1F531 }, - ["trinidad & tobago"]={ 0x1F1F9, 0x1F1F9 }, - ["tristan da cunha"]={ 0x1F1F9, 0x1F1E6 }, ["trolleybus"]={ 0x1F68E }, ["trophy"]={ 0x1F3C6 }, ["tropical drink"]={ 0x1F379 }, @@ -2150,55 +2445,36 @@ return { ["trumpet"]={ 0x1F3BA }, ["tulip"]={ 0x1F337 }, ["tumbler glass"]={ 0x1F943 }, - ["tunisia"]={ 0x1F1F9, 0x1F1F3 }, - ["turkey"]={ 0x1F1F9, 0x1F1F7 }, - ["turkmenistan"]={ 0x1F1F9, 0x1F1F2 }, - ["turks & caicos islands"]={ 0x1F1F9, 0x1F1E8 }, + ["turkey"]={ 0x1F983 }, ["turtle"]={ 0x1F422 }, - ["tuvalu"]={ 0x1F1F9, 0x1F1FB }, ["twelve o’clock"]={ 0x1F55B }, ["twelve-thirty"]={ 0x1F567 }, ["two hearts"]={ 0x1F495 }, - ["two men holding hands"]={ 0x1F46C }, ["two o’clock"]={ 0x1F551 }, - ["two women holding hands"]={ 0x1F46D }, ["two-hump camel"]={ 0x1F42B }, ["two-thirty"]={ 0x1F55D }, - ["u.s. outlying islands"]={ 0x1F1FA, 0x1F1F2 }, - ["u.s. virgin islands"]={ 0x1F1FB, 0x1F1EE }, - ["uganda"]={ 0x1F1FA, 0x1F1EC }, - ["ukraine"]={ 0x1F1FA, 0x1F1E6 }, - ["umbrella"]={ 0x2602 }, - ["umbrella on ground"]={ 0x26F1 }, + ["umbrella"]={ 0x2602, 0xFE0F }, + ["umbrella on ground"]={ 0x26F1, 0xFE0F }, ["umbrella with rain drops"]={ 0x2614 }, ["unamused face"]={ 0x1F612 }, - ["unicorn face"]={ 0x1F984 }, - ["united arab emirates"]={ 0x1F1E6, 0x1F1EA }, - ["united kingdom"]={ 0x1F1EC, 0x1F1E7 }, - ["united nations"]={ 0x1F1FA, 0x1F1F3 }, - ["united states"]={ 0x1F1FA, 0x1F1F8 }, + ["unicorn"]={ 0x1F984 }, ["unlocked"]={ 0x1F513 }, - ["up arrow"]={ 0x2B06 }, - ["up button"]={ 0x1F53C }, + ["up arrow"]={ 0x2B06, 0xFE0F }, ["up! button"]={ 0x1F199 }, - ["up-down arrow"]={ 0x2195 }, - ["up-left arrow"]={ 0x2196 }, - ["up-right arrow"]={ 0x2197 }, + ["up-down arrow"]={ 0x2195, 0xFE0F }, + ["up-left arrow"]={ 0x2196, 0xFE0F }, + ["up-right arrow"]={ 0x2197, 0xFE0F }, ["upside-down face"]={ 0x1F643 }, - ["uruguay"]={ 0x1F1FA, 0x1F1FE }, - ["uzbekistan"]={ 0x1F1FA, 0x1F1FF }, + ["upwards button"]={ 0x1F53C }, ["vampire"]={ 0x1F9DB }, ["vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF }, ["vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB }, ["vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD }, ["vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE }, ["vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC }, - ["vanuatu"]={ 0x1F1FB, 0x1F1FA }, - ["vatican city"]={ 0x1F1FB, 0x1F1E6 }, - ["venezuela"]={ 0x1F1FB, 0x1F1EA }, ["vertical traffic light"]={ 0x1F6A6 }, ["vibration mode"]={ 0x1F4F3 }, - ["victory hand"]={ 0x270C }, + ["victory hand"]={ 0x270C, 0xFE0F }, ["victory hand: dark skin tone"]={ 0x270C, 0x1F3FF }, ["victory hand: light skin tone"]={ 0x270C, 0x1F3FB }, ["victory hand: medium skin tone"]={ 0x270C, 0x1F3FD }, @@ -2207,7 +2483,6 @@ return { ["video camera"]={ 0x1F4F9 }, ["video game"]={ 0x1F3AE }, ["videocassette"]={ 0x1F4FC }, - ["vietnam"]={ 0x1F1FB, 0x1F1F3 }, ["violin"]={ 0x1F3BB }, ["virgo"]={ 0x264D }, ["volcano"]={ 0x1F30B }, @@ -2219,12 +2494,11 @@ return { ["vulcan salute: medium skin tone"]={ 0x1F596, 0x1F3FD }, ["vulcan salute: medium-dark skin tone"]={ 0x1F596, 0x1F3FE }, ["vulcan salute: medium-light skin tone"]={ 0x1F596, 0x1F3FC }, - ["wales"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0077, 0xE006C, 0xE0073, 0xE007F }, - ["wallis & futuna"]={ 0x1F1FC, 0x1F1EB }, + ["waffle"]={ 0x1F9C7 }, ["waning crescent moon"]={ 0x1F318 }, ["waning gibbous moon"]={ 0x1F316 }, - ["warning"]={ 0x26A0 }, - ["wastebasket"]={ 0x1F5D1 }, + ["warning"]={ 0x26A0, 0xFE0F }, + ["wastebasket"]={ 0x1F5D1, 0xFE0F }, ["watch"]={ 0x231A }, ["water buffalo"]={ 0x1F403 }, ["water closet"]={ 0x1F6BE }, @@ -2236,35 +2510,60 @@ return { ["waving hand: medium skin tone"]={ 0x1F44B, 0x1F3FD }, ["waving hand: medium-dark skin tone"]={ 0x1F44B, 0x1F3FE }, ["waving hand: medium-light skin tone"]={ 0x1F44B, 0x1F3FC }, - ["wavy dash"]={ 0x3030 }, + ["wavy dash"]={ 0x3030, 0xFE0F }, ["waxing crescent moon"]={ 0x1F312 }, ["waxing gibbous moon"]={ 0x1F314 }, - ["weary cat face"]={ 0x1F640 }, + ["weary cat"]={ 0x1F640 }, ["weary face"]={ 0x1F629 }, ["wedding"]={ 0x1F492 }, - ["western sahara"]={ 0x1F1EA, 0x1F1ED }, ["whale"]={ 0x1F40B }, - ["wheel of dharma"]={ 0x2638 }, + ["wheel of dharma"]={ 0x2638, 0xFE0F }, ["wheelchair symbol"]={ 0x267F }, ["white circle"]={ 0x26AA }, ["white exclamation mark"]={ 0x2755 }, - ["white flag"]={ 0x1F3F3 }, + ["white flag"]={ 0x1F3F3, 0xFE0F }, ["white flower"]={ 0x1F4AE }, - ["white heavy check mark"]={ 0x2705 }, + ["white heart"]={ 0x1F90D }, ["white large square"]={ 0x2B1C }, - ["white medium square"]={ 0x25FB }, - ["white medium star"]={ 0x2B50 }, + ["white medium square"]={ 0x25FB, 0xFE0F }, ["white medium-small square"]={ 0x25FD }, ["white question mark"]={ 0x2754 }, - ["white small square"]={ 0x25AB }, + ["white small square"]={ 0x25AB, 0xFE0F }, ["white square button"]={ 0x1F533 }, ["wilted flower"]={ 0x1F940 }, ["wind chime"]={ 0x1F390 }, - ["wind face"]={ 0x1F32C }, + ["wind face"]={ 0x1F32C, 0xFE0F }, ["wine glass"]={ 0x1F377 }, ["winking face"]={ 0x1F609 }, - ["wolf face"]={ 0x1F43A }, + ["winking face with tongue"]={ 0x1F61C }, + ["wolf"]={ 0x1F43A }, ["woman"]={ 0x1F469 }, + ["woman and man holding hands"]={ 0x1F46B }, + ["woman and man holding hands: dark skin tone"]={ 0x1F46B, 0x1F3FF }, + ["woman and man holding hands: dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["woman and man holding hands: dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["woman and man holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["woman and man holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["woman and man holding hands: light skin tone"]={ 0x1F46B, 0x1F3FB }, + ["woman and man holding hands: light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["woman and man holding hands: light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["woman and man holding hands: light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["woman and man holding hands: light skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["woman and man holding hands: medium skin tone"]={ 0x1F46B, 0x1F3FD }, + ["woman and man holding hands: medium skin tone, dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["woman and man holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["woman and man holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["woman and man holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["woman and man holding hands: medium-dark skin tone"]={ 0x1F46B, 0x1F3FE }, + ["woman and man holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["woman and man holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["woman and man holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["woman and man holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, + ["woman and man holding hands: medium-light skin tone"]={ 0x1F46B, 0x1F3FC }, + ["woman and man holding hands: medium-light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["woman and man holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["woman and man holding hands: medium-light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["woman and man holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["woman artist"]={ 0x1F469, 0x200D, 0x1F3A8 }, ["woman artist: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3A8 }, ["woman artist: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3A8 }, @@ -2277,42 +2576,42 @@ return { ["woman astronaut: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F680 }, ["woman astronaut: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F680 }, ["woman astronaut: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F680 }, - ["woman biking"]={ 0x1F6B4, 0x200D, 0x2640 }, - ["woman biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2640 }, - ["woman biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2640 }, - ["woman biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2640 }, - ["woman biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2640 }, - ["woman biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2640 }, - ["woman bouncing ball"]={ 0x26F9, 0x200D, 0x2640 }, - ["woman bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2640 }, - ["woman bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2640 }, - ["woman bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2640 }, - ["woman bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2640 }, - ["woman bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2640 }, - ["woman bowing"]={ 0x1F647, 0x200D, 0x2640 }, - ["woman bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2640 }, - ["woman bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2640 }, - ["woman bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2640 }, - ["woman bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2640 }, - ["woman bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2640 }, - ["woman cartwheeling"]={ 0x1F938, 0x200D, 0x2640 }, - ["woman cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2640 }, - ["woman cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2640 }, - ["woman cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2640 }, - ["woman cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2640 }, - ["woman cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2640 }, - ["woman climbing"]={ 0x1F9D7, 0x200D, 0x2640 }, - ["woman climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2640 }, - ["woman climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2640 }, - ["woman climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2640 }, - ["woman climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2640 }, - ["woman climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2640 }, - ["woman construction worker"]={ 0x1F477, 0x200D, 0x2640 }, - ["woman construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2640 }, - ["woman construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2640 }, - ["woman construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2640 }, - ["woman construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2640 }, - ["woman construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2640 }, + ["woman biking"]={ 0x1F6B4, 0x200D, 0x2640, 0xFE0F }, + ["woman biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball"]={ 0x26F9, 0xFE0F, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing"]={ 0x1F647, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling"]={ 0x1F938, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing"]={ 0x1F9D7, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker"]={ 0x1F477, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman cook"]={ 0x1F469, 0x200D, 0x1F373 }, ["woman cook: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F373 }, ["woman cook: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F373 }, @@ -2325,36 +2624,36 @@ return { ["woman dancing: medium skin tone"]={ 0x1F483, 0x1F3FD }, ["woman dancing: medium-dark skin tone"]={ 0x1F483, 0x1F3FE }, ["woman dancing: medium-light skin tone"]={ 0x1F483, 0x1F3FC }, - ["woman detective"]={ 0x1F575, 0x200D, 0x2640 }, - ["woman detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2640 }, - ["woman detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2640 }, - ["woman detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2640 }, - ["woman detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2640 }, - ["woman detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2640 }, - ["woman elf"]={ 0x1F9DD, 0x200D, 0x2640 }, - ["woman elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2640 }, - ["woman elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2640 }, - ["woman elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2640 }, - ["woman elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2640 }, - ["woman elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2640 }, - ["woman facepalming"]={ 0x1F926, 0x200D, 0x2640 }, - ["woman facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2640 }, - ["woman facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2640 }, - ["woman facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2640 }, - ["woman facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2640 }, - ["woman facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2640 }, + ["woman detective"]={ 0x1F575, 0xFE0F, 0x200D, 0x2640, 0xFE0F }, + ["woman detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman elf"]={ 0x1F9DD, 0x200D, 0x2640, 0xFE0F }, + ["woman elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming"]={ 0x1F926, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman factory worker"]={ 0x1F469, 0x200D, 0x1F3ED }, ["woman factory worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3ED }, ["woman factory worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3ED }, ["woman factory worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F3ED }, ["woman factory worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F3ED }, ["woman factory worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F3ED }, - ["woman fairy"]={ 0x1F9DA, 0x200D, 0x2640 }, - ["woman fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2640 }, - ["woman fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2640 }, - ["woman fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2640 }, - ["woman fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2640 }, - ["woman fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2640 }, + ["woman fairy"]={ 0x1F9DA, 0x200D, 0x2640, 0xFE0F }, + ["woman fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman farmer"]={ 0x1F469, 0x200D, 0x1F33E }, ["woman farmer: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F33E }, ["woman farmer: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F33E }, @@ -2367,193 +2666,229 @@ return { ["woman firefighter: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F692 }, ["woman firefighter: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F692 }, ["woman firefighter: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F692 }, - ["woman frowning"]={ 0x1F64D, 0x200D, 0x2640 }, - ["woman frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2640 }, - ["woman frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2640 }, - ["woman frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2640 }, - ["woman frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2640 }, - ["woman frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2640 }, - ["woman genie"]={ 0x1F9DE, 0x200D, 0x2640 }, - ["woman gesturing no"]={ 0x1F645, 0x200D, 0x2640 }, - ["woman gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2640 }, - ["woman gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2640 }, - ["woman gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2640 }, - ["woman gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2640 }, - ["woman gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2640 }, - ["woman gesturing ok"]={ 0x1F646, 0x200D, 0x2640 }, - ["woman gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2640 }, - ["woman gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2640 }, - ["woman gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2640 }, - ["woman gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2640 }, - ["woman gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2640 }, - ["woman getting haircut"]={ 0x1F487, 0x200D, 0x2640 }, - ["woman getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2640 }, - ["woman getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2640 }, - ["woman getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2640 }, - ["woman getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2640 }, - ["woman getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2640 }, - ["woman getting massage"]={ 0x1F486, 0x200D, 0x2640 }, - ["woman getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2640 }, - ["woman getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2640 }, - ["woman getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2640 }, - ["woman getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2640 }, - ["woman getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2640 }, - ["woman golfing"]={ 0x1F3CC, 0x200D, 0x2640 }, - ["woman golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2640 }, - ["woman golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2640 }, - ["woman golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2640 }, - ["woman golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2640 }, - ["woman golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2640 }, - ["woman guard"]={ 0x1F482, 0x200D, 0x2640 }, - ["woman guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2640 }, - ["woman guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2640 }, - ["woman guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2640 }, - ["woman guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2640 }, - ["woman guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2640 }, - ["woman health worker"]={ 0x1F469, 0x200D, 0x2695 }, - ["woman health worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2695 }, - ["woman health worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2695 }, - ["woman health worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2695 }, - ["woman health worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2695 }, - ["woman health worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2695 }, - ["woman in lotus position"]={ 0x1F9D8, 0x200D, 0x2640 }, - ["woman in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2640 }, - ["woman in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2640 }, - ["woman in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2640 }, - ["woman in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2640 }, - ["woman in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2640 }, - ["woman in steamy room"]={ 0x1F9D6, 0x200D, 0x2640 }, - ["woman in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2640 }, - ["woman in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2640 }, - ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640 }, - ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640 }, - ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640 }, - ["woman judge"]={ 0x1F469, 0x200D, 0x2696 }, - ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696 }, - ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696 }, - ["woman judge: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2696 }, - ["woman judge: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2696 }, - ["woman judge: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2696 }, - ["woman juggling"]={ 0x1F939, 0x200D, 0x2640 }, - ["woman juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2640 }, - ["woman juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2640 }, - ["woman juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2640 }, - ["woman juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2640 }, - ["woman juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2640 }, - ["woman lifting weights"]={ 0x1F3CB, 0x200D, 0x2640 }, - ["woman lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2640 }, - ["woman lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2640 }, - ["woman lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2640 }, - ["woman lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2640 }, - ["woman lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2640 }, - ["woman mage"]={ 0x1F9D9, 0x200D, 0x2640 }, - ["woman mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2640 }, - ["woman mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2640 }, - ["woman mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2640 }, - ["woman mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2640 }, - ["woman mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2640 }, + ["woman frowning"]={ 0x1F64D, 0x200D, 0x2640, 0xFE0F }, + ["woman frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman genie"]={ 0x1F9DE, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no"]={ 0x1F645, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok"]={ 0x1F646, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut"]={ 0x1F487, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage"]={ 0x1F486, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing"]={ 0x1F3CC, 0xFE0F, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman guard"]={ 0x1F482, 0x200D, 0x2640, 0xFE0F }, + ["woman guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman health worker"]={ 0x1F469, 0x200D, 0x2695, 0xFE0F }, + ["woman health worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2695, 0xFE0F }, + ["woman health worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2695, 0xFE0F }, + ["woman health worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2695, 0xFE0F }, + ["woman health worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2695, 0xFE0F }, + ["woman health worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2695, 0xFE0F }, + ["woman in lotus position"]={ 0x1F9D8, 0x200D, 0x2640, 0xFE0F }, + ["woman in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman in manual wheelchair"]={ 0x1F469, 0x200D, 0x1F9BD }, + ["woman in manual wheelchair: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9BD }, + ["woman in manual wheelchair: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9BD }, + ["woman in manual wheelchair: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9BD }, + ["woman in manual wheelchair: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9BD }, + ["woman in manual wheelchair: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9BD }, + ["woman in motorized wheelchair"]={ 0x1F469, 0x200D, 0x1F9BC }, + ["woman in motorized wheelchair: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9BC }, + ["woman in motorized wheelchair: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9BC }, + ["woman in motorized wheelchair: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9BC }, + ["woman in motorized wheelchair: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9BC }, + ["woman in motorized wheelchair: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9BC }, + ["woman in steamy room"]={ 0x1F9D6, 0x200D, 0x2640, 0xFE0F }, + ["woman in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman judge"]={ 0x1F469, 0x200D, 0x2696, 0xFE0F }, + ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, + ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, + ["woman judge: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2696, 0xFE0F }, + ["woman judge: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2696, 0xFE0F }, + ["woman judge: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2696, 0xFE0F }, + ["woman juggling"]={ 0x1F939, 0x200D, 0x2640, 0xFE0F }, + ["woman juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling"]={ 0x1F9CE, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights"]={ 0x1F3CB, 0xFE0F, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman mage"]={ 0x1F9D9, 0x200D, 0x2640, 0xFE0F }, + ["woman mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman mechanic"]={ 0x1F469, 0x200D, 0x1F527 }, ["woman mechanic: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F527 }, ["woman mechanic: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F527 }, ["woman mechanic: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F527 }, ["woman mechanic: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F527 }, ["woman mechanic: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F527 }, - ["woman mountain biking"]={ 0x1F6B5, 0x200D, 0x2640 }, - ["woman mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2640 }, - ["woman mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2640 }, - ["woman mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2640 }, - ["woman mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2640 }, - ["woman mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2640 }, + ["woman mountain biking"]={ 0x1F6B5, 0x200D, 0x2640, 0xFE0F }, + ["woman mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman office worker"]={ 0x1F469, 0x200D, 0x1F4BC }, ["woman office worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F4BC }, ["woman office worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F4BC }, ["woman office worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F4BC }, ["woman office worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F4BC }, ["woman office worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F4BC }, - ["woman pilot"]={ 0x1F469, 0x200D, 0x2708 }, - ["woman pilot: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2708 }, - ["woman pilot: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2708 }, - ["woman pilot: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2708 }, - ["woman pilot: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2708 }, - ["woman pilot: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2708 }, - ["woman playing handball"]={ 0x1F93E, 0x200D, 0x2640 }, - ["woman playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2640 }, - ["woman playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2640 }, - ["woman playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2640 }, - ["woman playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2640 }, - ["woman playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2640 }, - ["woman playing water polo"]={ 0x1F93D, 0x200D, 0x2640 }, - ["woman playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2640 }, - ["woman playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2640 }, - ["woman playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2640 }, - ["woman playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2640 }, - ["woman playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2640 }, - ["woman police officer"]={ 0x1F46E, 0x200D, 0x2640 }, - ["woman police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2640 }, - ["woman police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2640 }, - ["woman police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2640 }, - ["woman police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2640 }, - ["woman police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2640 }, - ["woman pouting"]={ 0x1F64E, 0x200D, 0x2640 }, - ["woman pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2640 }, - ["woman pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2640 }, - ["woman pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2640 }, - ["woman pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2640 }, - ["woman pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2640 }, - ["woman raising hand"]={ 0x1F64B, 0x200D, 0x2640 }, - ["woman raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2640 }, - ["woman raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2640 }, - ["woman raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2640 }, - ["woman raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2640 }, - ["woman raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2640 }, - ["woman rowing boat"]={ 0x1F6A3, 0x200D, 0x2640 }, - ["woman rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2640 }, - ["woman rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2640 }, - ["woman rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2640 }, - ["woman rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2640 }, - ["woman rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2640 }, - ["woman running"]={ 0x1F3C3, 0x200D, 0x2640 }, - ["woman running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2640 }, - ["woman running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2640 }, - ["woman running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2640 }, - ["woman running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2640 }, - ["woman running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2640 }, + ["woman pilot"]={ 0x1F469, 0x200D, 0x2708, 0xFE0F }, + ["woman pilot: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2708, 0xFE0F }, + ["woman pilot: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2708, 0xFE0F }, + ["woman pilot: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2708, 0xFE0F }, + ["woman pilot: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2708, 0xFE0F }, + ["woman pilot: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2708, 0xFE0F }, + ["woman playing handball"]={ 0x1F93E, 0x200D, 0x2640, 0xFE0F }, + ["woman playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo"]={ 0x1F93D, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer"]={ 0x1F46E, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting"]={ 0x1F64E, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand"]={ 0x1F64B, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat"]={ 0x1F6A3, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman running"]={ 0x1F3C3, 0x200D, 0x2640, 0xFE0F }, + ["woman running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman scientist"]={ 0x1F469, 0x200D, 0x1F52C }, ["woman scientist: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F52C }, ["woman scientist: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F52C }, ["woman scientist: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F52C }, ["woman scientist: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F52C }, ["woman scientist: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F52C }, - ["woman shrugging"]={ 0x1F937, 0x200D, 0x2640 }, - ["woman shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2640 }, - ["woman shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2640 }, - ["woman shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2640 }, - ["woman shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2640 }, - ["woman shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2640 }, + ["woman shrugging"]={ 0x1F937, 0x200D, 0x2640, 0xFE0F }, + ["woman shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman singer"]={ 0x1F469, 0x200D, 0x1F3A4 }, ["woman singer: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3A4 }, ["woman singer: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3A4 }, ["woman singer: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F3A4 }, ["woman singer: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F3A4 }, ["woman singer: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F3A4 }, + ["woman standing"]={ 0x1F9CD, 0x200D, 0x2640, 0xFE0F }, + ["woman standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman standing: light skin tone"]={ 0x1F9CD, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman student"]={ 0x1F469, 0x200D, 0x1F393 }, ["woman student: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F393 }, ["woman student: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F393 }, ["woman student: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F393 }, ["woman student: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F393 }, ["woman student: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F393 }, - ["woman surfing"]={ 0x1F3C4, 0x200D, 0x2640 }, - ["woman surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2640 }, - ["woman surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2640 }, - ["woman surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2640 }, - ["woman surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2640 }, - ["woman surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2640 }, - ["woman swimming"]={ 0x1F3CA, 0x200D, 0x2640 }, - ["woman swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2640 }, - ["woman swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2640 }, - ["woman swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2640 }, - ["woman swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2640 }, - ["woman swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2640 }, + ["woman superhero"]={ 0x1F9B8, 0x200D, 0x2640, 0xFE0F }, + ["woman superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain"]={ 0x1F9B9, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing"]={ 0x1F3C4, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming"]={ 0x1F3CA, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman teacher"]={ 0x1F469, 0x200D, 0x1F3EB }, ["woman teacher: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3EB }, ["woman teacher: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3EB }, @@ -2566,68 +2901,123 @@ return { ["woman technologist: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F4BB }, ["woman technologist: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F4BB }, ["woman technologist: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F4BB }, - ["woman tipping hand"]={ 0x1F481, 0x200D, 0x2640 }, - ["woman tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2640 }, - ["woman tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2640 }, - ["woman tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2640 }, - ["woman tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2640 }, - ["woman tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2640 }, - ["woman vampire"]={ 0x1F9DB, 0x200D, 0x2640 }, - ["woman vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2640 }, - ["woman vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2640 }, - ["woman vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2640 }, - ["woman vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2640 }, - ["woman vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2640 }, - ["woman walking"]={ 0x1F6B6, 0x200D, 0x2640 }, - ["woman walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2640 }, - ["woman walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2640 }, - ["woman walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2640 }, - ["woman walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2640 }, - ["woman walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2640 }, - ["woman wearing turban"]={ 0x1F473, 0x200D, 0x2640 }, - ["woman wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2640 }, - ["woman wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2640 }, - ["woman wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2640 }, - ["woman wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2640 }, - ["woman wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2640 }, + ["woman tipping hand"]={ 0x1F481, 0x200D, 0x2640, 0xFE0F }, + ["woman tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire"]={ 0x1F9DB, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman walking"]={ 0x1F6B6, 0x200D, 0x2640, 0xFE0F }, + ["woman walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban"]={ 0x1F473, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman with headscarf"]={ 0x1F9D5 }, ["woman with headscarf: dark skin tone"]={ 0x1F9D5, 0x1F3FF }, ["woman with headscarf: light skin tone"]={ 0x1F9D5, 0x1F3FB }, ["woman with headscarf: medium skin tone"]={ 0x1F9D5, 0x1F3FD }, ["woman with headscarf: medium-dark skin tone"]={ 0x1F9D5, 0x1F3FE }, ["woman with headscarf: medium-light skin tone"]={ 0x1F9D5, 0x1F3FC }, - ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640 }, + ["woman with probing cane"]={ 0x1F469, 0x200D, 0x1F9AF }, + ["woman with probing cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF }, + ["woman with probing cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF }, + ["woman with probing cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF }, + ["woman with probing cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF }, + ["woman with probing cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF }, + ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640, 0xFE0F }, + ["woman: bald"]={ 0x1F469, 0x200D, 0x1F9B2 }, + ["woman: blond hair"]={ 0x1F471, 0x200D, 0x2640, 0xFE0F }, + ["woman: curly hair"]={ 0x1F469, 0x200D, 0x1F9B1 }, ["woman: dark skin tone"]={ 0x1F469, 0x1F3FF }, + ["woman: dark skin tone, bald"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B2 }, + ["woman: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman: dark skin tone, curly hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B1 }, + ["woman: dark skin tone, red hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B0 }, + ["woman: dark skin tone, white hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B3 }, ["woman: light skin tone"]={ 0x1F469, 0x1F3FB }, + ["woman: light skin tone, bald"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B2 }, + ["woman: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman: light skin tone, curly hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B1 }, + ["woman: light skin tone, red hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B0 }, + ["woman: light skin tone, white hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B3 }, ["woman: medium skin tone"]={ 0x1F469, 0x1F3FD }, + ["woman: medium skin tone, bald"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B2 }, + ["woman: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman: medium skin tone, curly hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B1 }, + ["woman: medium skin tone, red hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B0 }, + ["woman: medium skin tone, white hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B3 }, ["woman: medium-dark skin tone"]={ 0x1F469, 0x1F3FE }, + ["woman: medium-dark skin tone, bald"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B2 }, + ["woman: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman: medium-dark skin tone, curly hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B1 }, + ["woman: medium-dark skin tone, red hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B0 }, + ["woman: medium-dark skin tone, white hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B3 }, ["woman: medium-light skin tone"]={ 0x1F469, 0x1F3FC }, + ["woman: medium-light skin tone, bald"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B2 }, + ["woman: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman: medium-light skin tone, curly hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B1 }, + ["woman: medium-light skin tone, red hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B0 }, + ["woman: medium-light skin tone, white hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B3 }, + ["woman: red hair"]={ 0x1F469, 0x200D, 0x1F9B0 }, + ["woman: white hair"]={ 0x1F469, 0x200D, 0x1F9B3 }, ["woman’s boot"]={ 0x1F462 }, ["woman’s clothes"]={ 0x1F45A }, ["woman’s hat"]={ 0x1F452 }, ["woman’s sandal"]={ 0x1F461 }, - ["women with bunny ears partying"]={ 0x1F46F, 0x200D, 0x2640 }, - ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640 }, + ["women holding hands"]={ 0x1F46D }, + ["women holding hands: dark skin tone"]={ 0x1F46D, 0x1F3FF }, + ["women holding hands: dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, + ["women holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, + ["women holding hands: light skin tone"]={ 0x1F46D, 0x1F3FB }, + ["women holding hands: medium skin tone"]={ 0x1F46D, 0x1F3FD }, + ["women holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, + ["women holding hands: medium-dark skin tone"]={ 0x1F46D, 0x1F3FE }, + ["women holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, + ["women holding hands: medium-light skin tone"]={ 0x1F46D, 0x1F3FC }, + ["women holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women with bunny ears"]={ 0x1F46F, 0x200D, 0x2640, 0xFE0F }, + ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640, 0xFE0F }, ["women’s room"]={ 0x1F6BA }, - ["world map"]={ 0x1F5FA }, + ["woozy face"]={ 0x1F974 }, + ["world map"]={ 0x1F5FA, 0xFE0F }, ["worried face"]={ 0x1F61F }, ["wrapped gift"]={ 0x1F381 }, ["wrench"]={ 0x1F527 }, - ["writing hand"]={ 0x270D }, + ["writing hand"]={ 0x270D, 0xFE0F }, ["writing hand: dark skin tone"]={ 0x270D, 0x1F3FF }, ["writing hand: light skin tone"]={ 0x270D, 0x1F3FB }, ["writing hand: medium skin tone"]={ 0x270D, 0x1F3FD }, ["writing hand: medium-dark skin tone"]={ 0x270D, 0x1F3FE }, ["writing hand: medium-light skin tone"]={ 0x270D, 0x1F3FC }, + ["yarn"]={ 0x1F9F6 }, + ["yawning face"]={ 0x1F971 }, + ["yellow circle"]={ 0x1F7E1 }, ["yellow heart"]={ 0x1F49B }, - ["yemen"]={ 0x1F1FE, 0x1F1EA }, + ["yellow square"]={ 0x1F7E8 }, ["yen banknote"]={ 0x1F4B4 }, - ["yin yang"]={ 0x262F }, - ["zambia"]={ 0x1F1FF, 0x1F1F2 }, + ["yin yang"]={ 0x262F, 0xFE0F }, + ["yo-yo"]={ 0x1FA80 }, + ["zany face"]={ 0x1F92A }, ["zebra"]={ 0x1F993 }, - ["zimbabwe"]={ 0x1F1FF, 0x1F1FC }, ["zipper-mouth face"]={ 0x1F910 }, ["zombie"]={ 0x1F9DF }, ["zzz"]={ 0x1F4A4 }, - ["Åland islands"]={ 0x1F1E6, 0x1F1FD }, -} +} \ No newline at end of file diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua index c308a2c0fc6..fb9d9f126e4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-ini.lua @@ -234,6 +234,7 @@ local blocks = allocate { ["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" }, ["cherokee"] = { first = 0x013A0, last = 0x013FF, otf="cher", description = "Cherokee" }, ["cherokeesupplement"] = { first = 0x0AB70, last = 0x0ABBF, description = "Cherokee Supplement" }, + ["chesssymbols"] = { first = 0x1FA00, last = 0x1FA6F, description = "Chess Symbols" }, ["cjkcompatibility"] = { first = 0x03300, last = 0x033FF, otf="hang", description = "CJK Compatibility" }, ["cjkcompatibilityforms"] = { first = 0x0FE30, last = 0x0FE4F, otf="hang", description = "CJK Compatibility Forms" }, ["cjkcompatibilityideographs"] = { first = 0x0F900, last = 0x0FAFF, otf="hang", description = "CJK Compatibility Ideographs" }, @@ -296,6 +297,7 @@ local blocks = allocate { -- ["digitsthai"] = { first = 0x00E50, last = 0x00E59, math = true }, -- ["digitstibetan"] = { first = 0x00F20, last = 0x00F29, math = true }, ["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" }, + ["dogra"] = { first = 0x11800, last = 0x1184F, description = "Dogra" }, ["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" }, ["duployan"] = { first = 0x1BC00, last = 0x1BC9F, description = "Duployan" }, ["earlydynasticcuneiform"] = { first = 0x12480, last = 0x1254F, description = "Early Dynastic Cuneiform" }, @@ -314,6 +316,7 @@ local blocks = allocate { ["geometricshapes"] = { first = 0x025A0, last = 0x025FF, math = true, description = "Geometric Shapes" }, ["geometricshapesextended"] = { first = 0x1F780, last = 0x1F7FF, description = "Geometric Shapes Extended" }, ["georgian"] = { first = 0x010A0, last = 0x010FF, otf="geor", description = "Georgian" }, + ["georgianextended"] = { first = 0x01C90, last = 0x01CBF, description = "Georgian Extended" }, ["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, otf="geor", description = "Georgian Supplement" }, ["glagolitic"] = { first = 0x02C00, last = 0x02C5F, otf="glag", description = "Glagolitic" }, ["glagoliticsupplement"] = { first = 0x1E000, last = 0x1E02F, description = "Glagolitic Supplement" }, @@ -322,6 +325,7 @@ local blocks = allocate { ["greekandcoptic"] = { first = 0x00370, last = 0x003FF, otf="grek", description = "Greek and Coptic" }, ["greekextended"] = { first = 0x01F00, last = 0x01FFF, otf="grek", description = "Greek Extended" }, ["gujarati"] = { first = 0x00A80, last = 0x00AFF, otf="gujr", description = "Gujarati" }, + ["gunjalagondi"] = { first = 0x11D60, last = 0x11DAF, description = "Gunjala Gondi" }, ["gurmukhi"] = { first = 0x00A00, last = 0x00A7F, otf="guru", description = "Gurmukhi" }, ["halfwidthandfullwidthforms"] = { first = 0x0FF00, last = 0x0FFEF, description = "Halfwidth and Fullwidth Forms" }, ["hangulcompatibilityjamo"] = { first = 0x03130, last = 0x0318F, otf="jamo", description = "Hangul Compatibility Jamo" }, @@ -329,6 +333,7 @@ local blocks = allocate { ["hanguljamoextendeda"] = { first = 0x0A960, last = 0x0A97F, description = "Hangul Jamo Extended-A" }, ["hanguljamoextendedb"] = { first = 0x0D7B0, last = 0x0D7FF, description = "Hangul Jamo Extended-B" }, ["hangulsyllables"] = { first = 0x0AC00, last = 0x0D7AF, otf="hang", description = "Hangul Syllables" }, + ["hanifirohingya"] = { first = 0x10D00, last = 0x10D3F, description = "Hanifi Rohingya" }, ["hanunoo"] = { first = 0x01720, last = 0x0173F, otf="hano", description = "Hanunoo" }, ["hatran"] = { first = 0x108E0, last = 0x108FF, description = "Hatran" }, ["hebrew"] = { first = 0x00590, last = 0x005FF, otf="hebr", description = "Hebrew" }, @@ -338,6 +343,7 @@ local blocks = allocate { ["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" }, ["ideographicsymbolsandpunctuation"] = { first = 0x16FE0, last = 0x16FFF, description = "Ideographic Symbols and Punctuation" }, ["imperialaramaic"] = { first = 0x10840, last = 0x1085F, description = "Imperial Aramaic" }, + ["indicsiyaqnumbers"] = { first = 0x1EC70, last = 0x1ECBF, description = "Indic Siyaq Numbers" }, ["inscriptionalpahlavi"] = { first = 0x10B60, last = 0x10B7F, description = "Inscriptional Pahlavi" }, ["inscriptionalparthian"] = { first = 0x10B40, last = 0x10B5F, description = "Inscriptional Parthian" }, ["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" }, @@ -396,6 +402,7 @@ local blocks = allocate { ["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" }, ["mahajani"] = { first = 0x11150, last = 0x1117F, description = "Mahajani" }, ["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" }, + ["makasar"] = { first = 0x11EE0, last = 0x11EFF, description = "Makasar" }, ["malayalam"] = { first = 0x00D00, last = 0x00D7F, otf="mlym", description = "Malayalam" }, ["mandaic"] = { first = 0x00840, last = 0x0085F, otf="mand", description = "Mandaic" }, ["manichaean"] = { first = 0x10AC0, last = 0x10AFF, description = "Manichaean" }, @@ -403,6 +410,8 @@ local blocks = allocate { ["masaramgondi"] = { first = 0x11D00, last = 0x11D5F, description = "Masaram Gondi" }, ["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, math = true, description = "Mathematical Alphanumeric Symbols" }, ["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, math = true, description = "Mathematical Operators" }, + ["mayannumerals"] = { first = 0x1D2E0, last = 0x1D2FF, description = "Mayan Numerals" }, + ["medefaidrin"] = { first = 0x16E40, last = 0x16E9F, description = "Medefaidrin" }, ["meeteimayek"] = { first = 0x0ABC0, last = 0x0ABFF, description = "Meetei Mayek" }, ["meeteimayekextensions"] = { first = 0x0AAE0, last = 0x0AAFF, description = "Meetei Mayek Extensions" }, ["mendekikakui"] = { first = 0x1E800, last = 0x1E8DF, description = "Mende Kikakui" }, @@ -438,6 +447,7 @@ local blocks = allocate { ["oldnortharabian"] = { first = 0x10A80, last = 0x10A9F, description = "Old North Arabian" }, ["oldpermic"] = { first = 0x10350, last = 0x1037F, description = "Old Permic" }, ["oldpersian"] = { first = 0x103A0, last = 0x103DF, otf="xpeo", description = "Old Persian" }, + ["oldsogdian"] = { first = 0x10F00, last = 0x10F2F, description = "Old Sogdian" }, ["oldsoutharabian"] = { first = 0x10A60, last = 0x10A7F, description = "Old South Arabian" }, ["oldturkic"] = { first = 0x10C00, last = 0x10C4F, description = "Old Turkic" }, ["opticalcharacterrecognition"] = { first = 0x02440, last = 0x0245F, description = "Optical Character Recognition" }, @@ -468,6 +478,7 @@ local blocks = allocate { ["sinhala"] = { first = 0x00D80, last = 0x00DFF, otf="sinh", description = "Sinhala" }, ["sinhalaarchaicnumbers"] = { first = 0x111E0, last = 0x111FF, description = "Sinhala Archaic Numbers" }, ["smallformvariants"] = { first = 0x0FE50, last = 0x0FE6F, description = "Small Form Variants" }, + ["sogdian"] = { first = 0x10F30, last = 0x10F6F, description = "Sogdian" }, ["sorasompeng"] = { first = 0x110D0, last = 0x110FF, description = "Sora Sompeng" }, ["soyombo"] = { first = 0x11A50, last = 0x11AAF, description = "Soyombo" }, ["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" }, @@ -606,7 +617,8 @@ characters.otfscripts = otfscripts setmetatableindex(otfscripts,function(t,unicode) for k, v in next, blocks do - local first, last = v.first, v.last + local first = v.first + local last = v.last if unicode >= first and unicode <= last then local script = v.otf or "dflt" for u=first,last do @@ -631,25 +643,27 @@ function characters.getrange(name,expression) -- used in font fallback definitio name = gsub(name,'"',"0x") -- goodie: tex hex notation local start, stop if expression then - local first, rest = lpegmatch(splitter2,name) - local range = rawget(blocks,lower(gsub(first,"[^a-zA-Z0-9]",""))) - if range then - start = range.first - stop = range.last - local s = loadstring("return 0 " .. rest) - if type(s) == "function" then - local d = s() - if type(d) == "number" then - start = start + d - stop = stop + d - return start, stop, nil + local n = tonumber(name) + if n then + return n, n, nil + else + local first, rest = lpegmatch(splitter2,name) + local range = rawget(blocks,lower(gsub(first,"[^a-zA-Z0-9]",""))) + if range then + local s = loadstring("return 0 " .. rest) + if type(s) == "function" then + local d = s() + if type(d) == "number" then + return range.first + d, range.last + d, nil + end end end end end - start, stop = lpegmatch(splitter1,name) + local start, stop = lpegmatch(splitter1,name) if start and stop then - start, stop = tonumber(start,16) or tonumber(start), tonumber(stop,16) or tonumber(stop) + start = tonumber(start,16) or tonumber(start) + stop = tonumber(stop, 16) or tonumber(stop) if start and stop then return start, stop, nil end @@ -738,6 +752,10 @@ local is_punctuation = allocate ( tohash { "pc","pd","ps","pe","pi","pf","po", } ) +local is_symbol = allocate ( tohash { + "sm", "sc", "sk", "so", +} ) + -- to be redone: store checked characters characters.is_character = is_character @@ -746,6 +764,7 @@ characters.is_command = is_command characters.is_spacing = is_spacing characters.is_mark = is_mark characters.is_punctuation = is_punctuation +characters.is_symbol = is_symbol local mti = function(t,k) if type(k) == "number" then @@ -1039,7 +1058,8 @@ setmetatableindex(specialchars, function(t,u) local c = data[u] local s = c and c.specials if s then - local tt, ttn = { }, 0 + local tt = { } + local ttn = 0 for i=2,#s do local si = s[i] local c = data[si] @@ -1265,9 +1285,11 @@ lpegpatterns.utf8lower = utf8lower -- string lpegpatterns.utf8upper = utf8upper -- string lpegpatterns.utf8shape = utf8shape -- string -function characters.lower (str) return lpegmatch(utf8lower,str) end -function characters.upper (str) return lpegmatch(utf8upper,str) end -function characters.shaped(str) return lpegmatch(utf8shape,str) end +function characters.lower (str) return str and lpegmatch(utf8lower,str) or "" end +function characters.upper (str) return str and lpegmatch(utf8upper,str) or "" end +function characters.shaped(str) return str and lpegmatch(utf8shape,str) or "" end + +lpeg.setutfcasers(characters.lower,characters.upper) -- local str = [[ -- ÀÁÂÃÄÅàáâãäå àáâãäåàáâãäå ÀÁÂÃÄÅÀÁÂÃÄÅ AAAAAAaaaaaa diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv index 9c41df67300..0519aaf915f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/char-ini.mkiv @@ -42,8 +42,8 @@ % use \normalUchar when possible .. the next one is nice for documents and it also accepts % 0x prefixed numbers -\def\utfchar #1{\clf_utfchar \numexpr#1\relax} -\def\safechar#1{\clf_safechar\numexpr#1\relax} +\def\utfchar #1{\clf_utfchar {#1}} +\def\safechar#1{\clf_safechar{#1}} \unexpanded\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml @@ -66,6 +66,18 @@ \normalstartimath\char#1\normalstopimath \fi\fi} +\unexpanded\def\textormathchars#1% + {{\font_text_or_mathchars#1\relax}} + +\unexpanded\def\font_text_or_mathchars#1#2\relax + {\relax\ifmmode + #1#2% + \else\iffontchar\font`#1\relax + #1#2\relax + \else + \normalstartimath#1#2\normalstopimath + \fi\fi} + %D The codes are stored in the format, so we don't need to reinitialize %D them (unless of course we have adapted the table). It is on the agenda %D to do this with \type {tex.lccode} cum suis once they're available. diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua index 065152881d6..bbaf11875d0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-tex.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['char-tex'] = { local lpeg = lpeg local tonumber, next, type = tonumber, next, type -local format, find, gmatch = string.format, string.find, string.gmatch +local format, find, gmatch, match = string.format, string.find, string.gmatch, string.match local utfchar, utfbyte = utf.char, utf.byte local concat, tohash = table.concat, table.tohash local P, C, R, S, V, Cs, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.V, lpeg.Cs, lpeg.Cc @@ -462,16 +462,24 @@ function commands.makeactive(n,name) -- not used -- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name) end +local function to_number(s) + local n = tonumber(s) + if n then + return n + end + return tonumber(match(s,'^"(.*)$'),16) or 0 +end + implement { name = "utfchar", - actions = { utfchar, contextsprint }, - arguments = "integer" + actions = { to_number, utfchar, contextsprint }, + arguments = "string" } implement { name = "safechar", - actions = { texcharacters.safechar, contextsprint }, - arguments = "integer" + actions = { to_number, texcharacters.safechar, contextsprint }, + arguments = "string" } implement { @@ -592,14 +600,17 @@ if not csletters then end -- if isletter then - local lc, uc = chr.lccode, chr.uccode + local lc = chr.lccode + local uc = chr.uccode if not lc then - chr.lccode, lc = u, u + chr.lccode = u + lc = u elseif type(lc) == "table" then lc = u end if not uc then - chr.uccode, uc = u, u + chr.uccode = u + uc = u elseif type(uc) == "table" then uc = u end @@ -623,12 +634,14 @@ if not csletters then -- local lc, uc = chr.lccode, chr.uccode if not lc then - chr.lccode, lc = u, u + chr.lccode = u + lc = u elseif type(lc) == "table" then lc = u end if not uc then - chr.uccode, uc = u, u + chr.uccode = u + uc = u elseif type(uc) == "table" then uc = u end diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua b/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua index 4dc7eba7a77..110a4a48ce5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/char-utf.lua @@ -107,8 +107,10 @@ else local function backtrack(v,last,target) local vs = v.specials if vs and #vs == 3 and vs[1] == "char" then - local one, two = vs[2], vs[3] - local first, second = utfchar(one), utfchar(two) .. last + local one = vs[2] + local two = vs[3] + local first = utfchar(one) + local second = utfchar(two) .. last collapsed[first..second] = target backtrack(data[one],second,target) end @@ -141,8 +143,11 @@ else local size = #vs if kind == "char" and size == 3 then -- what if more than 3 -- - local one, two = vs[2], vs[3] - local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode) + local one = vs[2] + local two = vs[3] + local first = utfchar(one) + local second = utfchar(two) + local combination = utfchar(unicode) -- collapsed[first..second] = combination backtrack(data[one],second,combination) diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua b/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua index 7581a61d115..9f0738fc516 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/chem-str.lua @@ -766,9 +766,6 @@ function chemistry.stop() if trace_metapost then report_chemistry("metapost code:\n%s", mpcode) end - if metapost.instance(chemistry.instance) then - f_initialize = nil - end metapost.graphic { instance = chemistry.instance, format = chemistry.format, @@ -776,7 +773,6 @@ function chemistry.stop() data = mpcode, definitions = f_initialize, } - t_initialize = "" metacode = nil end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv b/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv index 646cf13f103..71b104e4791 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/chem-str.mkiv @@ -650,18 +650,18 @@ \chem_formula_bot_nop \fi\fi \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname - \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}% + \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}% \else - \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}% + \toksapp\t_chem_mid{\molecule{#1}\aligntab}% \fi} \def\chem_formula_mid#1% {\csname\??chemicalsymbol\detokenize{#1}\endcsname} -\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top\aligntab}} -\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot\aligntab}} -\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} -\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot} +\def\chem_formula_top_nop {\toksapp\t_chem_top{\aligntab}} +\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}} +\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} +\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot} \def\chem_formula_top_indeed#1{\strut#1} \def\chem_formula_bot_indeed#1{\strut#1} diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua index 07054663708..f55132a0612 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-bas.lua @@ -22,27 +22,38 @@ if not modules then modules = { } end modules ['cldf-bas'] = { -- flush(ctxcatcodes,"}") -- end -local tonumber = tonumber -local type = type -local format = string.format -local utfchar = utf.char -local concat = table.concat +local tonumber = tonumber +local type = type +local format = string.format +local utfchar = utf.char +local concat = table.concat -local context = context -local ctxcore = context.core -local variables = interfaces.variables +local context = context +local ctxcore = context.core -local nodepool = nodes.pool -local new_rule = nodepool.rule -local new_glyph = nodepool.glyph -local current_attr = nodes.current_attr +local variables = interfaces.variables -local current_font = font.current -local texgetcount = tex.getcount -local texsetcount = tex.setcount +local ctx_flushnode = context.nuts.flush + +local nuts = nodes.nuts +local tonode = nuts.tonode +local nodepool = nuts.pool +local new_rule = nodepool.rule +local new_glyph = nodepool.glyph +local new_latelua = nodepool.latelua + +local setattrlist = nuts.setattrlist + +local texgetcount = tex.getcount +local texsetcount = tex.setcount -- a set of basic fast ones +function context.setfontid(n) + -- isn't there a setter? + context("\\setfontid%i\\relax",n) +end + function context.char(k) -- used as escape too, so don't change to utf if type(k) == "table" then local n = #k @@ -70,30 +81,35 @@ function context.utfchar(k) end end -function context.rule(w,h,d,dir) +function context.rule(w,h,d,direction) local rule if type(w) == "table" then - rule = new_rule(w.width,w.height,w.depth,w.dir) + rule = new_rule(w.width,w.height,w.depth,w.direction) else - rule = new_rule(w,h,d,dir) + rule = new_rule(w,h,d,direction) end - rule.attr = current_attr() - context(rule) + setattrlist(rule,true) + context(tonode(rule)) + -- ctx_flushnode(tonode(rule)) end function context.glyph(id,k) if id then if not k then - id, k = current_font(), id + id, k = true, id end local glyph = new_glyph(id,k) - glyph.attr = current_attr() - context(glyph) + setattrlist(glyph,true) + context(tonode(glyph)) + -- ctx_flushnode(tonode(glyph)) end end -local function ctx_par () context("\\par") end -local function ctx_space() context("\\space") end +-- local function ctx_par () context("\\par") end +-- local function ctx_space() context("\\space") end + +local ctx_par = context.cs.par +local ctx_space = context.cs.space context.par = ctx_par context.space = ctx_space @@ -101,8 +117,11 @@ context.space = ctx_space ctxcore.par = ctx_par ctxcore.space = ctx_space -local function ctx_bgroup() context("{") end -local function ctx_egroup() context("}") end +-- local function ctx_bgroup() context("{") end +-- local function ctx_egroup() context("}") end + +local ctx_bgroup = context.cs.bgroup +local ctx_egroup = context.cs.egroup context.bgroup = ctx_bgroup context.egroup = ctx_egroup @@ -136,13 +155,21 @@ function ctxcore.flushboxregister(n) context(type(n) == "number" and [[\box%s ]] or [[\box\%s]],n) end -function ctxcore.beginhbox() context([[\hbox{]]) end -function ctxcore.beginvbox() context([[\vbox{]]) end -function ctxcore.beginvtop() context([[\vtop{]]) end +-- function ctxcore.beginhbox() context([[\hbox\bgroup]]) end +-- function ctxcore.beginvbox() context([[\vbox\bgroup]]) end +-- function ctxcore.beginvtop() context([[\vtop\bgroup]]) end + +local ctx_hbox = context.cs.hbox +local ctx_vbox = context.cs.vbox +local ctx_vtop = context.cs.vtop -ctxcore.endhbox = ctx_egroup -ctxcore.endvbox = ctx_egroup -ctxcore.endvtop = ctx_egroup +function ctxcore.beginhbox() ctx_hbox() ctx_bgroup() end +function ctxcore.beginvbox() ctx_vbox() ctx_bgroup() end +function ctxcore.beginvtop() ctx_vtop() ctx_bgroup() end + +ctxcore.endhbox = ctx_egroup -- \egroup +ctxcore.endvbox = ctx_egroup -- \egroup +ctxcore.endvtop = ctx_egroup -- \egroup local function allocate(name,what,cmd) local a = format("c_syst_last_allocated_%s",what) @@ -165,3 +192,65 @@ context.registers = { -- not really a register but kind of belongs here newchar = function(name,u) context([[\chardef\%s=%s\relax]],name,u) end, } + +do + + if CONTEXTLMTXMODE > 1 then + + function context.latelua(f) + -- table check moved elsewhere + local latelua = new_latelua(f) + setattrlist(latelua,true) -- will become an option + ctx_flushnode(latelua,true) + end + + else + + function context.latelua(f) + if type(f) == "table" then + local action = f.action + local specification = f.specification or f + f = function() action(specification) end + end + local latelua = new_latelua(f) + setattrlist(latelua,true) -- will become an option + ctx_flushnode(latelua,true) + end + + end + +end +-- yes or no + +do + + local NC = ctxcore.NC + local BC = ctxcore.BC + local NR = ctxcore.NR + + context.nc = setmetatable({ }, { + __call = + function(t,...) + NC() + return context(...) + end, + __index = + function(t,k) + NC() + return context[k] + end, + } + ) + + function context.bc(...) + BC() + return context(...) + end + + function context.nr(...) + NC() + NR() + end + +end + diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua index 8cd6408d372..9b1a4e368da 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = { license = "see context related readme files" } +-- todo: {token} -> 3 tokens + -- This started as an experiment: generating context code at the lua end. After all -- it is surprisingly simple to implement due to metatables. I was wondering if -- there was a more natural way to deal with commands at the lua end. Of course it's @@ -29,7 +31,7 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- todo : context("%bold{total: }%s",total) -- todo : context.documentvariable("title") -- --- during the crited project we ran into the situation that luajittex was 10-20 times +-- During the crited project we ran into the situation that luajittex was 10-20 times -- slower that luatex ... after 3 days of testing and probing we finally figured out that -- the the differences between the lua and luajit hashers can lead to quite a slowdown -- in some cases. @@ -52,6 +54,11 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- watching Trio Hiromi Uehara, Anthony Jackson & Simon Phillips (discovered via the -- later on YT). Hopefully the video breaks made the following better in the end. +-- This module is also a test bed for experimental features so the content changes over +-- time (for the better or worse). There have been no fundamental changes for many years +-- and performance has not changed much either. + + local format, stripstring = string.format, string.strip local next, type, tostring, tonumber, unpack, select, rawset = next, type, tostring, tonumber, unpack, select, rawset local insert, remove, concat = table.insert, table.remove, table.concat @@ -84,6 +91,13 @@ local texgetcount = tex.getcount local isnode = node.is_node local writenode = node.write local copynodelist = node.copy_list +local tonut = node.direct.todirect +local tonode = node.direct.tonode + +local istoken = token.is_token +local newtoken = token.new +local createtoken = token.create +local setluatoken = token.set_lua local catcodenumbers = catcodes.numbers @@ -104,16 +118,31 @@ local report_cld = logs.reporter("cld","stack") local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) +local tokenflushmode = true +local nodeflushmode = true +local scannerdefmode = true +local maxflushnodeindex = 0x10FFFF - 1 + +-- tokenflushmode = false +-- scannerdefmode = false +-- nodeflushmode = false + -- In earlier experiments a function tables was referred to as lua.calls and the -- primitive \luafunctions was \luacall and we used our own implementation of -- a function table (more indirectness). +local trialtypesettingstate = createtoken("trialtypesettingstate").index + +function context.trialtypesetting() + return texgetcount(trialtypesettingstate) ~= 0 +end + local knownfunctions = lua.get_functions_table() local showstackusage = false trackers.register("context.stack",function(v) showstackusage = v end) -local freed, nofused, noffreed = { }, 0, 0 -- maybe use the number of @@trialtypesetting +local freed, nofused, noffreed = { }, 0, 0 local usedstack = function() return nofused, noffreed @@ -122,7 +151,7 @@ end local flushfunction = function(slot,arg) if arg() then -- keep - elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! + elseif texgetcount(trialtypesettingstate) == 0 then noffreed = noffreed + 1 freed[noffreed] = slot knownfunctions[slot] = false @@ -147,7 +176,7 @@ local storefunction = function(arg) end local flushnode = function(slot,arg) - if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private! + if texgetcount(trialtypesettingstate) == 0 then writenode(arg) noffreed = noffreed + 1 freed[noffreed] = slot @@ -182,9 +211,13 @@ local f_resolve = nil local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1 local function resolvestoredfunction(str) - f_resolve = global - lpegmatch(p_resolve,str) - return f_resolve + if type(str) == "string" then + f_resolve = global + lpegmatch(p_resolve,str) + return f_resolve + else + return str + end end local function expose(slot,f,...) -- so we can register yet undefined functions @@ -246,17 +279,17 @@ local registerfunction = function(f,direct) -- either f=code or f=namespace,dire func = resolvestoredfunction(f) end if type(func) ~= "function" then - func = function() report_cld("invalid resolve %A",f) end + func = function() report_cld("invalid resolve %A, case %s",f,1) end end elseif type(f) == "string" then func = loadstring(f) if type(func) ~= "function" then - func = function() report_cld("invalid code %A",f) end + func = function() report_cld("invalid code %A, case %s",f,2) end end elseif type(f) == "function" then func = f else - func = function() report_cld("invalid function %A",f) end + func = function() report_cld("invalid function %A, case %s",f,3) end end knownfunctions[slot] = func return slot @@ -305,53 +338,52 @@ local storedscanners = interfaces.storedscanners storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") local interfacescanners = setmetatablenewindex(function(t,k,v) + rawset(t,k,v) if storedscanners[k] then - -- report_cld("warning: scanner %a is already set",k) + -- report_cld("warning: scanner %a is already set (mode 1a)",k) -- os.exit() -- \scan_ is already in the format -- report_cld("using interface scanner: %s",k) + elseif scannerdefmode then + -- report_cld("installing interface scanner: %s (mode 1b)",k) + -- local n = registerfunction(interfaces.scanners[k],true) + local n = registerfunction("interfaces.scanners."..k,true) + storedscanners[k] = n + local name = "clf_" .. k + setluatoken(name,n,"global") -- todo : protected and "protected" or "" else - -- todo: allocate slot here and pass it + -- report_cld("installing interface scanner: %s (mode 1c)",k) storedscanners[k] = true - -- report_cld("installing interface scanner: %s",k) context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k) end - rawset(t,k,v) + -- rawset(t,k,v) end) function interfaces.registerscanner(name,action,protected,public,call) + rawset(interfacescanners,name,action) if storedscanners[name] then - -- report_cld("warning: scanner %a is already set",k) + -- report_cld("warning: scanner %a is already set (mode 2a)",name) -- os.exit() -- \scan_ is already in the format -- report_cld("using interface scanner: %s",k) + elseif scannerdefmode then + -- report_cld("installing interface scanner: %s (mode 2b)",name) + -- local n = registerfunction(action,true) -- todo + local n = registerfunction("interfaces.scanners."..name,true) + storedscanners[name] = n + local name = public and name or ("clf_" .. name) + setluatoken(name,n,"global",protected and "protected" or "") else storedscanners[name] = true --- if protected then --- -- report_cld("installing expandable interface scanner: %s",k) --- if public then --- context("\\installprotectedctxscanner{%s}{interfaces.scanners.%s}",name,name) --- else --- context("\\installprotectedctxscanner{clf_%s}{interfaces.scanners.%s}",name,name) --- end --- else --- -- report_cld("installing protected interface scanner: %s",k) --- if public then --- context("\\installctxscanner{%s}{interfaces.scanners.%s}",name,name) --- else --- context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",name,name) --- end --- end - -- report_cld("installing interface scanner: %s",k) - context("\\install%sctxscanner%s{%s%s}{interfaces.scanners.%s}", - protected and "protected" or "", - call and "call" or "", - public and "" or "clf_", - name, - name - ) - end - rawset(interfacescanners,name,action) + -- report_cld("installing interface scanner: %s (mode 2c)",name) + context("\\install%sctxscanner{%s%s}{interfaces.scanners.%s}", + protected and "protected" or "", + public and "" or "clf_", + name, + name + ) + end + -- rawset(interfacescanners,name,action) end interfaces.scanners = storage.mark(interfacescanners) @@ -379,7 +411,7 @@ end local function dummy() end -function commands.ctxresetter(name) +function commands.ctxresetter(name) -- to be checked return function() if storedscanners[name] then rawset(interfacescanners,name,dummy) @@ -388,10 +420,6 @@ function commands.ctxresetter(name) end end -function context.trialtypesetting() - return texgetcount("@@trialtypesetting") ~= 0 -end - -- Should we keep the catcodes with the function? local catcodestack = { } @@ -673,6 +701,8 @@ local s_cldl_option_b = "[\\cldl" local s_cldl_option_f = "[\\cldl" -- add space (not needed) local s_cldl_option_e = "]" local s_cldl_option_s = "\\cldl" +----- s_cldl_option_d = "\\cldd" +local s_cldl_option_d = s_cldl_option_s local s_cldl_argument_b = "{\\cldl" local s_cldl_argument_f = "{\\cldl " local s_cldl_argument_e = "}" @@ -683,14 +713,23 @@ local s_cldl_argument_e = "}" -- local s_cldl_argument_b = "{" -- local s_cldl_argument_f = "{ " +local t_cldl_luafunction = createtoken("luafunctioncall") +local lua_expandable_call_token_code = token.command_id and token.command_id("lua_expandable_call") + local function writer(parent,command,...) -- already optimized before call - flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes + + if type(command) == "string" then -- for now + flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes + else + flush(command) -- todo: ctx|prt|texcatcodes + end + local direct = false -- local t = { ... } -- for i=1,#t do -- local ti = t[i] for i=1,select("#",...) do - local ti = (select(i,...)) + local ti = select(i,...) if direct then local typ = type(ti) if typ == "string" or typ == "number" then @@ -703,6 +742,8 @@ local function writer(parent,command,...) -- already optimized before call -- nothing elseif ti == "" then flush(currentcatcodes,"{}") + -- elseif ti == 1 then + -- flush(currentcatcodes,"{1}") else local typ = type(ti) if typ == "string" then @@ -719,7 +760,7 @@ local function writer(parent,command,...) -- already optimized before call flush(currentcatcodes,"}") end elseif typ == "number" then - -- numbers never have funny catcodes + -- numbers never have funny catcodesz flush(currentcatcodes,"{",ti,"}") elseif typ == "table" then local tn = #ti @@ -749,7 +790,16 @@ local function writer(parent,command,...) -- already optimized before call elseif tn == 1 then -- some 20% faster than the next loop local tj = ti[1] if type(tj) == "function" then - flush(currentcatcodes,s_cldl_option_b,storefunction(tj),s_cldl_option_e) + tj = storefunction(tj) + if tokenflushmode then + if newtoken then + flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),"]") + else + flush(currentcatcodes,"[",t_cldl_luafunction,tj,"]") + end + else + flush(currentcatcodes,s_cldl_option_b,tj,s_cldl_option_e) + end else flush(currentcatcodes,"[",tj,"]") end @@ -758,10 +808,15 @@ local function writer(parent,command,...) -- already optimized before call for j=1,tn do local tj = ti[j] if type(tj) == "function" then - if j == tn then - flush(currentcatcodes,s_cldl_option_s,storefunction(tj),"]") + tj = storefunction(tj) + if tokenflushmode then + if newtoken then + flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),j == tn and "]" or ",") + else + flush(currentcatcodes,"[",t_cldl_luafunction,tj,j == tn and "]" or ",") + end else - flush(currentcatcodes,s_cldl_option_s,storefunction(tj),",") + flush(currentcatcodes,s_cldl_option_s,tj,j == tn and "]" or ",") end else if j == tn then @@ -774,7 +829,16 @@ local function writer(parent,command,...) -- already optimized before call end elseif typ == "function" then -- todo: ctx|prt|texcatcodes - flush(currentcatcodes,s_cldl_argument_f,storefunction(ti),s_cldl_argument_e) + ti = storefunction(ti) + if tokenflushmode then + if newtoken then + flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}") + else + flush(currentcatcodes,"{",t_cldl_luafunction,ti,"}") + end + else + flush(currentcatcodes,s_cldl_argument_f,ti,s_cldl_argument_e) + end elseif typ == "boolean" then if ti then flushdirect(currentcatcodes,"\r") @@ -783,62 +847,123 @@ local function writer(parent,command,...) -- already optimized before call end elseif typ == "thread" then report_context("coroutines not supported as we cannot yield across boundaries") - elseif isnode(ti) then -- slow - flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) + elseif isnode(ti) then -- slow | why {} here ? + if nodeflushmode then + local n = tonut(ti) + if n <= maxflushnodeindex then + flush(currentcatcodes,"{",ti,"}") + else + flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) + end + else + flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) + end else report_context("error: %a gets a weird argument %a",command,ti) end +-- else +-- local n = isnode(ti) +-- if n then +-- if nodeflushmode and n <= maxflushnodeindex then +-- flush(ti) +-- else +-- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) +-- end +-- else +-- report_context("error: %a gets a weird argument %a",command,ti) +-- end +-- end end end end --- if performance really matters we can consider a compiler but it will never --- pay off - --- local function prtwriter(command,...) -- already optimized before call --- flush(prtcatcodes,command) --- for i=1,select("#",...) do --- local ti = (select(i,...)) --- if ti == nil then --- -- nothing --- elseif ti == "" then --- flush(prtcatcodes,"{}") --- else --- local tp = type(ti) --- if tp == "string" or tp == "number"then --- flush(prtcatcodes,"{",ti,"}") --- elseif tp == "function" then --- flush(prtcatcodes,s_cldl_argument_f,storefunction(ti),s_cldl_argument_e) --- elseif isnode(ti) then --- flush(prtcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) +local core + +if tokenflushmode then -- combine them + + local toks = tokens.cache + + context.tokenizedcs = toks + + core = setmetatableindex(function(parent,k) + local t + local f = function(first,...) + if not t then + t = toks[k] + end + if first == nil then + flush(t) + else + return writer(context,t,first,...) + end + end + parent[k] = f + return f + end) + +-- core = setmetatableindex(function(parent,k) +-- local t +-- local f = function(first,...) +-- if not t then +-- t = toks[k] +-- end +-- local f = function(first,...) +-- if first == nil then +-- flush(t) -- else --- report_context("fatal error: prt %a gets a weird argument %a",command,ti) +-- return writer(context,t,first,...) -- end -- end +-- parent[k] = f +-- if first == nil then +-- flush(t) +-- else +-- return writer(context,t,first,...) +-- end -- end --- end +-- parent[k] = f +-- return f +-- end) + + core.cs = setmetatableindex(function(parent,k) + local t + local f = function() + if not t then + t = toks[k] + end + flush(t) + end + parent[k] = f + return f + end) + +else + + context.tokenizedcs = false + + core = setmetatableindex(function(parent,k) + local c = "\\" .. k + local f = function(first,...) + if first == nil then + flush(currentcatcodes,c) + else + return writer(context,c,first,...) + end + end + parent[k] = f + return f + end) -local core = setmetatableindex(function(parent,k) - local c = "\\" .. k -- tostring(k) - local f = function(first,...) - if first == nil then + core.cs = setmetatableindex(function(parent,k) + local c = "\\" .. k -- tostring(k) + local f = function() flush(currentcatcodes,c) - else - return writer(context,c,first,...) end - end - parent[k] = f - return f -end) + parent[k] = f + return f + end) -core.cs = setmetatableindex(function(parent,k) - local c = "\\" .. k -- tostring(k) - local f = function() - flush(currentcatcodes,c) - end - parent[k] = f - return f -end) +end local indexer = function(parent,k) if type(k) == "string" then @@ -933,8 +1058,16 @@ local caller = function(parent,f,a,...) end elseif typ == "function" then -- ignored: a ... - flush(currentcatcodes,"{\\cldl",storefunction(f),"}") -- todo: ctx|prt|texcatcodes - -- flush(currentcatcodes,"{",storefunction(f),"}") -- todo: ctx|prt|texcatcodes + f = storefunction(f) + if tokenflushmode then + if newtoken then + flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}") + else + flush(currentcatcodes,"{",t_cldl_luafunction,f,"}") + end + else + flush(currentcatcodes,s_cldl_argument_b,f,s_cldl_argument_e) -- todo: ctx|prt|texcatcodes + end elseif typ == "boolean" then if f then if a ~= nil then @@ -953,20 +1086,55 @@ local caller = function(parent,f,a,...) elseif typ == "thread" then report_context("coroutines not supported as we cannot yield across boundaries") elseif isnode(f) then -- slow - -- writenode(f) - flush(currentcatcodes,"\\cldl",storenode(f)," ") - -- flush(currentcatcodes,"",storenode(f)," ") + if nodeflushmode then + local n = tonut(f) + if n <= maxflushnodeindex then + flush(f) + else + flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") + end + else + flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") + end else report_context("error: %a gets a weird argument %a","context",f) end +-- else +-- local n = isnode(f) +-- if n then +-- if nodeflushmode and n <= maxflushnodeindex then +-- flush(f) +-- else +-- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") +-- end +-- else +-- report_context("error: %a gets a weird argument %a","context",f) +-- end +-- end end end -context.nodes = { +context.nodes = { -- todo store = storenode, flush = function(n) - flush(currentcatcodes,"\\cldl",storenode(n)," ") - -- flush(currentcatcodes,"",storenode(n)," ") + if nodeflushmode and tonut(n) <= maxflushnodeindex then + flush(n) + else + flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(n)," ") + end + end, +} + +context.nuts = { -- todo + store = function(n) + return storenode(tonut(n)) + end, + flush = function(n,d) + if nodeflushmode and n <= maxflushnodeindex then + flush(tonode(n)) + else + flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(tonode(n))," ") + end end, } @@ -1012,8 +1180,8 @@ local nofflushes = 0 local tracingpermitted = true local visualizer = lpeg.replacer { - { "\n","<>" }, - { "\r","<>" }, + { "\n", "<>" }, + { "\r", "<>" }, } statistics.register("traced context", function() @@ -1026,13 +1194,48 @@ statistics.register("traced context", function() end end) +local function userdata(argument) + if isnode(argument) then + return formatters["<< %s node %i>>"](nodes.nodecodes[argument.id],tonut(argument)) + end + if istoken(argument) then + local csname = argument.csname + if csname then + -- return formatters["<<\\%s>>"](csname) + return formatters["\\%s"](csname) + end + local cmdname = argument.cmdname + if cmdname == "lua_expandable_call" or cmdname == "lua_call" then + return "<>" -- argument.mode + end + return "<>" + end + return "<>" +end + + local tracedwriter = function(parent,...) -- also catcodes ? nofwriters = nofwriters + 1 local savedflush = flush local savedflushdirect = flushdirect -- unlikely to be used here - local t, n = { "w : - : " }, 1 + local t = { "w : - : " } + local n = 1 local traced = function(catcodes,...) -- todo: check for catcodes - local s = concat({...}) + local s = type(catcodes) == "number" and { ... } or { catcodes, ... } + for i=1,#s do + local argument = s[i] + local argtype = type(argument) + if argtype == "string" then + s[i] = lpegmatch(visualizer,argument) + elseif argtype == "number" then + s[i] = argument + elseif argtype == "userdata" then + s[i] = userdata(argument) + else + s[i] = formatters["<<%S>>"](argument) + end + end + s = concat(s) s = lpegmatch(visualizer,s) n = n + 1 t[n] = s @@ -1060,9 +1263,10 @@ end local traced = function(one,two,...) if two ~= nil then -- only catcodes if 'one' is number - local catcodes = type(one) == "number" and one + local catcodes = type(one) == "number" and one local arguments = catcodes and { two, ... } or { one, two, ... } - local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1 + local collapsed = { formatters["f : %s : "](catcodes or '-') } + local c = 1 for i=1,#arguments do local argument = arguments[i] local argtype = type(argument) @@ -1071,6 +1275,8 @@ local traced = function(one,two,...) collapsed[c] = lpegmatch(visualizer,argument) elseif argtype == "number" then collapsed[c] = argument + elseif argtype == "userdata" then + collapsed[c] = userdata(argument) else collapsed[c] = formatters["<<%S>>"](argument) end @@ -1083,6 +1289,8 @@ local traced = function(one,two,...) currenttrace(formatters["f : - : %s"](lpegmatch(visualizer,one))) elseif argtype == "number" then currenttrace(formatters["f : - : %s"](one)) + elseif argtype == "userdata" then + currenttrace(formatters["F : - : %s"](userdata(one))) else currenttrace(formatters["f : - : <<%S>>"](one)) end @@ -1175,24 +1383,21 @@ do local sentinel = string.char(26) -- ASCII SUB character : endoffileasciicode : ignorecatcode local level = 0 - local function collect(c,...) -- can be optimized - -- snippets - for i=1,select("#",...) do + local function collect(c,a,...) -- can be optimized + if type(c) == "userdata" then nofcollected = nofcollected + 1 - collected[nofcollected] = (select(i,...)) + -- collected[nofcollected] = userdata(c) + collected[nofcollected] = "\\" .. c.csname + end + if a then + for i=1,select("#",a,...) do + local c = select(i,a,...) + nofcollected = nofcollected + 1 + collected[nofcollected] = type(c) == "userdata" and userdata(c) or c + end end end - -- local function collectdirect(c,...) -- can be optimized - -- -- lines - -- for i=1,select("#",...) do - -- n = n + 1 - -- t[n] = (select(i,...)) - -- n = n + 1 - -- t[n] = "\r" - -- end - -- end - local collectdirect = collect local permitted = true @@ -1224,34 +1429,39 @@ do end end -end - --- + local findtexfile = resolvers.findtexfile + local findfile = resolvers.findfile -function context.runfile(filename) - local foundname = resolvers.findtexfile(file.addsuffix(filename,"cld")) or "" - if foundname ~= "" then - local ok = dofile(foundname) - if type(ok) == "function" then - if trace_cld then - report_context("begin of file %a (function call)",foundname) - end - ok() - if trace_cld then - report_context("end of file %a (function call)",foundname) + function context.runfile(filename) + local foundname = findtexfile(file.addsuffix(filename,"cld")) or "" + if foundname ~= "" then + local ok = dofile(foundname) + if type(ok) == "function" then + if trace_cld then + report_context("begin of file %a (function call)",foundname) + end + ok() + if trace_cld then + report_context("end of file %a (function call)",foundname) + end + elseif ok then + report_context("file %a is processed and returns true",foundname) + else + report_context("file %a is processed and returns nothing",foundname) end - elseif ok then - report_context("file %a is processed and returns true",foundname) else - report_context("file %a is processed and returns nothing",foundname) + report_context("unknown file %a",filename) end - else - report_context("unknown file %a",filename) end -end -function context.loadfile(filename) - context(stripstring(loaddata(resolvers.findfile(filename)))) + function context.loadfile(filename) + context(stripstring(loaddata(findfile(filename)))) + end + + function context.loadviafile(filename) + viafile(stripstring(loaddata(findfile(filename)))) + end + end -- some functions @@ -1270,7 +1480,7 @@ do local function indexer(parent,k) local f = function(...) - local a = { ... } + local a = { ... } -- this also freezes ... return function() -- return context[k](unpack(a)) return core[k](unpack(a)) @@ -1295,46 +1505,48 @@ do end -do - - -- context.nested (todo: lines), creates strings - - local nested = { } - - local function indexer(parent,k) -- not ok when traced - local f = function(...) - local t, savedflush, n = { }, flush, 0 - flush = function(c,f,s,...) -- catcodes are ignored - n = n + 1 - t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 - end - -- context[k](...) - core[k](...) - flush = savedflush - return concat(t) - end - parent[k] = f - return f - end - - local function caller(parent,...) - local t, savedflush, n = { }, flush, 0 - flush = function(c,f,s,...) -- catcodes are ignored - n = n + 1 - t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 - end - -- context(...) - defaultcaller(context,...) - flush = savedflush - return concat(t) - end - - setmetatableindex(nested,indexer) - setmetatablecall (nested,caller) - - context.nested = nested +-- do +-- +-- -- context.nested (todo: lines), creates strings +-- +-- local nested = { } +-- +-- local function indexer(parent,k) -- not ok when traced +-- local f = function(...) +-- local t, savedflush, n = { }, flush, 0 +-- flush = function(c,f,s,...) -- catcodes are ignored +-- n = n + 1 +-- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 +-- end +-- -- context[k](...) +-- core[k](...) +-- flush = savedflush +-- return concat(t) +-- end +-- parent[k] = f +-- return f +-- end +-- +-- local function caller(parent,...) +-- local t, savedflush, n = { }, flush, 0 +-- flush = function(c,f,s,...) -- catcodes are ignored +-- n = n + 1 +-- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1 +-- end +-- -- context(...) +-- defaultcaller(context,...) +-- flush = savedflush +-- return concat(t) +-- end +-- +-- setmetatableindex(nested,indexer) +-- setmetatablecall (nested,caller) +-- +-- context.nested = nested +-- +-- end -end +context.nested = context.delayed -- verbatim @@ -1360,14 +1572,22 @@ function context.newindexer(catcodes,cmdcodes) contentcatcodes = savedcatcodes end - handler.cs = setmetatableindex(function(parent,k) - local c = "\\" .. k -- tostring(k) - local f = function() - flush(cmdcodes,c) - end - parent[k] = f - return f - end) + if tokenflushmode then + + handler.cs = core.cs + + else + + handler.cs = setmetatableindex(function(parent,k) + local c = "\\" .. k -- tostring(k) + local f = function() + flush(cmdcodes,c) + end + parent[k] = f + return f + end) + + end setmetatableindex(handler,indexer) setmetatablecall (handler,caller) @@ -1420,21 +1640,51 @@ do end end - local function indexer(parent,k) - if type(k) == "string" then - local c = "\\" .. k - local f = function(first,...) - if first == nil then - flush(currentcatcodes,c) - else - return formattedflush(parent,c,first,...) + local indexer + + if tokenflushmode then -- combine them + + local toks = tokens.cache + + indexer = function(parent,k) + if type(k) == "string" then + local t + local f = function(first,...) + if not t then + t = toks[k] + end + if first == nil then + flush(t) + else + return formattedflush(parent,t,first,...) + end + end + parent[k] = f + return f + else + return context -- catch + end + end + + else + + indexer = function(parent,k) + if type(k) == "string" then + local c = "\\" .. k + local f = function(first,...) + if first == nil then + flush(currentcatcodes,c) + else + return formattedflush(parent,c,first,...) + end end + parent[k] = f + return f + else + return context -- catch end - parent[k] = f - return f - else - return context -- catch end + end -- formatted([catcodes,]format[,...]) diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv index 27ce42aa2d0..29fb15d6883 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.mkiv @@ -13,6 +13,8 @@ \writestatus{loading}{ConTeXt Lua Documents / Initialization} +\newcount\trialtypesettingstate % gets aliased at the Lua end + \registerctxluafile{cldf-ini}{} %D With each new update of \MKIV\ we can join Within Temptation in @@ -41,14 +43,16 @@ % \fi \let\cldl\luafunction +\let\cldd\lateluafunction % \catcode`=\activecatcode \let\luafunction % saves 10% on the call -% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \global\let^^A=\cldf -% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \global\let^^B=\cldn +% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \glet^^A=\cldf +% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \glet^^B=\cldn \normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}} \def\cldloadfile #1{\directlua{context.loadfile("#1")}} + \def\cldloadviafile#1{\directlua{context.loadviafile("#1")}} \def\cldcontext #1{\directlua{context(#1)}} \def\cldcommand #1{\directlua{context.#1}} % \def\cldverbatim #1{\directlua{context.verbatim.#1}} % maybe make verbatim global diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua index a97eadf35ef..52cfea8d0ae 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-int.lua @@ -88,9 +88,10 @@ function interfaces.definecommand(name,specification) -- name is optional else -- we could flush immediate but tracing is bad then stack[name] = { } - local opt, done = 0, false + local opt = 0 + local done = false local snippets = { } -- we can reuse it - local mkivdo = "\\mkivdo" .. name -- maybe clddo + local mkivdo = "\\mkivdo" .. name -- maybe clddo snippets[#snippets+1] = "\\def" snippets[#snippets+1] = mkivdo for i=1,na do diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua index ccf1f01c6b5..d0b16e034fa 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-scn.lua @@ -25,6 +25,7 @@ local scanners = interfaces.scanners local register = interfaces.registerscanner local compile = tokens.compile or function() end +local presets = tokens.presets local dummy = function() end @@ -47,6 +48,10 @@ function interfaces.implement(specification) if name == "" then name = nil end + local p = arguments and presets[arguments] + if p then + arguments = p + end local scanner local resetter = onlyonce and name and commands.ctxresetter(name) if resetter then @@ -72,7 +77,7 @@ function interfaces.implement(specification) if scanners[name] and not specification.overload then report("warning: 'scanners.%s' is redefined",name) end --- scanners[name] = scanner + -- scanners[name] = scanner -- we now use: register(name,scanner,specification.protected,specification.public,specification.call) if private then return diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua index 3710b24159a..7a1c813014b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ver.lua @@ -13,32 +13,69 @@ if not modules then modules = { } end modules ['cldf-ver'] = { local concat, tohandle = table.concat, table.tohandle local splitlines, strip = string.splitlines, string.strip local tostring, type = tostring, type +local assignbuffer = buffers.assign local context = context -local function flush(...) - context(concat{...,"\r"}) -- was \n +context.tobuffer = assignbuffer -- (name,str,catcodes) + +function context.tolines(str,strip) + local lines = type(str) == "string" and splitlines(str) or str + for i=1,#lines do + if strip then + context(strip(lines[i]) .. " ") + else + context(lines[i] .. " ") + end + end end -local function t_tocontext(...) - context.starttyping { "typing" } -- else [1] is intercepted - context.pushcatcodes("verbatim") - tohandle(flush,...) -- ok? - context.stoptyping() - context.popcatcodes() +-- local function flush(...) +-- context(concat { ..., "\r" }) -- was \n +-- end +-- +-- somehow this doesn't work any longer .. i need to figure out why +-- +-- local function t_tocontext(t) +-- context.starttyping { "typing" } -- else [1] is intercepted +-- context.pushcatcodes("verbatim") +-- -- tohandle(flush,...) +-- context(table.serialize(t)) +-- context.stoptyping() +-- context.popcatcodes() +-- end +-- +-- local function s_tocontext(first,second,...) -- we need to catch {\} +-- context.type() +-- context("{") +-- context.pushcatcodes("verbatim") +-- if second then +-- context(concat({ first, second, ... }, " ")) +-- else +-- context(first) -- no need to waste a { } +-- end +-- context.popcatcodes() +-- context("}") +-- end + +local t_buffer = { "t_o_c_o_n_t_e_x_t" } +local t_typing = { "typing" } +local t_type = { "type" } + +local function flush(s,inline) + assignbuffer("t_o_c_o_n_t_e_x_t",s) + context[inline and "typeinlinebuffer" or "typebuffer"](t_buffer) + context.resetbuffer(t_buffer) end -local function s_tocontext(first,...) -- we need to catch {\} - context.type() - context("{") - context.pushcatcodes("verbatim") - if first then - context(first) -- no need to waste a { } - else - context(concat({first,...}," ")) - end - context.popcatcodes() - context("}") +local function t_tocontext(t) + local s = table.serialize(t) + context(function() flush(s,false) end) +end + +local function s_tocontext(first,second,...) -- we need to catch {\} + local s = second and concat({ first, second, ... }, " ") or first + context(function() flush(s,true) end) end local function b_tocontext(b) @@ -74,15 +111,3 @@ end) context.tocontext = tocontext -context.tobuffer = buffers.assign -- (name,str,catcodes) - -function context.tolines(str,strip) - local lines = type(str) == "string" and splitlines(str) or str - for i=1,#lines do - if strip then - context(strip(lines[i]) .. " ") - else - context(lines[i] .. " ") - end - end -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv index dbae02d5a2a..ae955ec1c18 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-crayola.mkiv @@ -1,9 +1,9 @@ %D \module -%D [ file=colo-imp-crayola -%D version=2016.03.21, -%D title=\CONTEXT\ Color Macros, -%D subtitle=Crayola, -%D author=Alan Braslau] +%D [ file=colo-imp-crayola +%D version=2016.03.21, +%D title=\CONTEXT\ Color Macros, +%D subtitle=Crayola, +%D author=Alan Braslau] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA, See mreadme.pdf for diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-imp-svg.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-svg.mkiv new file mode 100644 index 00000000000..f39adaa9874 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/colo-imp-svg.mkiv @@ -0,0 +1,164 @@ +%D \module +%D [ file=colo-imp-svg, +%D version=2018.09.17, +%D title=\CONTEXT\ Color Macros, +%D subtitle=SVG] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA, See mreadme.pdf for +%C details. + +%D This module was prepared by an user who wants to stay anonymous and is +%D derived from \url {http://www.december.com/html/spec/colorsvghex.html}. + +\startprotectedcolors + +\definecolor [black] [h=000000] +\definecolor [navy] [h=000080] +\definecolor [darkblue] [h=00008B] +\definecolor [mediumblue] [h=0000CD] +\definecolor [blue] [h=0000FF] +\definecolor [darkgreen] [h=006400] +\definecolor [green] [h=008000] +\definecolor [teal] [h=008080] +\definecolor [darkcyan] [h=008B8B] +\definecolor [deepskyblue] [h=00BFFF] +\definecolor [darkturquoise] [h=00CED1] +\definecolor [mediumspringgreen] [h=00FA9A] +\definecolor [lime] [h=00FF00] +\definecolor [springgreen] [h=00FF7F] +\definecolor [cyan] [h=00FFFF] +\definecolor [aqua] [h=00FFFF] +\definecolor [midnightblue] [h=191970] +\definecolor [dodgerblue] [h=1E90FF] +\definecolor [lightseagreen] [h=20B2AA] +\definecolor [forestgreen] [h=228B22] +\definecolor [seagreen] [h=2E8B57] +\definecolor [darkslategray] [h=2F4F4F] +\definecolor [darkslategrey] [h=2F4F4F] +\definecolor [limegreen] [h=32CD32] +\definecolor [mediumseagreen] [h=3CB371] +\definecolor [turquoise] [h=40E0D0] +\definecolor [royalblue] [h=4169E1] +\definecolor [steelblue] [h=4682B4] +\definecolor [darkslateblue] [h=483D8B] +\definecolor [mediumturquoise] [h=48D1CC] +\definecolor [indigo] [h=4B0082] +\definecolor [darkolivegreen] [h=556B2F] +\definecolor [cadetblue] [h=5F9EA0] +\definecolor [cornflowerblue] [h=6495ED] +\definecolor [mediumaquamarine] [h=66CDAA] +\definecolor [dimgrey] [h=696969] +\definecolor [dimgray] [h=696969] +\definecolor [slateblue] [h=6A5ACD] +\definecolor [olivedrab] [h=6B8E23] +\definecolor [slategrey] [h=708090] +\definecolor [slategray] [h=708090] +\definecolor [lightslategray] [h=778899] +\definecolor [lightslategrey] [h=778899] +\definecolor [mediumslateblue] [h=7B68EE] +\definecolor [lawngreen] [h=7CFC00] +\definecolor [chartreuse] [h=7FFF00] +\definecolor [aquamarine] [h=7FFFD4] +\definecolor [maroon] [h=800000] +\definecolor [purple] [h=800080] +\definecolor [olive] [h=808000] +\definecolor [gray] [h=808080] +\definecolor [grey] [h=808080] +\definecolor [skyblue] [h=87CEEB] +\definecolor [lightskyblue] [h=87CEFA] +\definecolor [blueviolet] [h=8A2BE2] +\definecolor [darkred] [h=8B0000] +\definecolor [darkmagenta] [h=8B008B] +\definecolor [saddlebrown] [h=8B4513] +\definecolor [darkseagreen] [h=8FBC8F] +\definecolor [lightgreen] [h=90EE90] +\definecolor [mediumpurple] [h=9370DB] +\definecolor [darkviolet] [h=9400D3] +\definecolor [palegreen] [h=98FB98] +\definecolor [darkorchid] [h=9932CC] +\definecolor [yellowgreen] [h=9ACD32] +\definecolor [sienna] [h=A0522D] +\definecolor [brown] [h=A52A2A] +\definecolor [darkgray] [h=A9A9A9] +\definecolor [darkgrey] [h=A9A9A9] +\definecolor [lightblue] [h=ADD8E6] +\definecolor [greenyellow] [h=ADFF2F] +\definecolor [paleturquoise] [h=AFEEEE] +\definecolor [lightsteelblue] [h=B0C4DE] +\definecolor [powderblue] [h=B0E0E6] +\definecolor [firebrick] [h=B22222] +\definecolor [darkgoldenrod] [h=B8860B] +\definecolor [mediumorchid] [h=BA55D3] +\definecolor [rosybrown] [h=BC8F8F] +\definecolor [darkkhaki] [h=BDB76B] +\definecolor [silver] [h=C0C0C0] +\definecolor [mediumvioletred] [h=C71585] +\definecolor [indianred] [h=CD5C5C] +\definecolor [peru] [h=CD853F] +\definecolor [chocolate] [h=D2691E] +\definecolor [tan] [h=D2B48C] +\definecolor [lightgray] [h=D3D3D3] +\definecolor [lightgrey] [h=D3D3D3] +\definecolor [thistle] [h=D8BFD8] +\definecolor [orchid] [h=DA70D6] +\definecolor [goldenrod] [h=DAA520] +\definecolor [palevioletred] [h=DB7093] +\definecolor [crimson] [h=DC143C] +\definecolor [gainsboro] [h=DCDCDC] +\definecolor [plum] [h=DDA0DD] +\definecolor [burlywood] [h=DEB887] +\definecolor [lightcyan] [h=E0FFFF] +\definecolor [lavender] [h=E6E6FA] +\definecolor [darksalmon] [h=E9967A] +\definecolor [violet] [h=EE82EE] +\definecolor [palegoldenrod] [h=EEE8AA] +\definecolor [lightcoral] [h=F08080] +\definecolor [khaki] [h=F0E68C] +\definecolor [aliceblue] [h=F0F8FF] +\definecolor [honeydew] [h=F0FFF0] +\definecolor [azure] [h=F0FFFF] +\definecolor [sandybrown] [h=F4A460] +\definecolor [wheat] [h=F5DEB3] +\definecolor [beige] [h=F5F5DC] +\definecolor [whitesmoke] [h=F5F5F5] +\definecolor [mintcream] [h=F5FFFA] +\definecolor [ghostwhite] [h=F8F8FF] +\definecolor [salmon] [h=FA8072] +\definecolor [antiquewhite] [h=FAEBD7] +\definecolor [linen] [h=FAF0E6] +\definecolor [lightgoldenrodyellow] [h=FAFAD2] +\definecolor [oldlace] [h=FDF5E6] +\definecolor [red] [h=FF0000] +\definecolor [fuchsia] [h=FF00FF] +\definecolor [magenta] [h=FF00FF] +\definecolor [deeppink] [h=FF1493] +\definecolor [orangered] [h=FF4500] +\definecolor [tomato] [h=FF6347] +\definecolor [hotpink] [h=FF69B4] +\definecolor [coral] [h=FF7F50] +\definecolor [darkorange] [h=FF8C00] +\definecolor [lightsalmon] [h=FFA07A] +\definecolor [orange] [h=FFA500] +\definecolor [lightpink] [h=FFB6C1] +\definecolor [pink] [h=FFC0CB] +\definecolor [gold] [h=FFD700] +\definecolor [peachpuff] [h=FFDAB9] +\definecolor [navajowhite] [h=FFDEAD] +\definecolor [moccasin] [h=FFE4B5] +\definecolor [bisque] [h=FFE4C4] +\definecolor [mistyrose] [h=FFE4E1] +\definecolor [blanchedalmond] [h=FFEBCD] +\definecolor [papayawhip] [h=FFEFD5] +\definecolor [lavenderblush] [h=FFF0F5] +\definecolor [seashell] [h=FFF5EE] +\definecolor [cornsilk] [h=FFF8DC] +\definecolor [lemonchiffon] [h=FFFACD] +\definecolor [floralwhite] [h=FFFAF0] +\definecolor [snow] [h=FFFAFA] +\definecolor [yellow] [h=FFFF00] +\definecolor [lightyellow] [h=FFFFE0] +\definecolor [ivory] [h=FFFFF0] +\definecolor [white] [h=FFFFFF] + +\stopprotectedcolors diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua index 921612b0fd4..3c8d23abc09 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.lua @@ -43,6 +43,7 @@ local texsetattribute = tex.setattribute local texgetattribute = tex.getattribute local texgetcount = tex.getcount local texgettoks = tex.gettoks +local texgetmacro = tokens.getters.macro local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') @@ -273,7 +274,9 @@ local function forcedmodel(model) -- delayed till the backend but mp directly return 2 end elseif model == 5 then -- spot - if cmyk_okay then + if spot_okay then + return 5 + elseif cmyk_okay then return 4 elseif rgb_okay then return 3 @@ -309,7 +312,8 @@ local function definetransparency(name,n,global) end local settings = settings_to_hash_strict(n) if settings then - local a, t = settings.a, settings.t + local a = settings.a + local t = settings.t if a and t then definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global) else @@ -440,16 +444,23 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent else local settings = settings_to_hash_strict(str) if settings then - local r, g, b = settings.r, settings.g, settings.b + local r = settings.r + local g = settings.g + local b = settings.b if r or g or b then -- we can consider a combined rgb cmyk s definition definecolor(name, register_color(name,'rgb', tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0), global) else - local c, m, y, k = settings.c, settings.m, settings.y, settings.k + local c = settings.c + local m = settings.m + local y = settings.y + local k = settings.k if c or m or y or k then definecolor(name, register_color(name,'cmyk',tonumber(c) or 0, tonumber(m) or 0, tonumber(y) or 0, tonumber(k) or 0), global) else - local h, s, v = settings.h, settings.s, settings.v + local h = settings.h + local s = settings.s + local v = settings.v if v then r, g, b = colors.hsvtorgb(tonumber(h) or 0, tonumber(s) or 1, tonumber(v) or 1) -- maybe later native definecolor(name, register_color(name,'rgb',r,g,b), global) @@ -468,7 +479,8 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent end end end - local a, t = settings.a, settings.t + local a = settings.a + local t = settings.t if a and t then definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global) elseif colors.couple then @@ -520,7 +532,8 @@ local function definespotcolor(name,parent,str,global) do_registerspotcolor(parent,cp,t.e,1,"",tp) -- p not really needed, only diagnostics if name and name ~= "" then definecolor(name,register_color(name,'spot',parent,1,"",tp),true) - local ta, tt = t.a, t.t + local ta = t.a + local tt = t.t if ta and tt then definetransparent(name, transparencies.register(name,transparent[ta] or tonumber(ta) or 1,tonumber(tt) or 1), global) elseif colors.couple then @@ -564,7 +577,7 @@ local function f(i,colors,fraction) return otf end -local function definemixcolor(makename,name,fractions,cs,global,freeze) +local function definemixcolor(makecolor,name,fractions,cs,global,freeze) local values = { } for i=1,#cs do -- do fraction in here local v = colorvalues[cs[i]] @@ -592,12 +605,15 @@ local function definemixcolor(makename,name,fractions,cs,global,freeze) end definecolor(name,ca,global,freeze) else - report_colors("invalid specification of components for color %a",makename) + report_colors("invalid specification of components for color %a",makecolor) end end local function definemultitonecolor(name,multispec,colorspec,selfspec) - local dd, pp, nn, max = { }, { }, { }, 0 + local dd = { } + local pp = { } + local nn = { } + local max = 0 for k,v in gmatch(multispec,"([^=,]+)=([^%,]*)") do -- use settings_to_array max = max + 1 dd[max] = k @@ -608,12 +624,12 @@ local function definemultitonecolor(name,multispec,colorspec,selfspec) nn = concat(nn,'_') local parent = gsub(lower(nn),"[^%d%a%.]+","_") if not colorspec or colorspec == "" then + -- this can happens when we come from metapost local cc = { } for i=1,max do --- cc[i] = l_color[dd[i]] cc[i] = resolvedname(dd[i]) end - definemixcolor(name,parent,pp,cc,global,freeze) -- can become local + definemixcolor(name,parent,pp,cc,true,true) else if selfspec ~= "" then colorspec = colorspec .. "," .. selfspec @@ -645,24 +661,29 @@ colors.definemultitonecolor = definemultitonecolor -- that we cannot cast .. so we really need to use (s,s,s) for gray in order -- to be able to map onto 'color' -local function mpcolor(model,ca,ta,default) +local function mpcolor(model,ca,ta,default,name) local cv = colorvalues[ca] if cv then local tv = transparencyvalues[ta] + -- maybe move the 5 logic into the forcedmodel call + local cm = cv[1] if model == 1 then - model = cv[1] + model = cm end model = forcedmodel(model) + if cm == 5 and model == 4 then + model = 5 -- a cheat but ok as spot colors have a representation + end if tv then if model == 2 then return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) elseif model == 3 then return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) elseif model == 4 then - return formatters["transparent(%s,%s,cmyk(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9]) + return formatters["transparent(%s,%s,(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9]) elseif model == 5 then -- return formatters['transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))'](tv[1],tv[2],cv[10],cv[11],cv[12],cv[13]) - return formatters['transparent(%s,%s,namedcolor("%s"))'](tv[1],tv[2],cv[10]) + return formatters['transparent(%s,%s,namedcolor("%s"))'](tv[1],tv[2],name or cv[10]) else -- see ** in meta-ini.mkiv: return formatters["transparent(%s,%s,(%s))"](tv[1],tv[2],cv[2]) return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5]) end @@ -672,10 +693,9 @@ local function mpcolor(model,ca,ta,default) elseif model == 3 then return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5]) elseif model == 4 then - return formatters["cmyk(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9]) + return formatters["(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9]) elseif model == 5 then - -- return formatters['multitonecolor("%s",%s,"%s","%s")'](cv[10],cv[11],cv[12],cv[13]) - return formatters['namedcolor("%s")'](cv[10]) + return formatters['namedcolor("%s")'](name or cv[10]) else -- see ** in meta-ini.mkiv: return formatters["%s"]((cv[2])) return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5]) end @@ -698,7 +718,8 @@ local paletnamespace = getnamespace("colorpalet") local function namedcolorattributes(name) local space = texgetattribute(a_colormodel) - local prefix = texgettoks("t_colo_prefix") + ----- prefix = texgettoks("t_colo_prefix") + local prefix = texgetmacro("currentcolorprefix") local color if prefix ~= "" then color = valid[prefix..name] @@ -734,7 +755,8 @@ end colors.namedcolorattributes = namedcolorattributes -- can be used local local function mpnamedcolor(name) - return mpcolor(namedcolorattributes(name)) + local model, ca, ta = namedcolorattributes(name) + return mpcolor(model,ca,ta,nil,name) end local function mpoptions(model,ca,ta,default) -- will move to mlib-col .. not really needed @@ -1090,7 +1112,7 @@ implement { implement { name = "defineprocesscolordummy", actions = defineprocesscolor, - arguments = { "'d_u_m_m_y'", "string", false, false } + arguments = { "'c_o_l_o_r'", "string", false, false } } implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv index daee8ada6a6..7079322f7a2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/colo-ini.mkiv @@ -592,22 +592,22 @@ % \the\everysetuppalet % \colo_helpers_initialize_maintextcolor} -\newtoks\t_colo_prefix % used in mp interface +% \newtoks\t_colo_prefix % used in mp interface \def\colo_palets_setup[#1]% {\edef\currentcolorpalet{#1}% \ifx\currentcolorpalet\empty % seems to be a reset \let\currentcolorprefix\empty - \t_colo_prefix\emptytoks + %\t_colo_prefix\emptytoks \else\ifcsname\??paletlist\currentcolorpalet\endcsname \edef\currentcolorprefix{#1:}% - \t_colo_prefix\expandafter{\currentcolorprefix}% + %\t_colo_prefix\expandafter{\currentcolorprefix}% \else \colo_helpers_show_message\m!colors7\currentcolorpalet \let\currentcolorpalet\empty \let\currentcolorprefix\empty - \t_colo_prefix\emptytoks + %\t_colo_prefix\emptytoks \fi\fi \the\everysetuppalet \colo_helpers_initialize_maintextcolor} @@ -782,7 +782,12 @@ % Since we couple definitions, we could stick to one test. Todo. Same for mpcolor. -\def\v_colo_dummy_name{d_u_m_m_y} +\def\v_colo_dummy_name{c_o_l_o_r} + +\letvalue{\??colorattribute \v_colo_dummy_name}\empty +\letvalue{\??transparencyattribute\v_colo_dummy_name}\empty +\letvalue{\??colorsetter \v_colo_dummy_name}\empty +\letvalue{\??transparencysetter \v_colo_dummy_name}\empty \letvalue{\??colorsetter -}\empty % used? \letvalue{\??transparencysetter-}\empty % used? @@ -942,7 +947,7 @@ \def\colo_basics_defined_and_activated#1% {\clf_defineprocesscolordummy{#1}% we could pass dummy here too - \colo_basics_synchronize{d_u_m_m_y}% + \colo_basics_synchronize{\v_colo_dummy_name}% \colo_helpers_activate_dummy} \def\colo_basics_define_process @@ -1058,7 +1063,7 @@ %D Here is a more efficient helper for pgf: %D -%D \starttying +%D \starttyping %D \startluacode %D function commands.pgfxcolorspec(ca) -- {}{}{colorspace}{list} %D local cv = attributes.colors.values[ca] diff --git a/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua b/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua index 2e4cca5ab7c..2e7ae08e3a4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/colo-run.lua @@ -14,7 +14,7 @@ local commands = commands local context = context local colors = attributes.colors -local private = table.tohash { "d_u_m_m_y", "maintextcolor", "themaintextcolor" } +local private = table.tohash { "c_o_l_o_r", "maintextcolor", "themaintextcolor" } function commands.showcolorset(name) local set = colors.setlist(name) diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv index 8b4660f3a1d..f9fc6a8f765 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/cont-log.mkiv @@ -133,7 +133,7 @@ \let\logofont\nullfont -\loadmapfile[original-base.map] % stil needed? not if we assume afm +% \loadmapfile[original-base.map] % stil needed? not if we assume afm \unexpanded\def\setMFPfont% more sensitive for low level changes {\font\logofont=logo% @@ -205,7 +205,7 @@ \unexpanded\def\Lua {Lua} \unexpanded\def\luajitTeX{luajit\wordboundary\TeX} \unexpanded\def\metaTeX {meta\wordboundary\TeX} -\unexpanded\def\XeTeX {X\lower.5\exheight\hbox{\kern-.15\emwidth\mirror{E}}\kern-.1667\emwidth\TeX} +%unexpanded\def\XeTeX {X\lower.5\exheight\hbox{\kern-.15\emwidth\mirror{E}}\kern-.1667\emwidth\TeX} % Adapted from a patch by Mojca: @@ -237,40 +237,6 @@ \let\LuaTeX \luaTeX \let\XETEX \XeTeX -% \unexpanded\def\MkApproved % joke, not used so it might move -% {\dontleavehmode\rotate -% [\c!rotation={\ifnum\texengine=\luatexengine\cldcontext{45-45*\the\luatexversion/100}\else0\fi}, -% \c!align=\v!middle, -% \c!foregroundstyle=\v!type, -% \c!foregroundcolor=darkred, -% \c!frame=\v!on, -% \c!offset=1ex, -% \c!background=\v!color, -% \c!backgroundcolor=lightgray, -% \c!framecolor=darkred, -% \c!rulethickness=2pt] -% {Mk\ifnum\texengine=\luatexengine IV\else II\fi\\approved}} - -% \unexpanded\def\luaTeX -% {\dontleavehmode\begingroup -% Lua% -% \setbox0\hbox{oT}% -% \setbox2\hbox{o\kern0ptT}% -% \ifdim\wd0=\wd2 -% \setbox0\hbox dir TRT{To}% -% \setbox2\hbox{T\kern0pto}% -% \hskip\dimexpr\wd0-\wd2\relax -% \fi -% \TeX -% \endgroup} -% -% a further iteration from the list, patched again - -% \ifx\fontalternative\s!it -\else -% \ifx\fontalternative\s!sl -\else -% \ifx\fontalternative\s!bi -\else -% \ifx\fontalternative\s!bs -\fi\fi\fi\fi - \unexpanded\def\LuaTeX {\dontleavehmode \begingroup @@ -317,6 +283,8 @@ \unexpanded\def\MPIV{MpIV} \unexpanded\def\MPVI{MpVI} +\unexpanded\def\LMTX{lmtx} + \appendtoks \def\ConTeXt {ConTeXt}% \def\MetaPost {MetaPost}% diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv index 9cb89326039..f8abf6fad98 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv @@ -11,13 +11,27 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2018.04.04 00:51} +\newcontextversion{2019.02.22 19:35} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. \unprotect -% \writestatus\m!system{beware: some patches loaded from cont-new.mkiv} +\writestatus\m!system{beware: some patches loaded from cont-new.mkiv} + +% math-ini.mkiv + +\ifdefined\t \else \unexpanded\def\t{\mathortext\text\mathtext} \fi +\ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi + +\appendtoks + \let\t\mathtext + \let\w\mathword +\to \everymathematics + +% \let\assumelongusagecs\relax % todo: fails on legends-001.tex + +% done \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua b/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua index 9bd252e6098..2634654fe77 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/cont-run.lua @@ -142,6 +142,7 @@ trackers.register("sandbox.tracecalls",sandbox.logcalls) trackers.register("sandbox.tracefiles",sandbox.logfiles) local sandboxing = environment.arguments.sandbox +local debugging = environment.arguments.debug if sandboxing then @@ -170,15 +171,33 @@ if sandboxing then \let\normalprimitive\relax ]] -end + debug = { + traceback = traceback, + } -local function processjob() + package.loaded.debug = debug - environment.initializefilenames() -- todo: check if we really need to pre-prep the filename +elseif debugging then + + -- we keep debug + +else + + debug = { + traceback = traceback, + getinfo = getinfo, + sethook = sethook, + } + + package.loaded.debug = debug + +end + +local preparejob preparejob = function() -- tricky: we need a hook for this local arguments = environment.arguments - local suffix = environment.suffix - local filename = environment.filename -- hm, not inputfilename ! + + environment.lmtxmode = CONTEXTLMTXMODE if arguments.nosynctex then luatex.synctex.setup { @@ -222,6 +241,24 @@ local function processjob() -- directives.enable("logs.errors",arguments.errors) -- end + preparejob = function() end + + job.prepare = preparejob + +end + +job.prepare = preparejob + +local function processjob() + + environment.initializefilenames() -- todo: check if we really need to pre-prep the filename + + local arguments = environment.arguments + local suffix = environment.suffix + local filename = environment.filename -- hm, not inputfilename ! + + preparejob() + if not filename or filename == "" then -- skip elseif suffix == "xml" or arguments.forcexml then @@ -285,7 +322,6 @@ local function processjob() -- \writestatus{system}{processing as tex} -- We have a regular tex file so no \starttext yet as we can -- load fonts. - -- context.enabletrackers { "resolvers.*" } context.input(filename) -- context.disabletrackers { "resolvers.*" } diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv index b650be67d93..f841ce53033 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/cont-run.mkiv @@ -25,19 +25,29 @@ \let\synctexsetfilename \clf_synctexsetfilename \let\synctexresetfilename\clf_synctexresetfilename \let\synctexblockfilename\clf_synctexblockfilename -\let\synctexpause \clf_synctexpause -\let\synctexresume \clf_synctexresume -\appendtoks\clf_synctexpause \to\everybeforeoutput -\appendtoks\clf_synctexresume\to\everyafteroutput +\let\synctexpause \donothing +\let\synctexresume \donothing +\let\synctexpushline\donothing +\let\synctexpopline \donothing + +\appendtoks\synctexpause \to\everybeforeoutput +\appendtoks\synctexresume\to\everyafteroutput \unexpanded\def\setupsynctex[#1]% {\begingroup \getdummyparameters[\c!state=\v!stop,\c!method=\v!max,#1]% + \edef\p_state{\dummyparameter\c!state}% \clf_setupsynctex - state {\dummyparameter\c!state}% + state {\p_state}% method {\dummyparameter\c!method}% \relax + \ifx\p_state\v!start + \glet\synctexpause \clf_synctexpause + \glet\synctexresume \clf_synctexresume + \glet\synctexpushline\clf_synctexpushline + \glet\synctexpopline \clf_synctexpopline + \fi \endgroup} \unexpanded\def\blocksynctexfile[#1]% diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv index 9a52cfe78b1..cd01705877f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv @@ -42,9 +42,13 @@ %D has to match \type {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2018.04.04 00:51} +\edef\contextversion{2019.02.22 19:35} \edef\contextkind {beta} +%D Kind of special: + +\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax + %D For those who want to use this: \let\fmtname \contextformat @@ -77,8 +81,8 @@ %D We just quit if new functionality is expected. -\ifnum\luatexversion<105 % also change message - \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.05!} +\ifnum\luatexversion<109 % also change message + \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.09!} \expandafter\end \fi @@ -99,6 +103,7 @@ \loadmarkfile{luat-cod} \loadmarkfile{luat-bas} \loadmarkfile{luat-lib} +\loadmarkfile{luat-soc} \loadmarkfile{catc-ini} \loadmarkfile{catc-act} @@ -106,6 +111,7 @@ \loadmarkfile{catc-ctx} \loadmarkfile{catc-sym} +\loadmarkfile{toks-ini} \loadmarkfile{cldf-ini} % \tracecatcodetables @@ -114,7 +120,7 @@ % \unexpanded long before etex came around. \loadmarkfile{luat-ini} -\loadmarkfile{toks-ini} +\loadmarkfile{toks-scn} \loadmarkfile{syst-aux} \loadmarkfile{syst-lua} @@ -125,13 +131,18 @@ \loadmarkfile{luat-usr} -% \loadmarkfile{luat-ini} % moved up -% \loadmarkfile{toks-ini} % moved up - \loadmkvifile{file-ini} \loadmkvifile{file-res} \loadmkvifile{file-lib} +\doifelsefileexists{core-lmt.mkiv} {\loadmarkfile{core-lmt}} {} + +% needs more checking for clashes: +% +% no need to register, just execute once, slightly faster +% +% \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{} + \loadmarkfile{supp-dir} \loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini @@ -153,6 +164,7 @@ % \loadmarkfile{luat-ini} \loadmarkfile{toks-tra} +\loadmarkfile{toks-aux} %loadmarkfile{toks-map} % obsolete, never used \loadmarkfile{attr-ini} @@ -170,6 +182,8 @@ \loadmarkfile{node-mig} %loadmarkfile{node-pag} +\loadmarkfile{driv-ini} + \loadmarkfile{back-ini} \loadmarkfile{attr-col} @@ -202,6 +216,7 @@ \loadmkvifile{file-syn} \loadmkvifile{file-mod} +\loadmarkfile{core-sys} \loadmarkfile{core-con} \loadmarkfile{cont-fil} @@ -274,7 +289,6 @@ \loadmarkfile{spac-lin} \loadmarkfile{spac-pag} \loadmarkfile{spac-par} -%loadmarkfile{spac-adj} % no longer needed \loadmarkfile{spac-def} \loadmkvifile{spac-prf} \loadmarkfile{spac-grd} @@ -296,7 +310,7 @@ \loadmarkfile{strc-lab} \loadmarkfile{strc-syn} -\loadmarkfile{core-sys} +% \loadmarkfile{core-sys} \loadmarkfile{page-var} \loadmkvifile{page-otr} @@ -319,9 +333,11 @@ \loadmarkfile{page-pst} \loadmkvifile{page-mbk} -\loadmarkfile{page-mul} % partly overloaded -\loadmarkfile{page-mix} % new -\loadmarkfile{page-set} +%loadmarkfile{page-mul} % \usecolumns[old-multicolumns] +\loadmarkfile{page-mix} +\loadmarkfile{page-smp} +%loadmarkfile{page-set} % \usecolumns[old-columnsets] +\loadmarkfile{page-cst} \loadmarkfile{page-pcl} % new \loadmarkfile{pack-lyr} \loadmarkfile{pack-pos} @@ -507,6 +523,7 @@ \loadmkvifile{strc-not} \loadmkvifile{strc-lnt} +\loadmkivfile{strc-usr} \loadmarkfile{pack-com} \loadmarkfile{typo-del} @@ -547,7 +564,7 @@ \loadmarkfile{cont-log} -\loadmarkfile{task-ini} +% \loadmarkfile{task-ini} \loadmarkfile{cldf-ver} % verbatim, this can come late \loadmarkfile{cldf-com} % commands, this can come late @@ -565,13 +582,24 @@ \loadmarkfile{back-exp} \loadmarkfile{back-pdf} % actually, this one should load the next three using document.arguments.backend + \loadmarkfile{mlib-pdf} \loadmarkfile{mlib-pps} \loadmarkfile{meta-pdf} +\loadmarkfile{meta-blb} \loadmarkfile{grph-epd} +\loadmarkfile{math-inc} % an experiment +\loadmarkfile{publ-inc} % an experiment + +\loadmarkfile{task-ini} + +\loadmarkfile{syst-cmp} % compatibility stuff moved here + \loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv) +\doifelsefileexists{driv-shp.mkiv} {\loadmarkfile{driv-shp}} {} + \setupcurrentlanguage[\defaultlanguagetag] \prependtoks @@ -582,6 +610,14 @@ \ctxlua{statistics.stoptiming(statistics)}% \to \everyjob +% \appendtoks +% \ctxlua{job.prepare()}% +% \to \everyjob + +% \appendtoks +% \enabletrackers[*]% +% \to \everyjob + \appendtoks \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkiv","\contextkind","\contextbanner")}% can become automatic \to \everydump diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.lua b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua index 87b4c063eaa..3829efc9c82 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-con.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.lua @@ -16,7 +16,7 @@ slower but look nicer this way.

Some code may move to a module in the language namespace.

--ldx]]-- -local floor, date, time, concat = math.floor, os.date, os.time, table.concat +local floor, osdate, ostime, concat = math.floor, os.date, os.time, table.concat local lower, upper, rep, match, gsub = string.lower, string.upper, string.rep, string.match, string.gsub local utfchar, utfbyte = utf.char, utf.byte local tonumber, tostring, type, rawset = tonumber, tostring, type, rawset @@ -33,6 +33,7 @@ local setmetatableindex = table.setmetatableindex local formatters = string.formatters local variables = interfaces.variables local constants = interfaces.constants +local addformatter = utilities.strings.formatters.add local texset = tex.set @@ -42,6 +43,9 @@ local converters = converters languages = languages or { } local languages = languages +local helpers = converters.helpers or { } +converters.helpers = helpers + local ctx_labeltext = context.labeltext local ctx_LABELTEXT = context.LABELTEXT local ctx_space = context.space @@ -304,14 +308,14 @@ local function leapyear(year) end local function textime() - return tonumber(date("%H")) * 60 + tonumber(date("%M")) + return tonumber(osdate("%H")) * 60 + tonumber(osdate("%M")) end -function converters.year () return date("%Y") end -function converters.month () return date("%m") end -function converters.hour () return date("%H") end -function converters.minute() return date("%M") end -function converters.second() return date("%S") end +function converters.year () return osdate("%Y") end +function converters.month () return osdate("%m") end +function converters.hour () return osdate("%H") end +function converters.minute() return osdate("%M") end +function converters.second() return osdate("%S") end converters.weekday = weekday converters.isleapyear = isleapyear @@ -323,11 +327,11 @@ implement { name = "weekday", actions = { weekday, context }, arguments = { "i implement { name = "leapyear", actions = { leapyear, context }, arguments = { "integer" } } implement { name = "nofdays", actions = { nofdays, context }, arguments = { "integer", "integer" } } -implement { name = "year", actions = { date, context }, arguments = "'%Y'" } -implement { name = "month", actions = { date, context }, arguments = "'%m'" } -implement { name = "hour", actions = { date, context }, arguments = "'%H'" } -implement { name = "minute", actions = { date, context }, arguments = "'%M'" } -implement { name = "second", actions = { date, context }, arguments = "'%S'" } +implement { name = "year", actions = { osdate, context }, arguments = "'%Y'" } +implement { name = "month", actions = { osdate, context }, arguments = "'%m'" } +implement { name = "hour", actions = { osdate, context }, arguments = "'%H'" } +implement { name = "minute", actions = { osdate, context }, arguments = "'%M'" } +implement { name = "second", actions = { osdate, context }, arguments = "'%S'" } implement { name = "textime", actions = { textime, context } } implement { @@ -1222,45 +1226,108 @@ setmetatableindex(months, function(t,k) return "unknown" end) setmetatableindex(days, function(t,k) return "unknown" end) setmetatableindex(monthmnems, function(t,k) return months[k] .. ":mnem" end) -local function dayname(n) - return days[n] -end +do -local function weekdayname(day,month,year) - return days[weekday(day,month,year)] -end + local function dayname(n) + ctx_labeltext(days[n]) + end -local function monthname(n) - return months[n] -end + local function weekdayname(day,month,year) + ctx_labeltext(days[weekday(day,month,year)]) + end -local function monthmnem(n) - return monthmnems[n] -end + local function monthname(n) + ctx_labeltext(months[n]) + end -implement { - name = "dayname", - actions = { dayname, ctx_labeltext }, - arguments = "integer", -} + local function monthmnem(n) + ctx_labeltext(monthmnems[n]) + end -implement { - name = "weekdayname", - actions = { weekdayname, ctx_labeltext }, - arguments = { "integer", "integer", "integer" } -} + implement { + name = "dayname", + actions = dayname, + arguments = "integer", + } -implement { - name = "monthname", - actions = { monthname, ctx_labeltext }, - arguments = { "integer" } -} + implement { + name = "weekdayname", + actions = weekdayname, + arguments = { "integer", "integer", "integer" } + } -implement { - name = "monthmnem", - actions = { monthmnem, ctx_labeltext }, - arguments = { "integer" } -} + implement { + name = "monthname", + actions = monthname, + arguments = { "integer" } + } + + implement { + name = "monthmnem", + actions = monthmnem, + arguments = { "integer" } + } + + local f_monthlong = formatters["\\monthlong{%s}"] + local f_monthshort = formatters["\\monthshort{%s}"] + local f_weekday = formatters["\\weekday{%s}"] + local f_dayoftheweek = formatters["\\dayoftheweek{%s}{%s}{%s}"] + + local function tomonthlong (m) return f_monthlong (tonumber(m) or 1) end + local function tomonthshort(m) return f_monthshort(tonumber(m) or 1) end + local function toweekday (d) return f_weekday (tonumber(d) or 1) end + + local function todayoftheweek(d,m,y) + return f_dayoftheweek(tonumber(d) or 1,tonumber(m) or 1,tonumber(y) or 2000) + end + + addformatter(formatters,"monthlong", [[tomonthlong(%s)]], { tomonthlong = tomonthlong }) + addformatter(formatters,"monthshort", [[tomonthshort(%s)]], { tomonthshort = tomonthshort }) + addformatter(formatters,"weekday", [[toweekday(%s)]], { toweekday = toweekday }) + addformatter(formatters,"dayoftheweek",[[todayoftheweek(%s,%s,%s)]],{ todayoftheweek = todayoftheweek }) + + -- using %t is slower, even with caching as we seldom use > 3 items per epoch + + local function toeyear (e) return osdate("%Y",tonumber(e)) end + local function toemonth (e) return osdate("%m",tonumber(e)) end + local function toeday (e) return osdate("%d",tonumber(e)) end + local function toeminute(e) return osdate("%M",tonumber(e)) end + local function toesecond(e) return osdate("%S",tonumber(e)) end + + local function toemonthlong(e) + return f_monthlong(tonumber(osdate("%m",tonumber(e)))) + end + + local function toemonthshort(e) + return f_monthshort(tonumber(osdate("%m",tonumber(e)))) + end + + local function toeweek(e) -- we run from 1-7 not 0-6 + return tostring(tonumber(osdate("%w",tonumber(e)))+1) + end + + local function toeweekday(e) + return f_weekday(tonumber(osdate("%w",tonumber(e)))+1) + end + + local function toedate(format,e) + return osdate(format,tonumber(e)) + end + + addformatter(formatters,"eyear", [[toeyear(%s)]], { toeyear = toeyear }) + addformatter(formatters,"emonth", [[toemonth(%s)]], { toemonth = toemonth }) + addformatter(formatters,"eday", [[toeday(%s)]], { toeday = toeday }) + addformatter(formatters,"eweek", [[toeweek(%s)]], { toeweek = toeweek }) + addformatter(formatters,"eminute", [[toeminute(%s)]], { toeminute = toeminute }) + addformatter(formatters,"esecond", [[toesecond(%s)]], { toesecond = toesecond }) + + addformatter(formatters,"emonthlong", [[toemonthlong(%s)]], { toemonthlong = toemonthlong }) + addformatter(formatters,"emonthshort", [[toemonthshort(%s)]], { toemonthshort = toemonthshort }) + addformatter(formatters,"eweekday", [[toeweekday(%s)]], { toeweekday = toeweekday }) + + addformatter(formatters,"edate", [[toedate(%s,%s)]], { toedate = toedate }) + +end -- a prelude to a function that we can use at the lua end @@ -1287,125 +1354,146 @@ local variants = { jalali = setmetatableindex(function(t,k) return months[k] .. ":jalali" end), } -local function currentdate(str,currentlanguage) -- second argument false : no label - local list = utilities.parsers.settings_to_array(str) - local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right - local year = tex.year - local month = tex.month - local day = tex.day - local auto = true - if currentlanguage == "" then - currentlanguage = false - end - for i=1,#list do - local entry = list[i] - local convert = dateconverters[entry] - if convert then - year, month, day = convert(year,month,day) - else - local tag, plus = splitlabel(entry) - local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false - if not tag then - tag = entry - elseif plus == "+" or plus == "ord" then - ordinal = true - elseif plus == "++" or plus == "highord" then - ordinal = true - highordinal = true - -- elseif plus == "mnem" then - -- mnemonic = true - elseif plus then -- elseif plus == "mnem" then - mnemonic = variants[plus] - end - if not auto and spaced[tag] then - ctx_space() - end - auto = false - if tag == v_year or tag == "y" or tag == "Y" then - context(year) - elseif tag == "yy" or tag == "YY" then - context("%02i",year % 100) - elseif tag == v_month or tag == "m" then - if currentlanguage == false then - context(Word(months[month])) - elseif mnemonic then - ctx_labeltext(variables[mnemonic[month]]) - else - ctx_labeltext(variables[months[month]]) +do + + local function currentdate(str,currentlanguage,year,month,day) -- second argument false : no label + local list = utilities.parsers.settings_to_array(str) + local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right + -- local year = tex.year + -- local month = tex.month + -- local day = tex.day + local auto = true + if currentlanguage == "" then + currentlanguage = false + end + for i=1,#list do + local entry = list[i] + local convert = dateconverters[entry] + if convert then + year, month, day = convert(year,month,day) + else + local tag, plus = splitlabel(entry) + local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false + if not tag then + tag = entry + elseif plus == "+" or plus == "ord" then + ordinal = true + elseif plus == "++" or plus == "highord" then + ordinal = true + highordinal = true + -- elseif plus == "mnem" then + -- mnemonic = true + elseif plus then -- elseif plus == "mnem" then + mnemonic = variants[plus] end - elseif tag == v_MONTH then - if currentlanguage == false then - context(Word(variables[months[month]])) - elseif mnemonic then - ctx_LABELTEXT(variables[mnemonic[month]]) - else - ctx_LABELTEXT(variables[months[month]]) + if not auto and spaced[tag] then + ctx_space() end - elseif tag == "mm" then - context("%02i",month) - elseif tag == "M" then - context(month) - elseif tag == v_day or tag == "d" then - if currentlanguage == false then + auto = false + if tag == v_year or tag == "y" or tag == "Y" then + context(year) + elseif tag == "yy" or tag == "YY" then + context("%02i",year % 100) + elseif tag == v_month or tag == "m" then + if currentlanguage == false then + context(Word(months[month])) + elseif mnemonic then + ctx_labeltext(variables[mnemonic[month]]) + else + ctx_labeltext(variables[months[month]]) + end + elseif tag == v_MONTH then + if currentlanguage == false then + context(Word(variables[months[month]])) + elseif mnemonic then + ctx_LABELTEXT(variables[mnemonic[month]]) + else + ctx_LABELTEXT(variables[months[month]]) + end + elseif tag == "mm" then + context("%02i",month) + elseif tag == "M" then + context(month) + elseif tag == v_day or tag == "d" then + if currentlanguage == false then + context(day) + else + ctx_convertnumber(v_day,day) -- why not direct + end + whatordinal = day + elseif tag == "dd" then + context("%02i",day) + whatordinal = day + elseif tag == "D" then context(day) - else - ctx_convertnumber(v_day,day) -- why not direct + whatordinal = day + elseif tag == v_weekday or tag == "w" then + local wd = weekday(day,month,year) + if currentlanguage == false then + context(Word(days[wd])) + else + ctx_labeltext(variables[days[wd]]) + end + elseif tag == v_WEEKDAY then + local wd = weekday(day,month,year) + if currentlanguage == false then + context(Word(days[wd])) + else + ctx_LABELTEXT(variables[days[wd]]) + end + elseif tag == "W" then + context(weekday(day,month,year)) + elseif tag == v_referral then + context("%04i%02i%02i",year,month,day) + elseif tag == v_space or tag == "\\ " then + ctx_space() + auto = true + elseif tag ~= "" then + context(tag) + auto = true end - whatordinal = day - elseif tag == "dd" then - context("%02i",day) - whatordinal = day - elseif tag == "D" then - context(day) - whatordinal = day - elseif tag == v_weekday or tag == "w" then - local wd = weekday(day,month,year) - if currentlanguage == false then - context(Word(days[wd])) - else - ctx_labeltext(variables[days[wd]]) - end - elseif tag == v_WEEKDAY then - local wd = weekday(day,month,year) - if currentlanguage == false then - context(Word(days[wd])) - else - ctx_LABELTEXT(variables[days[wd]]) - end - elseif tag == "W" then - context(weekday(day,month,year)) - elseif tag == v_referral then - context("%04i%02i%02i",year,month,day) - elseif tag == v_space or tag == "\\ " then - ctx_space() - auto = true - elseif tag ~= "" then - context(tag) - auto = true - end - if ordinal and whatordinal then - if currentlanguage == false then - -- ignore - else - context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage)) + if ordinal and whatordinal then + if currentlanguage == false then + -- ignore + else + context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage)) + end end end end end -end + implement { + name = "currentdate", + arguments = { "string", "string", "string", "integer", "integer", "integer" }, + actions = function(pattern,default,language,year,month,day) + currentdate( + pattern == "" and default or pattern, + language == "" and false or language, + year, month, day + ) + end, + } + + local function todate(s,y,m,d) + if y or m or d then + return formatters["\\date[y=%s,m=%s,d=%s][%s]\\relax"](y or "",m or "",d or "",s or "") + else + return formatters["\\currentdate[%s]\\relax"](s) + end + end + + addformatter(formatters,"date", [[todate(...)]], { todate = todate }) + -- context("one: %4!date!","MONTH",2020,12,11) context.par() + -- context("one: %4!date!","month",2020,12,11) context.par() + -- context("one: %4!date!","year,-,mm,-,dd",2020,12,11) context.par() -implement { - name = "currentdate", - arguments = "3 strings", - actions = function(pattern,default,language) - currentdate( - pattern == "" and default or pattern, - language == "" and false or language - ) - end, -} + -- context("two: %3!date!","MONTH",false,12) context.par() + -- context("two: %3!date!","month",false,12) context.par() + -- context("two: %3!date!","year,-,mm,-,dd",false,12) context.par() + +end implement { name = "unihex", @@ -1586,3 +1674,4 @@ implement { } } } + diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv index b4f247fcb28..303fb12910f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-con.mkiv @@ -190,10 +190,10 @@ %D want to use as meaningful commands as possible, and because \TEX\ already %D uses up some of those, we save the original meanings. -\savenormalmeaning\time -\savenormalmeaning\year -\savenormalmeaning\month -\savenormalmeaning\day +% \savenormalmeaning\time +% \savenormalmeaning\year +% \savenormalmeaning\month +% \savenormalmeaning\day %D \macros %D {month,MONTH} @@ -218,7 +218,7 @@ %D \showsetup{month} %D \showsetup{MONTH} -\let\month \monthlong +\let\month\monthlong \unexpanded\def\MONTH #1{\WORD{\month {#1}}} \unexpanded\def\MONTHLONG #1{\WORD{\monthlong {#1}}} @@ -414,30 +414,43 @@ {\dosingleempty\syst_converters_current_date} \def\syst_converters_current_date[#1]% - {\begingroup + {\dontleavehmode + \begingroup \the\everycurrentdate - \clf_currentdate{#1}{\currentdatespecification}{\labellanguage}% + \clf_currentdate + {#1}{\currentdatespecification}{\labellanguage}% + \normalyear\normalmonth\normalday \endgroup} \unexpanded\def\date {\dodoubleempty\syst_converters_date} \def\syst_converters_date[#1][#2]% - {\begingroup + {\dontleavehmode + \begingroup + \scratchcounterone \normalyear + \scratchcountertwo \normalmonth + \scratchcounterthree\normalday \iffirstargument - \letdummyparameter\c!d\normalday - \letdummyparameter\c!m\normalmonth - \letdummyparameter\c!y\normalyear + \letdummyparameter\c!y\empty + \letdummyparameter\c!m\empty + \letdummyparameter\c!d\empty \getdummyparameters[#1]% - \normalday \directdummyparameter\c!d\relax - \normalmonth\directdummyparameter\c!m\relax - \normalyear \directdummyparameter\c!y\relax + \edef\temp{\dummyparameter\c!y}\ifx\temp\empty\else\scratchcounterone \temp\fi + \edef\temp{\dummyparameter\c!m}\ifx\temp\empty\else\scratchcountertwo \temp\fi + \edef\temp{\dummyparameter\c!d}\ifx\temp\empty\else\scratchcounterthree\temp\fi + \relax \fi - \syst_converters_current_date[#2]% + \the\everycurrentdate + \clf_currentdate + {#2}{\currentdatespecification}{\labellanguage}% + \scratchcounterone\scratchcountertwo\scratchcounterthree \endgroup} \def\rawdate[#1]% expandable and no labels - {\clf_currentdate{#1}{\currentdatespecification}{}} + {\clf_currentdate + {#1}{\currentdatespecification}{}% + \normalyear\normalmonth\normalday} %D \macros %D {currenttime} @@ -454,7 +467,7 @@ \let\currentminute\!!plusone \let\currentsecond\!!plusone -\def\currenttimespecification{h,:,m} +% \def\currenttimespecification{h,:,m} \unexpanded\def\currenttime {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop} @@ -805,61 +818,119 @@ \ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo +% \defineconversion +% [set 0] +% [{\symbol[bullet]}, +% {\symbol[dash]}, +% {\symbol[star]}, +% {\symbol[triangle]}, +% {\symbol[circle]}, +% {\symbol[medcircle]}, +% {\symbol[bigcircle]}, +% {\symbol[square]}, +% {\symbol[checkmark]}] + +% \defineconversion +% [set 1] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] +% +% \defineconversion +% [set 2] +% [\mathematics{\ast}, +% \mathematics{\dag}, +% \mathematics{\ddag}, +% \mathematics{\ast\ast}, +% \mathematics{\dag\dag}, +% \mathematics{\ddag\ddag}, +% \mathematics{\ast\ast\ast}, +% \mathematics{\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag}, +% \mathematics{\ast\ast\ast\ast}, +% \mathematics{\dag\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag\ddag}] +% +% \defineconversion +% [set 3] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\P}, +% \mathematics{\P\P}, +% \mathematics{\P\P\P}, +% \mathematics{\S}, +% \mathematics{\S\S}, +% \mathematics{\S\S\S}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] + \defineconversion [set 0] - [{\symbol[bullet]}, - {\symbol[dash]}, - {\symbol[star]}, - {\symbol[triangle]}, - {\symbol[circle]}, - {\symbol[medcircle]}, - {\symbol[bigcircle]}, - {\symbol[square]}] + [\symbol{bullet}, + \symbol{dash}, + \symbol{star}, + \symbol{triangle}, + \symbol{circle}, + \symbol{medcircle}, + \symbol{bigcircle}, + \symbol{square}, + \symbol{checkmark}] \defineconversion [set 1] - [\mathematics{\star}, - \mathematics{\star\star}, - \mathematics{\star\star\star}, - \mathematics{\ddagger}, - \mathematics{\ddagger\ddagger}, - \mathematics{\ddagger\ddagger\ddagger}, - \mathematics{\ast}, - \mathematics{\ast\ast}, - \mathematics{\ast\ast\ast}] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] \defineconversion [set 2] - [\mathematics{*}, - \mathematics{\dag}, - \mathematics{\ddag}, - \mathematics{**}, - \mathematics{\dag\dag}, - \mathematics{\ddag\ddag}, - \mathematics{***}, - \mathematics{\dag\dag\dag}, - \mathematics{\ddag\ddag\ddag}, - \mathematics{****}, - \mathematics{\dag\dag\dag\dag}, - \mathematics{\ddag\ddag\ddag\ddag}] + [\textormathchars{∗}, + \textormathchars{†}, + \textormathchars{‡}, + \textormathchars{∗∗}, + \textormathchars{††}, + \textormathchars{‡‡}, + \textormathchars{∗∗∗}, + \textormathchars{†††}, + \textormathchars{‡‡‡}, + \textormathchars{∗∗∗∗}, + \textormathchars{††††}, + \textormathchars{‡‡‡‡}] \defineconversion [set 3] - [\mathematics{\star}, - \mathematics{\star\star}, - \mathematics{\star\star\star}, - \mathematics{\ddagger}, - \mathematics{\ddagger\ddagger}, - \mathematics{\ddagger\ddagger\ddagger}, - \mathematics{\P}, - \mathematics{\P\P}, - \mathematics{\P\P\P}, - \mathematics{\S}, - \mathematics{\S\S}, - \mathematics{\S\S\S}, - \mathematics{\ast}, - \mathematics{\ast\ast}, - \mathematics{\ast\ast\ast}] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{¶}, + \textormathchars{¶¶}, + \textormathchars{¶¶¶}, + \textormathchars{§}, + \textormathchars{§§}, + \textormathchars{§§§}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] %D Iteration of suggestion by WS on mailinglist 2010.12.22: %D @@ -888,4 +959,23 @@ data {#1}% \relax} +%D For those who sart counting at zero: +%D +%D \starttyping +%D \defineconversionset [zero] [n,zero] [n] +%D +%D \setuphead [sectionconversionset=zero] +%D +%D \starttext +%D \startchapter [title=Introduction] +%D \startsection [title=First topic] \stopsection +%D \startsection [title=Second topic] \stopsection +%D \stopchapter +%D \stoptext +%D \stoptyping + +\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax} + +\defineconversion [zero] [\zeronumberconversion] + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua b/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua index fa4d089d057..b497501598b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-dat.lua @@ -15,6 +15,7 @@ local tonumber, tostring, type = tonumber, tostring, type local context = context local commands = commands +local ctx_latelua = context.latelua local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end) local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end) @@ -35,6 +36,7 @@ local v_yes = interfaces.variables.yes local new_latelua = nodes.pool.latelua local implement = interfaces.implement +local getnamespace = interfaces.getnamespace local collected = allocate() local tobesaved = allocate() @@ -106,6 +108,9 @@ end datasets.setdata = setdata function datasets.extend(name,tag) + if type(name) == "table" then + name, tag = name.name, name.tag + end local set = sets[name] local order = set.order + 1 local realpage = texgetcount("realpageno") @@ -146,10 +151,8 @@ local function setdataset(settings) local name, tag = setdata(settings) if settings.delay ~= v_yes then -- - elseif type(tag) == "number" then - context(new_latelua(formatters["job.datasets.extend(%q,%i)"](name,tag))) else - context(new_latelua(formatters["job.datasets.extend(%q,%q)"](name,tag))) + context(new_latelua { action = job.datasets.extend, name = name, tag = tag }) end end @@ -242,9 +245,7 @@ local function setstate(settings) return name, tag, data end -pagestates.setstate = setstate - -function pagestates.extend(name,tag) +local function extend(name,tag) local realpage = texgetcount("realpageno") if trace_pagestates then report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage) @@ -252,7 +253,7 @@ function pagestates.extend(name,tag) tobesaved[name][tag] = realpage end -function pagestates.realpage(name,tag,default) +local function realpage(name,tag,default) local t = collected[name] if t then t = t[tag] or t[tonumber(tag)] @@ -267,21 +268,36 @@ function pagestates.realpage(name,tag,default) return default end -local function setpagestate(settings) - local name, tag, data = setstate(settings) - if type(tag) == "number" then - context(new_latelua(formatters["job.pagestates.extend(%q,%i)"](name,tag))) - else - context(new_latelua(formatters["job.pagestates.extend(%q,%q)"](name,tag))) - end -end - -local function pagestaterealpage(name,tag) +local function realpageorder(name,tag) local t = collected[name] - t = t and (t[tag] or t[tonumber(tag)]) if t then - context(t) + local p = t[tag] + if p then + local n = 1 + for i=tag-1,1,-1 do + if t[i] == p then + n = n +1 + end + end + return n + end end + return 0 +end + +pagestates.setstate = setstate +pagestates.extend = extend +pagestates.realpage = realpage +pagestates.realpageorder = realpageorder + +function pagestates.countervalue(name) + return name and texgetcount(getnamespace("pagestatecounter") .. name) or 0 +end + +local function setpagestate(settings) + local name, tag = setstate(settings) + -- context(new_latelua(function() extend(name,tag) end)) + ctx_latelua(function() extend(name,tag) end) end local function setpagestaterealpageno(name,tag) @@ -304,7 +320,7 @@ implement { implement { name = "pagestaterealpage", - actions = pagestaterealpage, + actions = { realpage, context }, arguments = "2 strings", } @@ -313,3 +329,9 @@ implement { actions = setpagestaterealpageno, arguments = "2 strings", } + +implement { + name = "pagestaterealpageorder", + actions = { realpageorder, context }, + arguments = { "string", "integer" } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv index 3bb923af424..9f4344b99d4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-dat.mkiv @@ -73,9 +73,18 @@ {\clf_datasetvariable{#1}{#2}{#3}} \installcorenamespace{pagestate} +\installcorenamespace{pagestatecounter} \installcommandhandler \??pagestate {pagestate} \??pagestate +\def\syst_pagestates_allocate + {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname + \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname} + +\appendtoks + \syst_pagestates_allocate +\to \everydefinepagestate + \setuppagestate [\c!delay=\v!yes] @@ -85,17 +94,31 @@ \def\syst_pagestates_set[#1][#2]% {\begingroup \edef\currentpagestate{#1}% + \ifcsname\??pagestatecounter\currentpagestate\endcsname + \let\c_syst_pagestate\lastnamedcs + \else + \syst_pagestates_allocate + \fi + \global\advance\c_syst_pagestate\plusone + \scratchcounter\lastnamedcs \clf_setpagestate name {\currentpagestate}% - tag {#2}% + tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}% delay {\pagestateparameter\c!delay}% \relax \endgroup} -\def\pagestaterealpage#1#2% - {\clf_pagestaterealpage{#1}{#2}} +\unexpanded\def\autosetpagestate#1% + {\secondargumentfalse\syst_pagestates_set[#1]} + +\def\autopagestatenumber#1{\begincsname\??pagestatecounter#1\endcsname} + +\def\pagestaterealpage #1#2{\clf_pagestaterealpage {#1}{#2}} +\def\setpagestaterealpageno#1#2{\clf_setpagestaterealpageno{#1}{#2}} +\def\pagestaterealpageorder#1#2{\clf_pagestaterealpageorder{#1}#2\relax} -\def\setpagestaterealpageno#1#2% - {\clf_setpagestaterealpageno{#1}{#2}} +\def\autopagestaterealpage #1{\clf_pagestaterealpage {#1}{\number\autopagestatenumber{#1}}} +\def\setautopagestaterealpageno#1{\clf_setpagestaterealpageno{#1}{\number\autopagestatenumber{#1}}} +\def\autopagestaterealpageorder#1{\clf_pagestaterealpageorder{#1}\numexpr\autopagestatenumber{#1}\relax} \protect diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv index 9dbb16f5cab..95f7f2577d0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-def.mkiv @@ -39,7 +39,7 @@ % \flushcommentanchors \flushnotes \synchronizenotes - \OTRSETshowstatus + % \OTRSETshowstatus \registerparoptions % \flushsyncpositions \flushpostponednodedata diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-env.lua b/Master/texmf-dist/tex/context/base/mkiv/core-env.lua index 0ef37a6d6b2..50759dd1941 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-env.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-env.lua @@ -26,6 +26,7 @@ local setmetatablenewindex = table.setmetatablenewindex local setmetatablecall = table.setmetatablecall local createtoken = token.create +local isdefined = tokens.isdefined texmodes = allocate { } tex.modes = texmodes texsystemmodes = allocate { } tex.systemmodes = texsystemmodes @@ -40,18 +41,27 @@ local systemmodes = { } -- we could use the built-in tex.is[count|dimen|skip|toks] here but caching -- at the lua end is not that bad (and we need more anyway) --- undefined: mode == 0 or cmdname = "undefined_cs" - -local cache = setmetatableindex(function(t,k) - local v = createtoken(k) - t[k] = v - return v -end) +local cache = tokens.cache -- we can have a modes cache too -local iftrue = cache["iftrue"].mode -local undefined = cache["*undefined*crap*"].mode -- is this ok? +local iftrue = cache["iftrue"].mode + +local dimencode = cache["scratchdimen"] .command +local countcode = cache["scratchcounter"] .command +local tokencode = cache["scratchtoken"] .command +local skipcode = cache["scratchskip"] .command +local muskipcode = cache["scratchmuskip"] .command +----- attributecode = cache["scratchattribute"].command + +local types = { + [dimencode] = "dimen", + [countcode] = "count", + [tokencode] = "token", + [skipcode] = "skip", + [muskipcode] = "muskip", + -- [attributecode] = "attribute", +} setmetatableindex(texmodes, function(t,k) local m = modes[k] @@ -59,16 +69,17 @@ setmetatableindex(texmodes, function(t,k) return m() elseif k then local n = "mode>" .. k - if cache[n].mode == 0 then - return false - else + if isdefined(n) then rawset(modes,k, function() return texgetcount(n) == 1 end) return texgetcount(n) == 1 -- 2 is prevented + else + return false end else return false end end) + setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode",k) end) @@ -79,11 +90,11 @@ setmetatableindex(texsystemmodes, function(t,k) return m() else local n = "mode>*" .. k - if cache[n].mode == 0 then - return false - else + if isdefined(n) then rawset(systemmodes,k,function() return texgetcount(n) == 1 end) return texgetcount(n) == 1 -- 2 is prevented + else + return false end end end) @@ -112,31 +123,7 @@ setmetatablenewindex(texifs, function(t,k) -- just ignore end) -setmetatableindex(texisdefined, function(t,k) - return k and cache[k].mode ~= 0 -end) -setmetatablecall(texisdefined, function(t,k) - return k and cache[k].mode ~= 0 -end) -setmetatablenewindex(texisdefined, function(t,k) - -- just ignore -end) - -local dimencode = cache["scratchdimen"] .command -local countcode = cache["scratchcounter"] .command -local tokencode = cache["scratchtoken"] .command -local skipcode = cache["scratchskip"] .command -local muskipcode = cache["scratchmuskip"] .command ----- attributecode = cache["scratchattribute"].command - -local types = { - [dimencode] = "dimen", - [countcode] = "count", - [tokencode] = "token", - [skipcode] = "skip", - [muskipcode] = "muskip", - -- [attributecode] = "attribute", -} +tex.isdefined = isdefined function tex.isdimen(name) local hit = cache[name] diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv index c93350db04f..758ee126d1a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-env.mkiv @@ -68,6 +68,14 @@ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi \lastnamedcs\disabledmode} +\unexpanded\def\globalsetmode#1% + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \global\lastnamedcs\enabledmode} + +\unexpanded\def\globalresetmode#1% + {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi + \global\lastnamedcs\disabledmode} + \unexpanded\def\newsystemmode#1% {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi} @@ -79,6 +87,14 @@ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi \lastnamedcs\disabledmode} +\unexpanded\def\globalsetsystemmode#1% + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi + \global\lastnamedcs\enabledmode} + +\unexpanded\def\globalresetsystemmode#1% + {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi + \global\lastnamedcs\disabledmode} + % \def\dosetsystemmode#1% % {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode} % @@ -87,16 +103,18 @@ % demo: trialtypesetting is a systemmode as well as an if -\newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end) +\newsystemmode{trialtypesetting} -\expandafter\let\expandafter\@@trialtypesetting\csname\??mode\systemmodeprefix trialtypesetting\endcsname % private ! +\expandafter\let\csname\??mode\systemmodeprefix trialtypesetting\endcsname\trialtypesettingstate \appendtoks - \@@trialtypesetting\enabledmode + \trialtypesettingstate\enabledmode + \luacopyinputnodes\plusone \to \everysettrialtypesetting \appendtoks - \@@trialtypesetting\disabledmode + \trialtypesettingstate\disabledmode + \luacopyinputnodes\zerocount \to \everyresettrialtypesetting % user ones @@ -661,6 +679,24 @@ \dodoglobal\undefinevalue{\??setup:#1}% \fi} +% \unexpanded\def\resetsetups[#1]% see x-fo for usage +% {\dodoglobal\expandafter\let\csname\??setup +% \ifgridsnapping\ifcsname\??setup\v!grid:#1\endcsname\v!grid\fi +% :#1\endcsname\undefined} + +\unexpanded\def\copysetups + {\dodoubleargument\syst_setups_copy} + +% \def\syst_setups_copy[#1][#2]% +% {\ifcsname\??setup:#2\endcsname +% \expandafter\let\csname\??setup:#1\expandafter\endcsname\csname\??setup:#2\endcsname +% \fi} + +\def\syst_setups_copy[#1][#2]% + {\ifcsname\??setup:#2\endcsname + \expandafter\let\csname\??setup:#1\expandafter\endcsname\lastnamedcs + \fi} + \unexpanded\def\showsetupsdefinition[#1]% {\showvalue{\??setup:#1}} % temp hack for debugging @@ -777,7 +813,7 @@ %{\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}% {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% \ifx\m_syst_string_one\empty - \expandafter\firstoffourarguments + \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-lmt.lua b/Master/texmf-dist/tex/context/base/mkiv/core-lmt.lua new file mode 100644 index 00000000000..700ce47211e --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/core-lmt.lua @@ -0,0 +1,34 @@ +if not modules then modules = { } end modules ['core-lmt'] = { + version = 1.001, + comment = "companion to core-lmt.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local implement = interfaces.implement +local scankeyword = tokens.scanners.keyword + +local settextdir = tex.settextdir +local setlinedir = tex.setlinedir +local setpardir = tex.setpardir +local setboxdir = tex.setboxdir + +local function scandir(what) + if scankeyword("tlt") then + what(0) + elseif scankeyword("trt") then + what(1) + -- elseif scankeyword("rtt") then + -- what(2) + -- elseif scankeyword("ltl") then + -- what(3) + else + what(0) + end +end + +implement { name = "textdir", public = true, protected = true, actions = function() scandir(settextdir) end } +implement { name = "linedir", public = true, protected = true, actions = function() scandir(setlinedir) end } +implement { name = "pardir", public = true, protected = true, actions = function() scandir(setpardir) end } +implement { name = "boxdir", public = true, protected = true, actions = function() scandir(setboxdir) end } diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-lmt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-lmt.mkiv new file mode 100644 index 00000000000..eda66796918 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/core-lmt.mkiv @@ -0,0 +1,32 @@ +%D \module +%D [ file=core-lmt, +%D version=2010.08.2, +%D title=\CONTEXT\ System Macros, +%D subtitle=Primitives, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\ifcase\contextlmtxmode\expandafter\endinput\fi + +\writestatus{loading}{ConTeXt System Macros / Primitives} + +\ifdefined\textdir \else + \registerctxluafile{core-lmt}{} +\fi + +\unprotect + +% nothing yet + +\protect \endinput + +% \starttext +% abc{\textdir TRTdef}ghi +% abc{\textdir trtdef}ghi +% \boxdirection0=1 +% \stoptext diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua b/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua index 26229235b44..4078ab8a8a9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-sys.lua @@ -73,13 +73,13 @@ implement { name = "outputfilename", actions = function() context(environme statistics.register("result saved in file", function() -- suffix will be fetched from backend local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "" - if (tex.pdfoutput or tex.outputmode) > 0 then + -- if (tex.pdfoutput or tex.outputmode) > 0 then return format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf", lpdf.getcompression() ) - else - return format("%s.%s",outputfilename,"dvi") -- hard to imagine - end + -- else + -- return format("%s.%s",outputfilename,"dvi") -- hard to imagine + -- end end) implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-two.lua b/Master/texmf-dist/tex/context/base/mkiv/core-two.lua index 1e59004be6f..3ab2112b9aa 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-two.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-two.lua @@ -32,7 +32,7 @@ end job.register('job.passes.collected', tobesaved, initializer, nil) -local function allocate(id) +local function define(id) local p = tobesaved[id] if not p then p = { } @@ -41,10 +41,8 @@ local function allocate(id) return p end -jobpasses.define = allocate - -function jobpasses.save(id,str,index) - local jti = allocate(id) +local function save(id,str,index) + local jti = define(id) if index then jti[index] = str else @@ -52,30 +50,30 @@ function jobpasses.save(id,str,index) end end -function jobpasses.savetagged(id,tag,str) - local jti = allocate(id) +local function savetagged(id,tag,str) + local jti = define(id) jti[tag] = str end -function jobpasses.getdata(id,index,default) +local function getdata(id,index,default) local jti = collected[id] local value = jti and jti[index] return value ~= "" and value or default or "" end -function jobpasses.getfield(id,index,tag,default) +local function getfield(id,index,tag,default) local jti = collected[id] jti = jti and jti[index] local value = jti and jti[tag] return value ~= "" and value or default or "" end -function jobpasses.getcollected(id) +local function getcollected(id) return collected[id] or { } end -function jobpasses.gettobesaved(id) - return allocate(id) +local function gettobesaved(id) + return define(id) end local function get(id) @@ -87,23 +85,17 @@ end local function first(id) local jti = collected[id] - if jti and #jti > 0 then - return jti[1] - end + return jti and jti[1] end local function last(id) local jti = collected[id] - if jti and #jti > 0 then - return jti[#jti] - end + return jti and jti[#jti] end local function find(id,n) local jti = collected[id] - if jti and jti[n] then - return jti[n] - end + return jti and jti[n] or nil end local function count(id) @@ -132,44 +124,49 @@ end local check = first --- - -jobpasses.get = get -jobpasses.first = first -jobpasses.last = last -jobpasses.find = find -jobpasses.list = list -jobpasses.count = count -jobpasses.check = check -jobpasses.inlist = inlist +jobpasses.define = define +jobpasses.save = save +jobpasses.savetagged = savetagged +jobpasses.getdata = getdata +jobpasses.getfield = getfield +jobpasses.getcollected = getcollected +jobpasses.gettobesaved = gettobesaved +jobpasses.get = get +jobpasses.first = first +jobpasses.last = last +jobpasses.find = find +jobpasses.list = list +jobpasses.count = count +jobpasses.check = check +jobpasses.inlist = inlist -- interface local implement = interfaces.implement -implement { name = "gettwopassdata", actions = { get , context }, arguments = "string" } +implement { name = "gettwopassdata", actions = { get, context }, arguments = "string" } implement { name = "getfirsttwopassdata",actions = { first, context }, arguments = "string" } -implement { name = "getlasttwopassdata", actions = { last , context }, arguments = "string" } -implement { name = "findtwopassdata", actions = { find , context }, arguments = "2 strings" } -implement { name = "gettwopassdatalist", actions = { list , context }, arguments = "string" } +implement { name = "getlasttwopassdata", actions = { last, context }, arguments = "string" } +implement { name = "findtwopassdata", actions = { find, context }, arguments = "2 strings" } +implement { name = "gettwopassdatalist", actions = { list, context }, arguments = "string" } implement { name = "counttwopassdata", actions = { count, context }, arguments = "string" } implement { name = "checktwopassdata", actions = { check, context }, arguments = "string" } implement { name = "definetwopasslist", - actions = jobpasses.define, + actions = define, arguments = "string" } implement { name = "savetwopassdata", - actions = jobpasses.save, + actions = save, arguments = "2 strings", } implement { name = "savetaggedtwopassdata", - actions = jobpasses.savetagged, + actions = savetagged, arguments = "3 strings", } @@ -178,3 +175,23 @@ implement { actions = { inlist, commands.doifelse }, arguments = "2 strings", } + +-- local ctx_latelua = context.latelua + +-- implement { +-- name = "lazysavetwopassdata", +-- arguments = "3 strings", +-- public = true, +-- actions = function(a,b,c) +-- ctx_latelua(function() save(a,c) end) +-- end, +-- } + +-- implement { +-- name = "lazysavetaggedtwopassdata", +-- arguments = "3 strings", +-- public = true, +-- actions = function(a,b,c) +-- ctx_latelua(function() savetagged(a,b,c) end) +-- end, +-- } diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv b/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv index f83d630427b..aae4902bc9b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/core-two.mkiv @@ -74,10 +74,10 @@ \registerctxluafile{core-two}{} \def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\clf_savetwopassdata{#1}{#3}}} -\def\savetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}} -\def\lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}} -\def\savetaggedtwopassdata #1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}} -\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatecommand{savetaggedtwopassdata('#1','#3',"#4")}}} +\def \lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata("#1","#3")}}} +\let \savetwopassdata \lazysavetwopassdata +\def \savetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}} +\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatecommand{savetaggedtwopassdata("#1",'#3',"#4")}}} % temp hack: needs a proper \starteverytimeluacode diff --git a/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua b/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua index b281b81a42f..cd867db1bce 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/core-uti.lua @@ -43,7 +43,7 @@ local report_passes = logs.reporter("job","passes") job = job or { } local job = job -job.version = 1.30 +job.version = 1.31 job.packversion = 1.02 -- some day we will implement loading of other jobs and then we need @@ -195,6 +195,7 @@ end local packlist = { "numbers", + "ownnumbers", "metadata", "sectiondata", "prefixdata", @@ -209,6 +210,7 @@ local packlist = { local skiplist = { "datasets", "userdata", + "positions", } -- not ok as we can have arbitrary keys in userdata and dataset so some day we @@ -398,7 +400,7 @@ function statistics.callbacks() local c_internal = status.callbacks or 0 local c_file = status.indirect_callbacks or 0 local c_direct = status.direct_callbacks or 0 - local c_late = status.late_callbacks or 0 + local c_late = backends.noflatelua() or 0 local c_function = status.function_callbacks or 0 local c_total = c_internal + c_file + c_direct + c_late + c_function local n_pages = texgetcount('realpageno') - 1 @@ -430,6 +432,7 @@ end) -- local used_wood_factor = watts_per_core * kg_per_watt_per_second / speedup_by_other_engine -- local used_wood_factor = (50 / 15000000) / 1.2 + function statistics.formatruntime(runtime) if not environment.initex then -- else error when testing as not counters yet -- stoptiming(statistics) -- to be sure @@ -438,19 +441,15 @@ function statistics.formatruntime(runtime) if pages > shipped then pages = shipped end + runtime = tonumber(runtime) if shipped > 0 or pages > 0 then - runtime = tonumber(runtime) local persecond = (runtime > 0) and (shipped/runtime) or pages - if pages == 0 then pages = shipped end - -- if TEXENGINE == "luajittex" then - -- local saved = watts_per_core * runtime * kg_per_watt_per_second / speedup_by_other_engine - -- local saved = used_wood_factor * runtime - -- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f mg tree saved by using luajittex",runtime,pages,shipped,persecond,saved*1000*1000) - -- else - return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond) - -- end + if pages == 0 then + pages = shipped + end + return format("%0.3f seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond) else - return format("%s seconds",runtime) + return format("%0.3f seconds",runtime) end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua index 1e020d1e844..c57f16d2c57 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-aux.lua @@ -50,7 +50,7 @@ function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per local newdata = io.loaddata(newscript) if newdata then if trace_locating then - report_scripts("old script content replaced by new content") + report_scripts("old script content replaced by new content: %s",oldscript) end io.savedata(oldscript,newdata) break diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua b/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua index 70b2e735455..5e3020b7065 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-pre.lua @@ -6,6 +6,25 @@ if not modules then modules = { } end modules ['data-pre'] = { license = "see context related readme files" } +-- filename : only the basename, including suffix (file:) +-- pathname : the pathpart (path:) +-- locate : lookup in database (full: kpse: loc:) +-- home : home path +-- jobpath : job path +-- relative : relative path ./ ../ ../.. (rel:) +-- auto : relatove or lookup +-- toppath : topmost path in input stack +-- selfautodir : rather tex specific +-- selfautoloc : rather tex specific +-- selfautoparent : rather tex specific +-- environment : expansion of variable (env:) +-- +-- nodename : computer name +-- machine : private, when set +-- sysname : operating system name +-- version : operating system version +-- release : operating system release + local resolvers = resolvers local prefixes = resolvers.prefixes @@ -140,7 +159,6 @@ resolvers.setdynamic("toppath") resolvers.setdynamic("jobpath") -- for a while (obsolete): - -prefixes.jobfile = prefixes.jobpath - -resolvers.setdynamic("jobfile") +-- +-- prefixes.jobfile = prefixes.jobpath +-- resolvers.setdynamic("jobfile") diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-res.lua b/Master/texmf-dist/tex/context/base/mkiv/data-res.lua index 9fb33f88dce..0c2735fc274 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-res.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-res.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['data-res'] = { -- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012) local gsub, find, lower, upper, match, gmatch = string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch -local concat, insert, remove, sortedkeys, sortedhash = table.concat, table.insert, table.remove, table.sortedkeys, table.sortedhash +local concat, insert, remove = table.concat, table.insert, table.remove local next, type, rawget = next, type, rawget local os = os @@ -1875,7 +1875,7 @@ function resolvers.booleanvariable(str,default) end function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead - local hashes = instance.hashes + local hashes = instance.hashes for i=1,#hashes do local hash = hashes[i] local blobtype = hash.type @@ -1903,7 +1903,7 @@ function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, end end if after then - after(blobtype,blobpath,pattern,total,checked,done) + after(blobtype,blobpath,pattern,checked,done) end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua index 2d2c9b24d3a..8f978a204f3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-tex.lua @@ -149,19 +149,19 @@ function helpers.textopener(tag,filename,filehandle,coding) currentline = currentline + 1 -- self.currentline = currentline local content = lines[currentline] - if not content then - return nil - elseif content == "" then + if content == "" then return "" -- elseif content == ctrl_d or ctrl_z then -- return nil -- we need this as \endinput does not work in prints - else + elseif content then local runner = textlineactions.runner if runner then return runner(content,filename,currentline,noflines,coding) or content else return content end + else + return nil end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua b/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua index 4388731f98c..c4d43e3eb20 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-tre.lua @@ -100,11 +100,10 @@ end function resolvers.hashers.tree(specification) local name = specification.filename - -- if trace_locating then + if trace_locating then report_trees("analyzing %a",name) - -- end + end resolvers.methodhandler("hashers",name) - resolvers.generators.file(specification) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-use.lua b/Master/texmf-dist/tex/context/base/mkiv/data-use.lua index ff25c803ac5..5985a2eac24 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-use.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-use.lua @@ -69,7 +69,11 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile,kind,banner) - } io.savedata(luvname,table.serialize(luvdata,true)) lua.registerfinalizer(function() - logs.report("format banner","%s",banner) + if jit then + logs.report("format banner","%s lua: %s jit",banner,LUAVERSION) + else + logs.report("format banner","%s lua: %s",banner,LUAVERSION) + end logs.newline() end) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua b/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua index 32666bef268..6f20b4a9d96 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/data-zip.lua @@ -31,11 +31,11 @@ local resolvers = resolvers zip = zip or { } local zip = zip -zip.archives = zip.archives or { } -local archives = zip.archives +local archives = zip.archives or { } +zip.archives = archives -zip.registeredfiles = zip.registeredfiles or { } -local registeredfiles = zip.registeredfiles +local registeredfiles = zip.registeredfiles or { } +zip.registeredfiles = registeredfiles local function validzip(str) -- todo: use url splitter if not find(str,"^zip://") then @@ -108,7 +108,7 @@ function resolvers.finders.zip(specification) end local dfile = zfile:open(queryname) if dfile then - dfile = zfile:close() + dfile:close() if trace_locating then report_zip("finder: file %a found",queryname) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/driv-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/driv-ini.lua new file mode 100644 index 00000000000..e16327f27d7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/driv-ini.lua @@ -0,0 +1,194 @@ +if not modules then modules = { } end modules ['driv-ini'] = { + version = 1.001, + comment = "companion to driv-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 addsuffix = file.addsuffix + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local report = logs.reporter("drivers") + +local instances = { } +local helpers = { } +local prepared = { } +local wrappedup = { } +local currentdriver = "default" + +local prepare = nil +local convert = nil +local wrapup = nil +local outputfilename = nil + +drivers = drivers or { + instances = instances, + helpers = helpers, + lmtxversion = 0.10, +} + +local dummy = function() end + +local defaulthandlers = { + prepare = dummy, + initialize = dummy, + finalize = dummy, + updatefontstate = dummy, + wrapup = dummy, + convert = dummy, + outputfilename = dummy, +} + +function drivers.install(specification) + local name = specification.name + if not name then + report("missing driver name") + return + end + local actions = specification.actions + if not actions then + report("no actions for driver %a",name) + return + end + local flushers = specification.flushers + if not flushers then + report("no flushers for driver %a",name) + return + end + setmetatableindex(actions,defaulthandlers) + instances[name] = specification +end + +function drivers.convert(boxnumber) + callbacks.functions.start_page_number() + starttiming(drivers) + convert(boxnumber) + stoptiming(drivers) + callbacks.functions.stop_page_number() +end + +function drivers.outputfilename() + return outputfilename() +end + + +luatex.wrapup(function() + if not wrappedup[currentdriver] then + starttiming(drivers) + wrapup() + stoptiming(drivers) + wrappedup[currentdriver] = true + end +end) + +function drivers.enable(name) + currentdriver = name or "default" + local actions = instances[currentdriver].actions + prepare = actions.prepare + wrapup = actions.wrapup + convert = actions.convert + outputfilename = actions.outputfilename + -- + if prepare and not prepared[currentdriver] then + starttiming(drivers) + prepare() + stoptiming(drivers) + prepared[currentdriver] = true + end +end + +statistics.register("driver time",function() + return statistics.elapsedseconds(drivers) +end) + +interfaces.implement { + name = "shipoutpage", + arguments = "integer", + actions = drivers.convert, +} + +interfaces.implement { + name = "enabledriver", + arguments = "string", + actions = drivers.enable, +} + +-- The default driver: + +do + + local filename = nil + + drivers.install { + name = "default", + actions = { + convert = tex.shipout, + outputfilename = function() + if not filename then + filename = addsuffix(tex.jobname,"pdf") + end + return filename + end, + }, + flushers = { + -- we always need this entry + }, + } + +end + +setmetatableindex(instances,function() return instances.default end) + +-- for now: + +drivers.enable("default") + +-- helpers + +local s_matrix_0 = "1 0 0 1" +local f_matrix_2 = formatters["%.6F 0 0 %.6F"] +local f_matrix_4 = formatters["%.6F %.6F %.6F %.6F"] + +directives.register("pdf.stripzeros",function() + f_matrix_2 = formatters["%.6N 0 0 %.6N"] + f_matrix_4 = formatters["%.6N %.6N %.6N %.6N"] +end) + +function helpers.tomatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty + if type(rx) == "string" then + return rx + else + if not rx then + rx = 1 + elseif rx == 0 then + rx = 0.0001 + end + if not ry then + ry = 1 + elseif ry == 0 then + ry = 0.0001 + end + if not sx then + sx = 0 + end + if not sy then + sy = 0 + end + if sx == 0 and sy == 0 then + if rx == 1 and ry == 1 then + return s_matrix_0 + else + return f_matrix_2(rx,ry) + end + else + return f_matrix_4(rx,sx,sy,ry) + end + end +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/driv-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/driv-ini.mkiv new file mode 100644 index 00000000000..95b6c88a7b4 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/driv-ini.mkiv @@ -0,0 +1,25 @@ +%D \module +%D [ file=driv-ini, +%D version=2018.07.26, +%D title=\CONTEXT\ Driver Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Driver Macros / Initialization} + +\registerctxluafile{driv-ini}{} + +\unprotect + +\def\page_shipout_box#1% + {\clf_shipoutpage#1\relax + \setbox#1\emptybox + \global\deadcycles\zerocount} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/export-example.css b/Master/texmf-dist/tex/context/base/mkiv/export-example.css index 812873afc5b..c39f0bec637 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/export-example.css +++ b/Master/texmf-dist/tex/context/base/mkiv/export-example.css @@ -34,8 +34,9 @@ @namespace context url('http://www.pragma-ade.com/context/export') ; -/* ignore : mixed */ -/* metadata: display */ +/* ignore : mixed */ +/* metadata : display */ +/* extradata: display */ ignore, context|div.ignore { @@ -57,6 +58,11 @@ context|div.xmetavariable { display : none ; } +extradata, +context|div.extradata { + display : none ; +} + /* document : display */ document:before, @@ -679,6 +685,7 @@ context|div.combinationcaption { /* listcontent : mixed */ /* listdata : mixed */ /* listpage : mixed */ +/* listtext : inline */ list, context|div.list { @@ -758,6 +765,11 @@ context|div.listpage { display : none ; } +listtext, +context|div.listtext { + display : inline ; +} + /* delimitedblock : display */ /* delimited : inline */ /* delimitedsymbol : inline */ @@ -1024,6 +1036,20 @@ context|div.math-display { margin : 1ex 0ex 1em 3em ; } +/* publication : inline */ +/* pubfld : inline */ + +publication, +context|div.publication { + display : inline ; +} + +pubfld[detail="title"], +context|div.pubfld.title { + display : inline ; + font-weight : italic ; +} + /* quantity : inline */ /* unit : inline */ /* number : inline */ @@ -1097,6 +1123,13 @@ context|div.comment { font-family : "DejaVu Sans Mono", "Lucida Console", monospace ; } +/* blocks */ + +block, +context|div.block { + display : block ; +} + /* special */ c, diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-job.lua b/Master/texmf-dist/tex/context/base/mkiv/file-job.lua index dbf6da9b4ba..486aee63a72 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/file-job.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/file-job.lua @@ -386,7 +386,6 @@ local function starttext() if trace_jobfiles then report_jobfiles("starting text") end - -- registerfileinfo[begin]jobfilename context.dostarttext() end textlevel = textlevel + 1 @@ -406,8 +405,6 @@ local function stoptext() report_jobfiles("stopping text") end context.dostoptext() - -- registerfileinfo[end]jobfilename - context.finalend() stopped = true end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi index e1ea405c068..a46e519c061 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/file-job.mkvi @@ -312,6 +312,12 @@ {\documentvariable\c!after \stoptext} +\unexpanded\def\doifelsedocumentvariable#name{\doifelsesomething{\documentvariable{#name}}} +\unexpanded\def\doifdocumentvariable #name{\doifsomething {\documentvariable{#name}}} +\unexpanded\def\doifnotdocumentvariable #name{\doifnot {\documentvariable{#name}}} + +\let\doifdocumentvariableelse\doifelsedocumentvariable + \def\documentvariable#name% {\getvariable\s!document{#name}} @@ -347,12 +353,15 @@ % Bonus: -\installcorenamespace{samplefile} +% \installcorenamespace{samplefile} +% +% \unexpanded\def\samplefile#1% +% {\ifcsname\??samplefile#1\endcsname \else +% \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% +% \fi +% \lastnamedcs} \unexpanded\def\samplefile#1% - {\ifcsname\??samplefile#1\endcsname \else - \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% - \fi - \lastnamedcs} + {\clf_samplefile{#1}} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi b/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi index a2a3b77933e..a06770e24d1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/file-mod.mkvi @@ -36,9 +36,9 @@ \let\usetexmodule\usemodules \def\strc_modules_use[#category][#name][#parameters]% category=t|m|x|p|... - {\pushmacro\currentmodule - \pushmacro\currentmodulecategory - \pushmacro\currentmoduleparameters + {\push_macro_currentmodule + \push_macro_currentmodulecategory + \push_macro_currentmoduleparameters \ifthirdargument \edef\currentmodulecategory {#category}% \edef\currentmodule {#name}% @@ -57,9 +57,9 @@ \let \currentmoduleparameters\empty \fi\fi \processcommacommand[\currentmodule]{\strc_modules_use_indeed\currentmodulecategory}% - \popmacro\currentmoduleparameters - \popmacro\currentmodulecategory - \popmacro\currentmodule} + \pop_macro_currentmoduleparameters + \pop_macro_currentmodulecategory + \pop_macro_currentmodule} \def\strc_modules_use_indeed#category#name% {\ifx\currentmoduleparameters\empty\else @@ -70,20 +70,24 @@ \installcorenamespace{module} -\let\currentmoduleparameters\empty \let\currentmodule \s!unknown +\let\currentmodulecategory \empty +\let\currentmoduleparameters\empty -\newcount \c_syst_modules_nesting +\installmacrostack\currentmodule +\installmacrostack\currentmodulecategory +\installmacrostack\currentmoduleparameters -\newtoks\everysetupmodule +\newcount\c_syst_modules_nesting +\newtoks \everysetupmodule \unexpanded\def\startmodule {\doifelsenextoptionalcs\syst_modules_start_yes\syst_modules_start_nop} \def\syst_modules_start_yes[#name]% {\global\advance\c_syst_modules_nesting\plusone - \pushmacro\currentmodule - \pushmacro\currentmoduleparameters + \push_macro_currentmodule + \push_macro_currentmoduleparameters \def\currentmodule{#name}} \def\syst_modules_start_nop#name % @@ -93,8 +97,8 @@ {\ifcase\c_syst_modules_nesting \writestatus\m!system{module wrapping error in '\currentmodule'}% \else - \popmacro\currentmoduleparameters - \popmacro\currentmodule + \pop_macro_currentmoduleparameters + \pop_macro_currentmodule \global\advance\c_syst_modules_nesting\minusone \fi} @@ -203,7 +207,7 @@ {\ifcsname\??runtimeloaded#2\endcsname % already loaded \else - \global\let#1\undefined + \glet#1\undefined \startreadingfile \startnointerference % \bgroup \cleanupfeatures % better \setnormalcatcodes / test first diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua index fcbcd6d32d1..4ac6278cbcf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-aux.lua @@ -185,6 +185,7 @@ end local getters = { -- maybe better getters[format][...] kern = { ["type1"] = afm.getkern, + ["type3"] = afm.getkern, ["opentype"] = otf.getkern, }, substitution = { diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua index 1d4f010079f..46deedb5f93 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-cff.lua @@ -26,14 +26,16 @@ if not modules then modules = { } end modules ['font-cff'] = { -- with merging subroutines and flattening, not so much with calculations.) On -- the other hand, we can now feed back cff2 stuff. -local next, type, tonumber = next, type, tonumber +local next, type, tonumber, rawget = next, type, tonumber, rawget local byte, char, gmatch = string.byte, string.char, string.gmatch -local concat, remove = table.concat, table.remove +local concat, remove, unpack = table.concat, table.remove, table.unpack local floor, abs, round, ceil, min, max = math.floor, math.abs, math.round, math.ceil, math.min, math.max local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct local lpegmatch = lpeg.match local formatters = string.formatters local bytetable = string.bytetable +local idiv = number.idiv +local rshift, band, extract = bit32.rshift, bit32.band, bit32.extract local readers = fonts.handlers.otf.readers local streamreader = readers.streamreader @@ -47,6 +49,21 @@ local setposition = streamreader.setposition local getposition = streamreader.getposition local readbytetable = streamreader.readbytetable +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + readstring = streamreader.readstring + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readuint = streamreader.readcardinal3 + readulong = streamreader.readcardinal4 + setposition = streamreader.setposition + getposition = streamreader.getposition + readbytetable = streamreader.readbytetable + +end) + local setmetatableindex = table.setmetatableindex local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end) @@ -272,12 +289,30 @@ do result.fontbbox = { unpack(stack,1,4) } top = 0 end - -- + P("\06") / function() end -- bluevalues - -- + P("\07") / function() end -- otherblues - -- + P("\08") / function() end -- familyblues - -- + P("\09") / function() end -- familyotherblues - -- + P("\10") / function() end -- strhw - -- + P("\11") / function() end -- stdvw + + P("\06") / function() + result.bluevalues = { unpack(stack,1,top) } + top = 0 + end + + P("\07") / function() + result.otherblues = { unpack(stack,1,top) } + top = 0 + end + + P("\08") / function() + result.familyblues = { unpack(stack,1,top) } + top = 0 + end + + P("\09") / function() + result.familyotherblues = { unpack(stack,1,top) } + top = 0 + end + + P("\10") / function() + result.strhw = stack[top] + top = 0 + end + + P("\11") / function() + result.strvw = stack[top] + top = 0 + end + P("\13") / function() result.uniqueid = stack[top] top = 0 @@ -371,6 +406,26 @@ do result.strokewidth = stack[top] top = 0 end + + P("\09") / function() + result.bluescale = stack[top] + top = 0 + end + + P("\10") / function() + result.bluesnap = stack[top] + top = 0 + end + + P("\11") / function() + result.bluefuzz = stack[top] + top = 0 + end + + P("\12") / function() + result.stemsnaph = { unpack(stack,1,top) } + top = 0 + end + + P("\13") / function() + result.stemsnapv = { unpack(stack,1,top) } + top = 0 + end + P("\20") / function() result.syntheticbase = stack[top] top = 0 @@ -431,52 +486,27 @@ do -- the second variant is much faster. Not that it matters much as we don't see -- such numbers often. - local p_last = P("\x0F") / "0" + P("\x1F") / "1" + P("\x2F") / "2" + P("\x3F") / "3" - + P("\x4F") / "4" + P("\x5F") / "5" + P("\x6F") / "6" + P("\x7F") / "7" - + P("\x8F") / "8" + P("\x9F") / "9" + P("\xAF") / "" + P("\xBF") / "" - + P("\xCF") / "" + P("\xDF") / "" + P("\xEF") / "" + R("\xF0\xFF") / "" - - -- local remap = { [0] = - -- "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0.", "0E", "0E-", "0", "0-", "0", - -- "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "0.", "0E", "0E-", "0", "0-", "0", - -- "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "0.", "0E", "0E-", "0", "0-", "0", - -- "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "0.", "0E", "0E-", "0", "0-", "0", - -- "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "0.", "0E", "0E-", "0", "0-", "0", - -- "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "0.", "0E", "0E-", "0", "0-", "0", - -- "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "0.", "0E", "0E-", "0", "0-", "0", - -- "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "0.", "0E", "0E-", "0", "0-", "0", - -- "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "0.", "0E", "0E-", "0", "0-", "0", - -- "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "0.", "0E", "0E-", "0", "0-", "0", - -- ".0", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9", "..", ".E", ".E-", ".", ".-", ".", - -- "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "E.", "EE", "EE-", "E", "E-", "E", - -- "E-0", "E-1", "E-2", "E-3", "E-4", "E-5", "E-6", "E-7", "E-8", "E-9", "E-.", "E-E", "E-E-", "E-", "E--", "E-", - -- "-0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-.", "-E", "-E-", "-", "--", "-", - -- } - - -- local p_nibbles = Cs(((1-p_last)/byte/remap)^0+p_last) - - -- local p = P("\30") * p_nibbles / function(t) - -- print(tonumber(t)) - -- end - local remap = { ["\x00"] = "00", ["\x01"] = "01", ["\x02"] = "02", ["\x03"] = "03", ["\x04"] = "04", ["\x05"] = "05", ["\x06"] = "06", ["\x07"] = "07", ["\x08"] = "08", ["\x09"] = "09", ["\x0A"] = "0.", ["\x0B"] = "0E", ["\x0C"] = "0E-", ["\x0D"] = "0", ["\x0E"] = "0-", ["\x0F"] = "0", - ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "0.", ["\x1B"] = "0E", ["\x1C"] = "0E-", ["\x1D"] = "0", ["\x1E"] = "0-", ["\x1F"] = "0", - ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "0.", ["\x2B"] = "0E", ["\x2C"] = "0E-", ["\x2D"] = "0", ["\x2E"] = "0-", ["\x2F"] = "0", - ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "0.", ["\x3B"] = "0E", ["\x3C"] = "0E-", ["\x3D"] = "0", ["\x3E"] = "0-", ["\x3F"] = "0", - ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "0.", ["\x4B"] = "0E", ["\x4C"] = "0E-", ["\x4D"] = "0", ["\x4E"] = "0-", ["\x4F"] = "0", - ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "0.", ["\x5B"] = "0E", ["\x5C"] = "0E-", ["\x5D"] = "0", ["\x5E"] = "0-", ["\x5F"] = "0", - ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "0.", ["\x6B"] = "0E", ["\x6C"] = "0E-", ["\x6D"] = "0", ["\x6E"] = "0-", ["\x6F"] = "0", - ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "0.", ["\x7B"] = "0E", ["\x7C"] = "0E-", ["\x7D"] = "0", ["\x7E"] = "0-", ["\x7F"] = "0", - ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "0.", ["\x8B"] = "0E", ["\x8C"] = "0E-", ["\x8D"] = "0", ["\x8E"] = "0-", ["\x8F"] = "0", - ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "0.", ["\x9B"] = "0E", ["\x9C"] = "0E-", ["\x9D"] = "0", ["\x9E"] = "0-", ["\x9F"] = "0", + ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "1.", ["\x1B"] = "1E", ["\x1C"] = "1E-", ["\x1D"] = "1", ["\x1E"] = "1-", ["\x1F"] = "1", + ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "2.", ["\x2B"] = "2E", ["\x2C"] = "2E-", ["\x2D"] = "2", ["\x2E"] = "2-", ["\x2F"] = "2", + ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "3.", ["\x3B"] = "3E", ["\x3C"] = "3E-", ["\x3D"] = "3", ["\x3E"] = "3-", ["\x3F"] = "3", + ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "4.", ["\x4B"] = "4E", ["\x4C"] = "4E-", ["\x4D"] = "4", ["\x4E"] = "4-", ["\x4F"] = "4", + ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "5.", ["\x5B"] = "5E", ["\x5C"] = "5E-", ["\x5D"] = "5", ["\x5E"] = "5-", ["\x5F"] = "5", + ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "6.", ["\x6B"] = "6E", ["\x6C"] = "6E-", ["\x6D"] = "6", ["\x6E"] = "6-", ["\x6F"] = "6", + ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "7.", ["\x7B"] = "7E", ["\x7C"] = "7E-", ["\x7D"] = "7", ["\x7E"] = "7-", ["\x7F"] = "7", + ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "8.", ["\x8B"] = "8E", ["\x8C"] = "8E-", ["\x8D"] = "8", ["\x8E"] = "8-", ["\x8F"] = "8", + ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "9.", ["\x9B"] = "9E", ["\x9C"] = "9E-", ["\x9D"] = "9", ["\x9E"] = "9-", ["\x9F"] = "9", ["\xA0"] = ".0", ["\xA1"] = ".1", ["\xA2"] = ".2", ["\xA3"] = ".3", ["\xA4"] = ".4", ["\xA5"] = ".5", ["\xA6"] = ".6", ["\xA7"] = ".7", ["\xA8"] = ".8", ["\xA9"] = ".9", ["\xAA"] = "..", ["\xAB"] = ".E", ["\xAC"] = ".E-", ["\xAD"] = ".", ["\xAE"] = ".-", ["\xAF"] = ".", ["\xB0"] = "E0", ["\xB1"] = "E1", ["\xB2"] = "E2", ["\xB3"] = "E3", ["\xB4"] = "E4", ["\xB5"] = "E5", ["\xB6"] = "E6", ["\xB7"] = "E7", ["\xB8"] = "E8", ["\xB9"] = "E9", ["\xBA"] = "E.", ["\xBB"] = "EE", ["\xBC"] = "EE-", ["\xBD"] = "E", ["\xBE"] = "E-", ["\xBF"] = "E", ["\xC0"] = "E-0", ["\xC1"] = "E-1", ["\xC2"] = "E-2", ["\xC3"] = "E-3", ["\xC4"] = "E-4", ["\xC5"] = "E-5", ["\xC6"] = "E-6", ["\xC7"] = "E-7", ["\xC8"] = "E-8", ["\xC9"] = "E-9", ["\xCA"] = "E-.", ["\xCB"] = "E-E", ["\xCC"] = "E-E-", ["\xCD"] = "E-", ["\xCE"] = "E--", ["\xCF"] = "E-", ["\xD0"] = "-0", ["\xD1"] = "-1", ["\xD2"] = "-2", ["\xD3"] = "-3", ["\xD4"] = "-4", ["\xD5"] = "-5", ["\xD6"] = "-6", ["\xD7"] = "-7", ["\xD8"] = "-8", ["\xD9"] = "-9", ["\xDA"] = "-.", ["\xDB"] = "-E", ["\xDC"] = "-E-", ["\xDD"] = "-", ["\xDE"] = "--", ["\xDF"] = "-", } - local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0+p_last) / function(n) + local p_last = S("\x0F\x1F\x2F\x3F\x4F\x5F\x6F\x7F\x8F\x9F\xAF\xBF") + + R("\xF0\xFF") + + local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0 * (P(1)/remap)) / function(n) -- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish top = top + 1 stack[top] = tonumber(n) or 0 @@ -1215,7 +1245,7 @@ do if trace_charstrings then showstate("stem") end - stems = stems + top/2 + stems = stems + idiv(top,2) top = 0 end @@ -1236,14 +1266,15 @@ do if trace_charstrings then showstate(operator == 19 and "hintmark" or "cntrmask") end - stems = stems + top/2 + stems = stems + idiv(top,2) top = 0 if stems == 0 then -- forget about it elseif stems <= 8 then return 1 else - return floor((stems+7)/8) + -- return floor((stems+7)/8) + return idiv(stems+7,8) end end @@ -1290,8 +1321,9 @@ do local function hsbw() if version == 1 then if trace_charstrings then - showstate("dotsection") + showstate("hsbw") end + -- lsb = stack[top-1] width = stack[top] end top = 0 @@ -1513,88 +1545,115 @@ do [037] = flex1, } - local c_endchar = char(14) + local chars = setmetatableindex(function (t,k) + local v = char(k) + t[k] = v + return v + end) - local passon do + local c_endchar = chars[14] - -- todo: round in blend - -- todo: delay this hash + -- todo: round in blend - local rshift = bit32.rshift - local band = bit32.band - local round = math.round + local encode = { } - local encode = table.setmetatableindex(function(t,i) - for i=-2048,-1130 do - t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) - end - for i=-1131,-108 do - local v = 0xFB00 - i - 108 - t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF)) - end - for i=-107,107 do - t[i] = char(i + 139) - end - for i=108,1131 do - local v = 0xF700 + i - 108 - t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF)) - end - for i=1132,2048 do - t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + -- this eventually can become a helper + + setmetatableindex(encode,function(t,i) + for i=-2048,-1130 do + t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + end + for i=-1131,-108 do + local v = 0xFB00 - i - 108 + t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF)) + end + for i=-107,107 do + t[i] = chars[i + 139] + end + for i=108,1131 do + local v = 0xF700 + i - 108 +-- t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF)) + t[i] = char(extract(v,8,8),extract(v,0,8)) + end + for i=1132,2048 do + t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + end + setmetatableindex(encode,function(t,k) + -- 16.16-bit signed fixed value + local r = round(k) + local v = rawget(t,r) + if v then + return v end - return t[i] + local v1 = floor(k) + local v2 = floor((k - v1) * 0x10000) + return char(255,extract(v1,8,8),extract(v1,0,8),extract(v2,8,8),extract(v2,0,8)) end) + return t[i] + end) - local function setvsindex() - local vsindex = stack[top] - updateregions(vsindex) - top = top - 1 - end + readers.cffencoder = encode - local function blend() - local n = stack[top] - top = top - 1 - if not axis then - -- fatal error - elseif n == 1 then - top = top - nofregions - local v = stack[top] + local function p_setvsindex() + local vsindex = stack[top] + updateregions(vsindex) + top = top - 1 + end + + local function p_blend() + -- leaves n values on stack + local n = stack[top] + top = top - 1 + if not axis then + -- fatal error + elseif n == 1 then + top = top - nofregions + local v = stack[top] + for r=1,nofregions do + v = v + stack[top+r] * factors[r] + end + stack[top] = round(v) + else + top = top - nofregions * n + local d = top + local k = top - n + for i=1,n do + k = k + 1 + local v = stack[k] for r=1,nofregions do - v = v + stack[top+r] * factors[r] - end - stack[top] = round(v) - else - top = top - nofregions * n - local d = top - local k = top - n - for i=1,n do - k = k + 1 - local v = stack[k] - for r=1,nofregions do - v = v + stack[d+r] * factors[r] - end - stack[k] = round(v) - d = d + nofregions + v = v + stack[d+r] * factors[r] end + stack[k] = round(v) + d = d + nofregions end end + end - passon = function(operation) - if operation == 15 then - setvsindex() - elseif operation == 16 then - blend() - else - for i=1,top do - r = r + 1 - result[r] = encode[stack[i]] - end - r = r + 1 - result[r] = char(operation) -- maybe use a hash - top = 0 - end + local function p_getstem() + local n = 0 + if top % 2 ~= 0 then + n = 1 + end + if top > n then + stems = stems + idiv(top-n,2) end + end + local function p_getmask() + local n = 0 + if top % 2 ~= 0 then + n = 1 + end + if top > n then + stems = stems + idiv(top-n,2) + end + if stems == 0 then + return 0 + elseif stems <= 8 then + return 1 + else + return idiv(stems+7,8) + end end -- end of experiment @@ -1627,6 +1686,42 @@ do local justpass = false + -- local function decode(str) + -- local a, b, c, d, e = byte(str,1,5) + -- if a == 28 then + -- if c then + -- local n = 0x100 * b + c + -- if n >= 0x8000 then + -- return n - 0x10000 + -- else + -- return n + -- end + -- end + -- elseif a < 32 then + -- return false + -- elseif a <= 246 then + -- return a - 139 + -- elseif a <= 250 then + -- if b then + -- return a*256 - 63124 + b + -- end + -- elseif a <= 254 then + -- if b then + -- return -a*256 + 64148 - b + -- end + -- else + -- if e then + -- local n = 0x100 * b + c + -- if n >= 0x8000 then + -- return n - 0x10000 + (0x100 * d + e)/0xFFFF + -- else + -- return n + (0x100 * d + e)/0xFFFF + -- end + -- end + -- end + -- return false + -- end + process = function(tab) local i = 1 local n = #tab @@ -1651,9 +1746,9 @@ do stack[top] = -t*256 + 64148 - tab[i+1] i = i + 2 else + -- a 16.16 float local n = 0x100 * tab[i+1] + tab[i+2] - if n >= 0x8000 then - -- stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF + if n >= 0x8000 then stack[top] = n - 0x10000 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF else stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF @@ -1700,19 +1795,94 @@ do elseif t == 12 then i = i + 1 local t = tab[i] - local a = subactions[t] - if a then - a(t) + if justpass then + if t >= 34 or t <= 37 then -- flexes + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + r = r + 1 ; result[r] = chars[12] + r = r + 1 ; result[r] = chars[t] + top = 0 + else + local a = subactions[t] + if a then + a(t) + else + top = 0 + end + end else - if trace_charstrings then - showvalue("",t) + local a = subactions[t] + if a then + a(t) + else + if trace_charstrings then + showvalue("",t) + end + top = 0 end - top = 0 end i = i + 1 elseif justpass then - passon(t) - i = i + 1 + -- todo: local a = passactions + if t == 15 then + p_setvsindex() + i = i + 1 + elseif t == 16 then + local s = p_blend() or 0 + i = i + s + 1 + -- cff 1: (when cff2 strip them) + elseif t == 1 or t == 3 or t == 18 or operation == 23 then + p_getstem() -- at the start +if true then + if top > 0 then + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] +else + top = 0 +end + i = i + 1 + -- cff 1: (when cff2 strip them) + elseif t == 19 or t == 20 then + local s = p_getmask() or 0 -- after the stems +if true then + if top > 0 then + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] + for j=1,s do + i = i + 1 + r = r + 1 ; result[r] = chars[tab[i]] + end +else + i = i + s + top = 0 +end + i = i + 1 + -- cff 1: closepath + elseif t == 9 then + top = 0 + i = i + 1 + elseif t == 13 then + local s = hsbw() or 0 + i = i + s + 1 + else + if top > 0 then + for i=1,top do + r = r + 1 ; result[r] = encode[stack[i]] + end + top = 0 + end + r = r + 1 ; result[r] = chars[t] + i = i + 1 + end else local a = actions[t] if a then @@ -1772,20 +1942,33 @@ do -- end local function setbias(globals,locals) - if version == 1 then +-- if version == 1 then -- charstring version, not cff +-- return +-- 0, +-- 0 +-- return +-- 1, +-- 1 +-- else + local g = #globals + local l = #locals return - false, - false - else - local g, l = #globals, #locals - return - ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1, - ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1 - end + ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1, + ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1 +-- end end local function processshape(tab,index) + if not tab then + glyphs[index] = { + boundingbox = { 0, 0, 0, 0 }, + width = 0, + name = charset and charset[index] or nil, + } + return + end + tab = bytetable(tab) x = 0 @@ -1801,7 +1984,6 @@ do ymin = 0 ymax = 0 checked = false - if trace_charstrings then report("glyph: %i",index) report("data : % t",tab) @@ -1921,19 +2103,20 @@ do globalbias, localbias = setbias(globals,locals) nominalwidth, defaultwidth = setwidths(dictionary.private) - startparsing(fontdata,data,streams) - - for index=1,#charstrings do - processshape(charstrings[index],index-1) - charstrings[index] = nil -- free memory (what if used more often?) + if charstrings then + startparsing(fontdata,data,streams) + for index=1,#charstrings do + processshape(charstrings[index],index-1) +-- charstrings[index] = nil -- free memory (what if used more often?) + end + stopparsing(fontdata,data) + else + report("no charstrings") end - - stopparsing(fontdata,data) - return glyphs end - parsecharstring = function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion) + parsecharstring = function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion,streams) keepcurve = doshapes version = tversion @@ -1944,6 +2127,8 @@ do vsindex = dictionary.vsindex or 0 glyphs = glphs or { } + justpass = streams == true + globalbias, localbias = setbias(globals,locals) nominalwidth, defaultwidth = setwidths(dictionary.private) @@ -2118,7 +2303,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams) local format = readbyte(f) if format == 1 then for i=0,nofglyphs do -- notdef included (needs checking) - local index = readbyte(i) + local index = readbyte(f) fdindex[i] = index if index > maxindex then maxindex = index @@ -2149,23 +2334,27 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams) -- hm, always if maxindex >= 0 then local cidarray = cid.fdarray - setposition(f,header.offset+cidarray) - local dictionaries = readlengths(f) - for i=1,#dictionaries do - dictionaries[i] = readstring(f,dictionaries[i]) - end - parsedictionaries(data,dictionaries) - cid.dictionaries = dictionaries - readcidprivates(f,data) - for i=1,#dictionaries do - readlocals(f,data,dictionaries[i]) - end - startparsing(fontdata,data,streams) - for i=1,#charstrings do - parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) - charstrings[i] = nil + if cidarray then + setposition(f,header.offset+cidarray) + local dictionaries = readlengths(f) + for i=1,#dictionaries do + dictionaries[i] = readstring(f,dictionaries[i]) + end + parsedictionaries(data,dictionaries) + cid.dictionaries = dictionaries + readcidprivates(f,data) + for i=1,#dictionaries do + readlocals(f,data,dictionaries[i]) + end + startparsing(fontdata,data,streams) + for i=1,#charstrings do + parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version,streams) +-- charstrings[i] = nil + end + stopparsing(fontdata,data) + else + report("no cid array") end - stopparsing(fontdata,data) end end @@ -2184,7 +2373,7 @@ local function cleanup(data,dictionaries) end function readers.cff(f,fontdata,specification) - local tableoffset = gotodatatable(f,fontdata,"cff",specification.details) + local tableoffset = gotodatatable(f,fontdata,"cff",specification.details or specification.glyphs) if tableoffset then local header = readheader(f) if header.major ~= 1 then @@ -2207,14 +2396,17 @@ function readers.cff(f,fontdata,specification) -- local dic = dictionaries[1] local cid = dic.cid - fontdata.cffinfo = { - familynamename = dic.familyname, + -- + local cffinfo = { + familyname = dic.familyname, fullname = dic.fullname, boundingbox = dic.boundingbox, weight = dic.weight, italicangle = dic.italicangle, underlineposition = dic.underlineposition, underlinethickness = dic.underlinethickness, + defaultwidth = dic.defaultwidthx, + nominalwidth = dic.nominalwidthx, monospaced = dic.monospaced, } fontdata.cidinfo = cid and { @@ -2222,13 +2414,31 @@ function readers.cff(f,fontdata,specification) ordering = cid.ordering, supplement = cid.supplement, } + fontdata.cffinfo = cffinfo -- - if specification.glyphs then - local all = specification.shapes or false + local all = specification.shapes or specification.streams or false + if specification.glyphs or all then if cid and cid.fdselect then - readfdselect(f,fontdata,data,glyphs,all,"cff") + readfdselect(f,fontdata,data,glyphs,all,"cff",specification.streams) else - readnoselect(f,fontdata,data,glyphs,all,"cff") + readnoselect(f,fontdata,data,glyphs,all,"cff",specification.streams) + end + end + local private = dic.private + if private then + local data = private.data + if type(data) == "table" then + cffinfo.defaultwidth = data.defaultwidth or cffinfo.defaultwidth + cffinfo.nominalwidth = data.nominalwidth or cffinfo.nominalwidth + cffinfo.bluevalues = data.bluevalues + cffinfo.otherblues = data.otherblues + cffinfo.familyblues = data.familyblues + cffinfo.familyotherblues = data.familyotherblues + cffinfo.bluescale = data.bluescale + cffinfo.blueshift = data.blueshift + cffinfo.bluefuzz = data.bluefuzz + cffinfo.stdhw = data.stdhw + cffinfo.stdvw = data.stdvw end end cleanup(data,dictionaries) @@ -2267,7 +2477,7 @@ function readers.cff2(f,fontdata,specification) data.factors = specification.factors -- local cid = data.dictionaries[1].cid - local all = specification.shapes or false + local all = specification.shapes or specification.streams or false if cid and cid.fdselect then readfdselect(f,fontdata,data,glyphs,all,"cff2",specification.streams) else @@ -2300,7 +2510,7 @@ function readers.cffcheck(filename) dictionaries = dictionaries, strings = strings, glyphs = glyphs, - nofglyphs = 4, + nofglyphs = 0, } -- parsedictionaries(data,dictionaries,"cff") diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-cft.lua b/Master/texmf-dist/tex/context/base/mkiv/font-cft.lua index 83227ca4a5d..2e1610f1767 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-cft.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-cft.lua @@ -248,6 +248,16 @@ do mathitalics = t_boolean, textitalics = t_boolean, finalized = t_boolean, + effect = { + effect = t_cardinal, + width = t_float, + factor = t_float, + hfactor = t_float, + vfactor = t_float, + wdelta = t_float, + hdelta = t_float, + ddelta = t_float, + } }, parameters = { mathsize = t_cardinal, diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua index 3613432c1e0..ab145ce4d8f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-chk.lua @@ -66,14 +66,12 @@ local hpack_node = node.hpack local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfont = nuts.getfont -local getchar = nuts.getchar +local isglyph = nuts.isglyph local setchar = nuts.setchar -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph + local remove_node = nuts.remove local insert_node_after = nuts.insert_after @@ -142,7 +140,7 @@ local mapping = allocate { -- this is just an experiment to illustrate some prin table.setmetatableindex(mapping, function(t,k) - v = "placeholder unknown gray" + local v = "placeholder unknown gray" t[k] = v return v end @@ -196,7 +194,10 @@ local variants = allocate { { tag = "yellow", r = .6, g = .6, b = 0 }, } -local pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q" +-- bah .. low level pdf ... should be a rule or plugged in + +----- pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q" +local pdf_blob = "q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q" local cache = { } -- saves some tables but not that impressive @@ -235,8 +236,8 @@ local function addmissingsymbols(tfmdata) -- we can have an alternative with rul width = size*fake.width, height = size*fake.height, depth = size*fake.depth, - -- bah .. low level pdf ... should be a rule or plugged in - commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } } + -- commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } } + commands = { { "pdf", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } } } cache[hash] = char end @@ -278,7 +279,7 @@ end local function placeholder(font,char) local tfmdata = fontdata[font] - local category = chardata[char].category + local category = chardata[char].category or "unknown" local fakechar = mapping[category] local slot = getprivateslot(font,fakechar) if not slot then @@ -292,15 +293,12 @@ checkers.placeholder = placeholder function checkers.missing(head) local lastfont, characters, found = nil, nil, nil - head = tonut(head) - for n in traverse_id(glyph_code,head) do -- faster than while loop so we delay removal - local font = getfont(n) - local char = getchar(n) + for n, char, font in nextglyph, head do -- faster than while loop so we delay removal if font ~= lastfont then characters = fontcharacters[font] lastfont = font end - if font > 0 and not characters[char] and is_character[chardata[char].category] then + if font > 0 and not characters[char] and is_character[chardata[char].category or "unknown"] then if action == "remove" then onetimemessage(font,char,"missing (will be deleted)") elseif action == "replace" then @@ -324,7 +322,8 @@ function checkers.missing(head) elseif action == "replace" then for i=1,#found do local node = found[i] - local kind, char = placeholder(getfont(node),getchar(node)) + local char, font = isglyph(node) + local kind, char = placeholder(font,char) if kind == "node" then insert_node_after(head,node,tonut(char)) head = remove_node(head,node,true) @@ -337,7 +336,7 @@ function checkers.missing(head) else -- maye write a report to the log end - return tonode(head), false + return head end local relevant = { @@ -362,6 +361,9 @@ local function getmissing(id) local messages = shared and shared.messages if messages then local filename = d.properties.filename + if not filename then + filename = tostring(d) + end local tf = t[filename] or { } for i=1,#relevant do local tm = messages[relevant[i]] @@ -390,7 +392,6 @@ checkers.getmissing = getmissing do local reported = true - local tracked = false callback.register("glyph_not_found",function(font,char) if font > 0 then @@ -408,7 +409,6 @@ do trackers.register("fonts.missing", function(v) if v then enableaction("processors","fonts.checkers.missing") - tracked = true else disableaction("processors","fonts.checkers.missing") end @@ -419,27 +419,25 @@ do end) logs.registerfinalactions(function() --- if tracked then - local collected, details = getmissing() - if next(collected) then + local collected, details = getmissing() + if next(collected) then + for filename, list in sortedhash(details) do + logs.startfilelogging(report,"missing characters",filename) + for u, v in sortedhash(list) do + report("%4i %U %c %s",v,u,u,chardata[u].description) + end + logs.stopfilelogging() + end + if logs.loggingerrors() then for filename, list in sortedhash(details) do - logs.startfilelogging(report,"missing characters",filename) + logs.starterrorlogging(report,"missing characters",filename) for u, v in sortedhash(list) do report("%4i %U %c %s",v,u,u,chardata[u].description) end - logs.stopfilelogging() - end - if logs.loggingerrors() then - for filename, list in sortedhash(details) do - logs.starterrorlogging(report,"missing characters",filename) - for u, v in sortedhash(list) do - report("%4i %U %c %s",v,u,u,chardata[u].description) - end - logs.stoperrorlogging() - end + logs.stoperrorlogging() end end --- end + end end) end @@ -507,3 +505,31 @@ local dummies_specification = { registerotffeature(dummies_specification) registerafmfeature(dummies_specification) + +-- + +local function addvisualspace(tfmdata) + local spacechar = tfmdata.characters[32] + if spacechar and not spacechar.commands then + local w = spacechar.width + local h = tfmdata.parameters.xheight + local c = { + width = w, + commands = { { "rule", h, w } } + } + local u = addprivate(tfmdata, "visualspace", c) + end +end + +local visualspace_specification = { + name = "visualspace", + description = "visual space", + default = true, + manipulators = { + base = addvisualspace, + node = addvisualspace, + } +} + +registerotffeature(visualspace_specification) +registerafmfeature(visualspace_specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-col.lua b/Master/texmf-dist/tex/context/base/mkiv/font-col.lua index 7bbaf31cb19..d197c7c8583 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-col.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-col.lua @@ -19,15 +19,11 @@ local fastcopy = table.fastcopy local formatters = string.formatters local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfont = nuts.getfont -local getchar = nuts.getchar local setfont = nuts.setfont -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char local settings_to_hash = utilities.parsers.settings_to_hash @@ -47,28 +43,38 @@ collections.definitions = definitions local vectors = collections.vectors or { } collections.vectors = vectors -local fonthashes = fonts.hashes -local fonthelpers = fonts.helpers - -local fontdata = fonthashes.identifiers -local fontquads = fonthashes.quads -local chardata = fonthashes.characters -local propdata = fonthashes.properties +local helpers = fonts.helpers +local charcommand = helpers.commands.char +local rightcommand = helpers.commands.right +local addprivate = helpers.addprivate +local hasprivate = helpers.hasprivate +local fontpatternhassize = helpers.fontpatternhassize -local addprivate = fonthelpers.addprivate -local hasprivate = fonthelpers.hasprivate +local hashes = fonts.hashes +local fontdata = hashes.identifiers +local fontquads = hashes.quads +local chardata = hashes.characters +local propdata = hashes.properties +local mathparameters = hashes.mathparameters local currentfont = font.current local addcharacters = font.addcharacters -local fontpatternhassize = fonts.helpers.fontpatternhassize - local implement = interfaces.implement local list = { } local current = 0 local enabled = false +local validvectors = table.setmetatableindex(function(t,k) + local v = false + if not mathparameters[k] then + v = vectors[k] + end + t[k] = v + return v +end) + local function checkenabled() -- a bit ugly but nicer than a fuzzy state while defining math if next(vectors) then @@ -113,6 +119,23 @@ function collections.define(name,font,ranges,details) end details = settings_to_hash(details) -- todo, combine per font start/stop as arrays + local offset = details.offset + if type(offset) == "string" then + offset = characters.getrange(offset,true) or false + else + offset = tonumber(offset) or false + end + local target = details.target + if type(target) == "string" then + target = characters.getrange(target,true) or false + else + target = tonumber(target) or false + end + local rscale = tonumber (details.rscale) or 1 + local force = toboolean(details.force,true) + local check = toboolean(details.check,true) + local factor = tonumber(details.factor) + local features = details.features for s in gmatch(ranges,"[^, ]+") do local start, stop, description, gaps = characters.getrange(s,true) if start and stop then @@ -127,24 +150,19 @@ function collections.define(name,font,ranges,details) end end end - local offset = details.offset - if type(offset) == "string" then - local start = characters.getrange(offset,true) - offset = start or false - else - offset = tonumber(offset) or false - end d[#d+1] = { font = font, start = start, stop = stop, gaps = gaps, offset = offset, - rscale = tonumber (details.rscale) or 1, - force = toboolean(details.force,true), - check = toboolean(details.check,true), - factor = tonumber(details.factor), - features = details.features, + target = target, + rscale = rscale, + force = force, + check = check, + method = details.method, + factor = factor, + features = features, } end end @@ -163,6 +181,32 @@ end -- check: when true, only set when present in font -- force: when false, then not set when already set +local uccodes = characters.uccodes +local lccodes = characters.lccodes + +local methods = { + lowercase = function(oldchars,newchars,vector,start,stop,cloneid) + for k, v in next, oldchars do + if k >= start and k <= stop then + local lccode = lccodes[k] + if k ~= lccode and newchars[lccode] then + vector[k] = { cloneid, lccode } + end + end + end + end, + uppercase = function(oldchars,newchars,vector,start,stop,cloneid) + for k, v in next, oldchars do + if k >= start and k <= stop then + local uccode = uccodes[k] + if k ~= uccode and newchars[uccode] then + vector[k] = { cloneid, uccode } + end + end + end + end, +} + function collections.clonevector(name) statistics.starttiming(fonts) if trace_collecting then @@ -179,7 +223,9 @@ function collections.clonevector(name) local check = definition.check local force = definition.force local offset = definition.offset or start - local remap = definition.remap + local remap = definition.remap -- not used + local target = definition.target + local method = definition.method local cloneid = list[i] local oldchars = fontdata[current].characters local newchars = fontdata[cloneid].characters @@ -188,28 +234,60 @@ function collections.clonevector(name) vector.factor = factor end if trace_collecting then - report_fonts("remapping font %a to %a for range %U - %U",current,cloneid,start,stop) + if target then + report_fonts("remapping font %a to %a for range %U - %U, offset %X, target %U",current,cloneid,start,stop,offset,target) + else + report_fonts("remapping font %a to %a for range %U - %U, offset %X",current,cloneid,start,stop,offset) + end end - if check then - for unicode = start, stop do - local unic = unicode + offset - start - if not newchars[unicode] then - -- not in font - elseif force or (not vector[unic] and not oldchars[unic]) then - if remap then - vector[unic] = { cloneid, remap[unicode] } - else + if method then + method = methods[method] + end + if method then + method(oldchars,newchars,vector,start,stop,cloneid) + elseif check then + if target then + for unicode = start, stop do + local unic = unicode + offset - start + if not newchars[target] then + -- not in font + elseif force or (not vector[unic] and not oldchars[unic]) then + vector[unic] = { cloneid, target } + end + target = target + 1 + end + elseif remap then + -- not used + else + for unicode = start, stop do + local unic = unicode + offset - start + if not newchars[unicode] then + -- not in font + elseif force or (not vector[unic] and not oldchars[unic]) then vector[unic] = cloneid end end end else - for unicode = start, stop do - local unic = unicode + offset - start - if force or (not vector[unic] and not oldchars[unic]) then - if remap then + if target then + for unicode = start, stop do + local unic = unicode + offset - start + if force or (not vector[unic] and not oldchars[unic]) then + vector[unic] = { cloneid, target } + end + target = target + 1 + end + elseif remap then + for unicode = start, stop do + local unic = unicode + offset - start + if force or (not vector[unic] and not oldchars[unic]) then vector[unic] = { cloneid, remap[unicode] } - else + end + end + else + for unicode = start, stop do + local unic = unicode + offset - start + if force or (not vector[unic] and not oldchars[unic]) then vector[unic] = cloneid end end @@ -219,8 +297,11 @@ function collections.clonevector(name) if trace_collecting then report_fonts("activating collection %a for font %a",name,current) end - checkenabled() statistics.stoptiming(fonts) + -- for WS: needs checking + if validvectors[current] then + checkenabled() + end end -- we already have this parser @@ -284,13 +365,16 @@ local function monoslot(font,char,parent,factor) local width = factor * fontquads[parent] local character = characters[char] if character then + -- runtime patching of the font (can only be new characters) + -- instead of messing with existing dimensions local data = { + -- no features so a simple copy width = width, height = character.height, depth = character.depth, commands = { - { "right", (width - character.width or 0)/2 }, - { "slot", 0, char } + rightcommand[(width - character.width or 0)/2], + charcommand[char], } } local u = addprivate(tfmdata, privatename, data) @@ -308,12 +392,9 @@ local function monoslot(font,char,parent,factor) end function collections.process(head) -- this way we keep feature processing - local done = false - for n in traverse_char(tonut(head)) do - local font = getfont(n) - local vector = vectors[font] + for n, char, font in nextchar, head do + local vector = validvectors[font] if vector then - local char = getchar(n) local vect = vector[char] if not vect then -- keep it @@ -326,7 +407,6 @@ function collections.process(head) -- this way we keep feature processing ) end setfont(n,newfont,newchar) - done = true else local fakemono = vector.factor if trace_collecting then @@ -339,11 +419,10 @@ function collections.process(head) -- this way we keep feature processing else setfont(n,vect) end - done = true end end end - return head, done + return head end function collections.found(font,char) -- this way we keep feature processing diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi index a9c461e44c1..7ba92b526e5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-col.mkvi @@ -23,6 +23,11 @@ % \definefontfallback [whatever] [Slanted] [0x0060-0x007F] [force=yes] % \definefontfallback [whatever] [Bold] [0x0080-0x00FF,0x00A0-0x00AF] [rscale=1.2] % \definefontfallback [whatever] [BoldSlanted] [0x00C0-0x00C7] [check=yes,force=yes] +% +% \definefontfeature [emboldened] [effect={width=0.1,delta=0.4,factor=0.3}] +% \definefontsynonym [SansEmboldened] [Sans] [features=emboldened] +% \definefontfallback[FakeSansCaps] [SansEmboldened] [0x0000-0xFFFF] [rscale=.8,method=uppercase] +% \definefontsynonym [SansCaps] [file:MyriadPro-Regular.otf] [fallbacks=FakeSansCaps] \writestatus{loading}{ConTeXt Font Macros / Collections} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-con.lua b/Master/texmf-dist/tex/context/base/mkiv/font-con.lua index add646da1ba..354fd4ac393 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-con.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-con.lua @@ -46,10 +46,11 @@ constructors.namemode = "fullpath" -- will be a function constructors.version = 1.01 constructors.cache = containers.define("fonts", "constructors", constructors.version, false) -constructors.privateoffset = 0xF0000 -- 0x10FFFF | context also uses privates: 0xE000-0xEFFF - +constructors.privateoffset = fonts.privateoffsets.textbase or 0xF0000 constructors.cacheintex = true -- so we see the original table in fonts.font +constructors.addtounicode = true + -- This might become an interface: local designsizes = allocate() @@ -98,6 +99,24 @@ function constructors.getprivate(tfmdata) return private end +function constructors.setmathparameter(tfmdata,name,value) + local m = tfmdata.mathparameters + local c = tfmdata.MathConstants + if m then + m[name] = value + end + if c and c ~= m then + c[name] = value + end +end + +function constructors.getmathparameter(tfmdata,name) + local p = tfmdata.mathparameters or tfmdata.MathConstants + if p then + return p[name] + end +end + --[[ldx--

Beware, the boundingbox is passed as reference so we may not overwrite it in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to @@ -407,7 +426,10 @@ function constructors.scale(tfmdata,specification) targetparameters.forcedsize = forcedsize -- context specific targetparameters.extrafactor = extrafactor -- context specific -- + local addtounicode = constructors.addtounicode + -- local tounicode = fonts.mappings.tounicode + local unknowncode = tounicode(0xFFFD) -- local defaultwidth = resources.defaultwidth or 0 local defaultheight = resources.defaultheight or 0 @@ -455,7 +477,8 @@ function constructors.scale(tfmdata,specification) local psname = properties.psname or tfmdata.psname local name = properties.name or tfmdata.name -- - -- the psname used in pdf file as well as for selecting subfont in ttc + -- The psname used in pdf file as well as for selecting subfont in ttc although + -- we don't need that subfont look up here (mapfile stuff). -- local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename)) -- @@ -477,20 +500,28 @@ function constructors.scale(tfmdata,specification) target.shrink = expansion.shrink target.step = expansion.step end + -- slanting + local slantfactor = parameters.slantfactor or 0 + if slantfactor ~= 0 then + target.slant = slantfactor * 1000 + else + target.slant = 0 + end -- widening local extendfactor = parameters.extendfactor or 0 if extendfactor ~= 0 and extendfactor ~= 1 then hdelta = hdelta * extendfactor - target.extend = extendfactor * 1000 -- extent ? + target.extend = extendfactor * 1000 else target.extend = 1000 -- extent ? end - -- slanting - local slantfactor = parameters.slantfactor or 0 - if slantfactor ~= 0 then - target.slant = slantfactor * 1000 + -- squeezing + local squeezefactor = parameters.squeezefactor or 0 + if squeezefactor ~= 0 and squeezefactor ~= 1 then + vdelta = vdelta * squeezefactor + target.squeeze = squeezefactor * 1000 else - target.slant = 0 + target.squeeze = 1000 -- extent ? end -- effects local mode = parameters.mode or 0 @@ -499,7 +530,7 @@ function constructors.scale(tfmdata,specification) end local width = parameters.width or 0 if width ~= 0 then - target.width = width + target.width = width * delta * 1000 / 655360 end -- targetparameters.factor = delta @@ -565,6 +596,7 @@ function constructors.scale(tfmdata,specification) targetparameters.descender = delta * descender end -- +-- inspect(targetparameters) constructors.enhanceparameters(targetparameters) -- official copies for us, now virtual -- local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0 @@ -708,11 +740,19 @@ function constructors.scale(tfmdata,specification) end end local isunicode = description.unicode - if isunicode then - chr.unicode = isunicode - chr.tounicode = tounicode(isunicode) - -- in luatex > 0.85 we can do this: - -- chr.tounicode = isunicode + if addtounicode then + if isunicode then + chr.unicode = isunicode + chr.tounicode = tounicode(isunicode) + -- in luatex > 0.85 we can do this: + -- chr.tounicode = isunicode + else + chr.tounicode = unknowncode + end + else + if isunicode then + chr.unicode = isunicode + end end if hasquality then -- we could move these calculations elsewhere (saves calculations) @@ -742,12 +782,15 @@ function constructors.scale(tfmdata,specification) local t = { } for i=1,#vv do local vvi = vv[i] - t[i] = { - ["start"] = (vvi["start"] or 0)*vdelta, - ["end"] = (vvi["end"] or 0)*vdelta, - ["advance"] = (vvi["advance"] or 0)*vdelta, - ["extender"] = vvi["extender"], - ["glyph"] = vvi["glyph"], + local s = vvi["start"] or 0 + local e = vvi["end"] or 0 + local a = vvi["advance"] or 0 + t[i] = { -- zero check nicer for 5.3 + ["start"] = s == 0 and 0 or s * vdelta, + ["end"] = e == 0 and 0 or e * vdelta, + ["advance"] = a == 0 and 0 or a * vdelta, + ["extender"] = vvi["extender"], + ["glyph"] = vvi["glyph"], } end chr.vert_variants = t @@ -757,12 +800,15 @@ function constructors.scale(tfmdata,specification) local t = { } for i=1,#hv do local hvi = hv[i] - t[i] = { - ["start"] = (hvi["start"] or 0)*hdelta, - ["end"] = (hvi["end"] or 0)*hdelta, - ["advance"] = (hvi["advance"] or 0)*hdelta, - ["extender"] = hvi["extender"], - ["glyph"] = hvi["glyph"], + local s = hvi["start"] or 0 + local e = hvi["end"] or 0 + local a = hvi["advance"] or 0 + t[i] = { -- zero check nicer for 5.3 + ["start"] = s == 0 and 0 or s * hdelta, + ["end"] = e == 0 and 0 or e * hdelta, + ["advance"] = a == 0 and 0 or a * hdelta, + ["extender"] = hvi["extender"], + ["glyph"] = hvi["glyph"], } end chr.horiz_variants = t @@ -781,7 +827,10 @@ function constructors.scale(tfmdata,specification) if stackmath then local mk = character.mathkerns if mk then - local tr, tl, br, bl = mk.topright, mk.topleft, mk.bottomright, mk.bottomleft + local tr = mk.topright + local tl = mk.topleft + local br = mk.bottomright + local bl = mk.bottomleft chr.mathkern = { -- singular -> should be patched in luatex ! top_right = tr and mathkerns(tr,vdelta) or nil, top_left = tl and mathkerns(tl,vdelta) or nil, @@ -876,7 +925,7 @@ function constructors.scale(tfmdata,specification) else chr.commands = vc end - chr.index = nil + -- chr.index = nil end end targetcharacters[unicode] = chr @@ -886,15 +935,14 @@ function constructors.scale(tfmdata,specification) -- constructors.aftercopyingcharacters(target,tfmdata) -- - constructors.trytosharefont(target,tfmdata) + constructors.trytosharefont(target,tfmdata) -- -- catch inconsistencies -- local vfonts = target.fonts --- if isvirtual then -if isvirtual or target.type == "virtual" or properties.virtualized then + if isvirtual or target.type == "virtual" or properties.virtualized then properties.virtualized = true -target.type = "virtual" + target.type = "virtual" if not vfonts or #vfonts == 0 then target.fonts = { { id = 0 } } end @@ -947,12 +995,16 @@ function constructors.finalize(tfmdata) parameters.width = 0 end -- + if not parameters.slantfactor then + parameters.slantfactor = tfmdata.slant or 0 + end + -- if not parameters.extendfactor then parameters.extendfactor = tfmdata.extend or 0 end -- - if not parameters.slantfactor then - parameters.slantfactor = tfmdata.slant or 0 + if not parameters.squeezefactor then + parameters.squeezefactor = tfmdata.squeeze or 0 end -- local designsize = parameters.designsize @@ -988,24 +1040,22 @@ function constructors.finalize(tfmdata) properties.virtualized = tfmdata.type == "virtual" end -- - if not tfmdata.properties then - tfmdata.properties = { - fontname = tfmdata.fontname, - filename = tfmdata.filename, - fullname = tfmdata.fullname, - name = tfmdata.name, - psname = tfmdata.psname, - -- - encodingbytes = tfmdata.encodingbytes or 1, - embedding = tfmdata.embedding or "subset", - tounicode = tfmdata.tounicode or 1, - cidinfo = tfmdata.cidinfo or nil, - format = tfmdata.format or "type1", - direction = tfmdata.direction or 0, - writingmode = tfmdata.writingmode or "horizontal", - identity = tfmdata.identity or "horizontal", - } - end + properties.fontname = tfmdata.fontname + properties.filename = tfmdata.filename + properties.fullname = tfmdata.fullname + properties.name = tfmdata.name + properties.psname = tfmdata.psname + -- + properties.encodingbytes = tfmdata.encodingbytes or 1 + properties.embedding = tfmdata.embedding or "subset" + properties.tounicode = tfmdata.tounicode or 1 + properties.cidinfo = tfmdata.cidinfo or nil + properties.format = tfmdata.format or "type1" + properties.direction = tfmdata.direction or 0 + properties.writingmode = tfmdata.writingmode or "horizontal" + properties.identity = tfmdata.identity or "horizontal" + properties.usedbitmap = tfmdata.usedbitmap + -- if not tfmdata.resources then tfmdata.resources = { } end @@ -1043,8 +1093,9 @@ function constructors.finalize(tfmdata) tfmdata.stretch = nil tfmdata.shrink = nil tfmdata.step = nil - tfmdata.extend = nil tfmdata.slant = nil + tfmdata.extend = nil + tfmdata.squeeze = nil tfmdata.mode = nil tfmdata.width = nil tfmdata.units = nil @@ -1097,7 +1148,18 @@ hashmethods.normal = function(list) -- no need to add to hash (maybe we need a skip list) else n = n + 1 - s[n] = k .. '=' .. tostring(v) + if type(v) == "table" then + -- table.sequenced + local t = { } + local m = 0 + for k, v in next, v do + m = m + 1 + t[m] = k .. '=' .. tostring(v) + end + s[n] = k .. '={' .. concat(t,",") .. "}" + else + s[n] = k .. '=' .. tostring(v) + end end end if n > 0 then @@ -1115,7 +1177,9 @@ loose our testcases for .

--ldx]]-- function constructors.hashinstance(specification,force) - local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks + local hash = specification.hash + local size = specification.size + local fallbacks = specification.fallbacks if force or not hash then hash = constructors.hashfeatures(specification) specification.hash = hash @@ -1553,7 +1617,8 @@ end -- while typesetting function constructors.collectprocessors(what,tfmdata,features,trace,report) - local processes, nofprocesses = { }, 0 + local processes = { } + local nofprocesses = 0 if features and next(features) then local properties = tfmdata.properties local whathandler = handlers[what] diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua index 87885f64f70..6847a2b8d30 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ctx.lua @@ -12,21 +12,23 @@ if not modules then modules = { } end modules ['font-ctx'] = { -- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true' -- in virtual fonts indices is implemented. -local context, commands = context, commands +local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber local format, gmatch, match, find, lower, upper, gsub, byte, topattern = string.format, string.gmatch, string.match, string.find, string.lower, string.upper, string.gsub, string.byte, string.topattern local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced -local settings_to_hash, hash_to_string, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string, utilities.parsers.settings_to_array +local parsers = utilities.parsers +local settings_to_hash, hash_to_string, settings_to_array = parsers.settings_to_hash, parsers.hash_to_string, parsers.settings_to_array local formatcolumns = utilities.formatters.formatcolumns local mergehashes = utilities.parsers.mergehashes local formatters = string.formatters local basename = file.basename -local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber local utfchar, utfbyte = utf.char, utf.byte local round = math.round +local context, commands = context, commands + local P, S, C, Cc, Cf, Cg, Ct, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.match local trace_features = false trackers.register("fonts.features", function(v) trace_features = v end) @@ -66,6 +68,8 @@ local hashes = fonts.hashes local currentfont = font.current local definefont = font.define +local getprivateslot = helpers.getprivateslot + local cleanname = names.cleanname local encodings = fonts.encodings @@ -75,11 +79,12 @@ local aglunicodes = nil -- delayed loading local nuts = nodes.nuts local tonut = nuts.tonut +local nextchar = nuts.traversers.char + local getattr = nuts.getattr local setattr = nuts.setattr local getprop = nuts.getprop local setprop = nuts.setprop -local getfont = nuts.getfont local setsubtype = nuts.setsubtype local texgetattribute = tex.getattribute @@ -158,17 +163,8 @@ helpers.name = getfontname local addformatter = utilities.strings.formatters.add -if LUAVERSION < 5.2 then - - addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], "local fontname = fonts.helpers.name") - addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],"local sequenced = table.sequenced") - -else - - addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = helpers.name }) - addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],{ sequenced = table.sequenced }) - -end +addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = helpers.name }) +addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],{ sequenced = table.sequenced }) -- ... like font-sfm or so @@ -472,36 +468,40 @@ registerotffeature { -- }, -- } -local beforecopyingcharacters = sequencers.new { - name = "beforecopyingcharacters", - arguments = "target,original", -} +do + + local beforecopyingcharacters = sequencers.new { + name = "beforecopyingcharacters", + arguments = "target,original", + } -appendgroup(beforecopyingcharacters,"before") -- user -appendgroup(beforecopyingcharacters,"system") -- private -appendgroup(beforecopyingcharacters,"after" ) -- user + appendgroup(beforecopyingcharacters,"before") -- user + appendgroup(beforecopyingcharacters,"system") -- private + appendgroup(beforecopyingcharacters,"after" ) -- user -function constructors.beforecopyingcharacters(original,target) - local runner = beforecopyingcharacters.runner - if runner then - runner(original,target) + function constructors.beforecopyingcharacters(original,target) + local runner = beforecopyingcharacters.runner + if runner then + runner(original,target) + end end -end -local aftercopyingcharacters = sequencers.new { - name = "aftercopyingcharacters", - arguments = "target,original", -} + local aftercopyingcharacters = sequencers.new { + name = "aftercopyingcharacters", + arguments = "target,original", + } -appendgroup(aftercopyingcharacters,"before") -- user -appendgroup(aftercopyingcharacters,"system") -- private -appendgroup(aftercopyingcharacters,"after" ) -- user + appendgroup(aftercopyingcharacters,"before") -- user + appendgroup(aftercopyingcharacters,"system") -- private + appendgroup(aftercopyingcharacters,"after" ) -- user -function constructors.aftercopyingcharacters(original,target) - local runner = aftercopyingcharacters.runner - if runner then - runner(original,target) + function constructors.aftercopyingcharacters(original,target) + local runner = aftercopyingcharacters.runner + if runner then + runner(original,target) + end end + end --[[ldx-- @@ -566,6 +566,12 @@ local function definecontext(name,t) -- can be shared return number, t end +-- {a,b,c} as table (so we don' need to parse again when it gets applied) +-- we will update this ... when we have foo={a,b,c} then we can keep the table + +-- \definefontfeature[demo][a={b,c}] +-- \definefontfeature[demo][a={b=12,c={34,35}}] + local function presetcontext(name,parent,features) -- will go to con and shared if features == "" and find(parent,"=",1,true) then features = parent @@ -575,6 +581,16 @@ local function presetcontext(name,parent,features) -- will go to con and shared features = { } elseif type(features) == "string" then features = normalize_features(settings_to_hash(features)) + -- if type(value) == "string" and find(value,"[=:]") then + -- local t = settings_to_hash_colon_too(value) -- clashes with foo=file:bar + for key, value in next, features do + if type(value) == "string" and find(value,"[=]") then + local t = settings_to_hash(value) + if next(t) then + features[key] = sequenced(normalize_features(t,true),",") + end + end + end else features = normalize_features(features) end @@ -584,8 +600,8 @@ local function presetcontext(name,parent,features) -- will go to con and shared local s = setups[p] if s then for k, v in next, s do --- no, as then we cannot overload: e.g. math,mathextra --- reverted, so we only take from parent when not set + -- no, as then we cannot overload: e.g. math,mathextra + -- reverted, so we only take from parent when not set if features[k] == nil then features[k] = v end @@ -777,7 +793,8 @@ end local function registercontext(fontnumber,extraname,option) local extra = setups[extraname] if extra then - local mergedfeatures, mergedname = { }, nil + local mergedfeatures = { } + local mergedname = nil if option < 0 then mergedname = fontnumber .. "-" .. extraname else @@ -997,25 +1014,33 @@ definers.registersplit(":",colonized,"direct") -- define (two steps) ------ space = P(" ") ------ spaces = space^0 -local leftparent = (P"(") -local rightparent = (P")") -local value = C((leftparent * (1-rightparent)^0 * rightparent + (1-space))^1) -local dimension = C((space/"" + P(1))^1) -local rest = C(P(1)^0) -local scale_none = Cc(0) -local scale_at = (P("at") +P("@")) * Cc(1) * spaces * dimension -- dimension -local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number -local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number -local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number -local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension -local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension - -local specialscale = { [5] = "ht", [6] = "cp" } - -local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_ht + scale_cp + scale_scaled + scale_none) -local splitpattern = spaces * value * spaces * rest +local sizepattern, splitpattern, specialscale do + + ----- space = P(" ") + ----- spaces = space^0 + local leftparent = (P"(") + local rightparent = (P")") + local leftbrace = (P"{") + local rightbrace = (P"}") + local withinparents = leftparent * (1-rightparent)^0 * rightparent + local withinbraces = leftbrace * (1-rightbrace )^0 * rightbrace + local value = C((withinparents + withinbraces + (1-space))^1) + local dimension = C((space/"" + P(1))^1) + local rest = C(P(1)^0) + local scale_none = Cc(0) + local scale_at = (P("at") +P("@")) * Cc(1) * spaces * dimension -- dimension + local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number + local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number + local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number + local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension + local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension + + specialscale = { [5] = "ht", [6] = "cp" } + + sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_ht + scale_cp + scale_scaled + scale_none) + splitpattern = spaces * value * spaces * rest + +end function helpers.splitfontpattern(str) local name, size = lpegmatch(splitpattern,str) @@ -1299,7 +1324,6 @@ do -- else too many locals local busy = false scanners.definefont_two = function() - local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi local cs = scanstring () -- {#csname}% local str = scanstring () -- \somefontfile @@ -1411,6 +1435,7 @@ do -- else too many locals specification.fallbacks = fontfallbacks end end + -- local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?) -- local lastfontid = 0 @@ -1426,15 +1451,15 @@ do -- else too many locals -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period -- - local fallbacks = specification.fallbacks + local fallbacks = specification.fallbacks or "" local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3 - if fallbacks and fallbacks ~= "" and mathsize and not busy then + if fallbacks ~= "" and mathsize and not busy then busy = true -- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally -- math was done in Lua after loading (plugged into aftercopying). -- -- After tl 2017 I'll also do text fallbacks this way (although backups there are done - -- in a completely different way. + -- in a completely different way.) if trace_defining then report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1) @@ -1825,7 +1850,7 @@ function mappings.loadfile(name) if trace_mapfiles then report_mapfiles("loading map file %a",name) end - pdf.mapfile(name) + lpdf.setmapfile(name) loaded[name] = true end end @@ -1843,17 +1868,15 @@ function mappings.loadline(how,line) if trace_mapfiles then report_mapfiles("processing map line %a",line) end - pdf.mapline(how) + lpdf.setmapline(how) loaded[how] = true end end function mappings.reset() - pdf.mapfile("") + lpdf.setmapfile("") -- tricky ... backend related end -mappings.reset() -- resets the default file - implement { name = "loadmapfile", actions = mappings.loadfile, @@ -1876,19 +1899,36 @@ implement { -- => commands -local function nametoslot(name) +local pattern = P("P") + * (lpeg.patterns.hexdigit^4 / function(s) return tonumber(s,16) end) + * P(-1) + +local function nametoslot(name) -- also supports PXXXXX (4+ positions) local t = type(name) if t == "string" then - local slot = unicodes[true][name] + local unic = unicodes[true] + local slot = unic[name] + if slot then + return slot + end + -- + local slot = unic[gsub(name,"_"," ")] or unic[gsub(name,"_","-")] or + unic[gsub(name,"-"," ")] or unic[gsub(name,"-","_")] or + unic[gsub(name," ","_")] or unic[gsub(name," ","-")] if slot then return slot end + -- if not aglunicodes then aglunicodes = encodings.agl.unicodes end local char = characters[true] local slot = aglunicodes[name] - if char[slot] then + if slot and char[slot] then + return slot + end + local slot = lpegmatch(pattern,name) + if slot and char[slot] then return slot end -- not in font @@ -1901,14 +1941,13 @@ local function nametoslot(name) end end - local found = { } local function descriptiontoslot(name) local t = type(name) if t == "string" then -- slow - local list = sortedkeys(chardata) + local list = sortedkeys(chardata) -- can be a cache with weak tables local slot = found[name] local char = characters[true] if slot then @@ -1971,13 +2010,17 @@ local function descriptiontoslot(name) end end -local function indextoslot(index) - local r = resources[true] +local function indextoslot(font,index) + if not index then + index = font + font = true + end + local r = resources[font] if r then local indices = r.indices if not indices then indices = { } - local c = characters[true] + local c = characters[font] for unicode, data in next, c do local di = data.index if di then @@ -2397,9 +2440,12 @@ do return f and (f.gpos[n] or f.gsub[n]) end + local ctx_doifelse = commands.doifelse + local ctx_doif = commands.doif + implement { name = "doifelsecurrentfonthasfeature", - actions = { constructors.currentfonthasfeature, commands.doifelse }, + actions = { constructors.currentfonthasfeature, ctx_doifelse }, arguments = "string" } @@ -2443,9 +2489,22 @@ do implement { name = "definefontfeature", arguments = "3 strings", - actions = presetcontext + actions = presetcontext, } + implement { + name = "doifelsefontfeature", + arguments = "string", + actions = function(name) ctx_doifelse(contextnumber(name) > 1) end, + } + + implement { + name = "doifunknownfontfeature", + arguments = "string", + actions = function(name) ctx_doif(contextnumber(name) == 0) end, + } + + implement { name = "adaptfontfeature", arguments = "2 strings", @@ -2602,8 +2661,6 @@ do local unsetvalue = attributes.unsetvalue - local traverse_char = nuts.traverse_char - local a_color = attributes.private('color') local a_colormodel = attributes.private('colormodel') local a_state = attributes.private('state') @@ -2627,11 +2684,14 @@ do [states.pstf] = "font:5", } + -- todo: traversers + -- todo: check attr_list so that we can use the same .. helper: setcolorattr + local function markstates(head) if head then head = tonut(head) local model = getattr(head,a_colormodel) or 1 - for glyph in traverse_char(head) do + for glyph in nextchar, head do local a = getprop(glyph,a_state) if a then local name = colornames[a] @@ -2682,8 +2742,8 @@ do function methods.nocolor(head,font,attr) - for n in traverse_char(head) do - if not font or getfont(n) == font then + for n, c, f in nextchar, head do + if not font or f == font then setattr(n,a_color,unsetvalue) end end @@ -2708,9 +2768,13 @@ implement { arguments = "string", } -local list = storage.shared.bodyfontsizes or { } +local sharedstorage = storage.shared -storage.shared.bodyfontsizes = list +local list = sharedstorage.bodyfontsizes or { } +local unknown = sharedstorage.unknownbodyfontsizes or { } + +sharedstorage.bodyfontsizes = list +sharedstorage.unknownbodyfontsizes = unknown implement { name = "registerbodyfontsize", @@ -2720,6 +2784,17 @@ implement { end } +interfaces.implement { + name = "registerunknownbodysize", + arguments = "string", + actions = function(size) + if not unknown[size] then + interfaces.showmessage("fonts",14,size) + end + unknown[size] = true + end, +} + implement { name = "getbodyfontsizes", arguments = "string", @@ -2873,6 +2948,12 @@ end -- for the font manual +statistics.register("body font sizes", function() + if next(unknown) then + return formatters["defined: % t, undefined: % t"](sortedkeys(list),sortedkeys(unknown)) + end +end) + statistics.register("used fonts",function() if trace_usage then local filename = file.nameonly(environment.jobname) .. "-fonts-usage.lua" @@ -3018,79 +3099,285 @@ end -- for the moment here (and not in font-con.lua): -local identical = table.identical -local copy = table.copy -local fontdata = fonts.hashes.identifiers -local addcharacters = font.addcharacters - --- This helper is mostly meant to add last-resort (virtual) characters --- or runtime generated fonts (so we forget about features and such). It --- will probably take a while before it get used. - -local trace_adding = false -local report_adding = logs.reporter("fonts","add characters") - -trackers.register("fonts.addcharacters",function(v) trace_adding = v end) - -if addcharacters then - - function fonts.constructors.addcharacters(id,list) - local newchar = list.characters - if newchar then - local data = fontdata[id] - local newfont = list.fonts - local oldchar = data.characters - local oldfont = data.fonts - addcharacters(id, { - characters = newchar, - fonts = newfont, - nomath = not data.properties.hasmath, - }) - -- this is just for tracing, as the assignment only uses the fonts list - -- and doesn't store it otherwise - if newfont then - if oldfont then - local oldn = #oldfont - local newn = #newfont - for n=1,newn do - local ok = false - local nf = newfont[n] - for o=1,oldn do - if identical(nf,oldfont[o]) then - ok = true - break +do + + local identical = table.identical + local copy = table.copy + local fontdata = fonts.hashes.identifiers + local addcharacters = font.addcharacters + + -- This helper is mostly meant to add last-resort (virtual) characters + -- or runtime generated fonts (so we forget about features and such). It + -- will probably take a while before it get used. + + local trace_adding = false + local report_adding = logs.reporter("fonts","add characters") + + trackers.register("fonts.addcharacters",function(v) trace_adding = v end) + + if addcharacters then + + function fonts.constructors.addcharacters(id,list) + local newchar = list.characters + if newchar then + local data = fontdata[id] + local newfont = list.fonts + local oldchar = data.characters + local oldfont = data.fonts + addcharacters(id, { + characters = newchar, + fonts = newfont, + nomath = not data.properties.hasmath, + }) + -- this is just for tracing, as the assignment only uses the fonts list + -- and doesn't store it otherwise + if newfont then + if oldfont then + local oldn = #oldfont + local newn = #newfont + for n=1,newn do + local ok = false + local nf = newfont[n] + for o=1,oldn do + if identical(nf,oldfont[o]) then + ok = true + break + end + end + if not ok then + oldn = oldn + 1 + oldfont[oldn] = newfont[i] end end - if not ok then - oldn = oldn + 1 - oldfont[oldn] = newfont[i] - end + else + data.fonts = newfont end - else - data.fonts = newfont end - end - -- this is because we need to know what goes on and also might - -- want to access character data - for u, c in next, newchar do - if trace_adding then - report_adding("adding character %U to font %!font:name!",u,id) + -- this is because we need to know what goes on and also might + -- want to access character data + for u, c in next, newchar do + if trace_adding then + report_adding("adding character %U to font %!font:name!",u,id) + end + oldchar[u] = c end - oldchar[u] = c end end + + else + function fonts.constructors.addcharacters(id,list) + report_adding("adding characters to %!font:name! is not yet supported",id) + end end -else - function fonts.constructors.addcharacters(id,list) - report_adding("adding characters to %!font:name! is not yet supported",id) + implement { + name = "addfontpath", + arguments = "string", + actions = function(list) + names.addruntimepath(settings_to_array(list)) + end + } + +end + +-- moved here + +do + + local family_font = node.family_font + local new_glyph = nodes.pool.glyph + local fontproperties = fonts.hashes.properties + + local function getprivateslot(id,name) + if not name then + name = id + id = currentfont() + end + local properties = fontproperties[id] + local privates = properties and properties.privates + return privates and privates[name] + end + + local function getprivatenode(tfmdata,name) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + local font = properties.id + local slot = getprivateslot(font,name) + if slot then + -- todo: set current attribibutes + local char = tfmdata.characters[slot] + local tonode = char.tonode + if tonode then + return tonode(font,char) + else + return new_glyph(font,slot) + end + end + end + + local function getprivatecharornode(tfmdata,name) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + local font = properties.id + local slot = getprivateslot(font,name) + if slot then + -- todo: set current attributes + local char = tfmdata.characters[slot] + local tonode = char.tonode + if tonode then + return "node", tonode(tfmdata,char) + else + return "char", slot + end + end end + + helpers.getprivateslot = getprivateslot + helpers.getprivatenode = getprivatenode + helpers.getprivatecharornode = getprivatecharornode + + implement { + name = "getprivatechar", + arguments = "string", + actions = function(name) + local p = getprivateslot(name) + if p then + context(utfchar(p)) + end + end + } + + implement { + name = "getprivatemathchar", + arguments = "string", + actions = function(name) + local p = getprivateslot(family_font(0),name) + if p then + context(utfchar(p)) + end + end + } + + implement { + name = "getprivateslot", + arguments = "string", + actions = function(name) + local p = getprivateslot(name) + if p then + context(p) + end + end + } + end -implement { - name = "addfontpath", - arguments = "string", - actions = function(list) - names.addruntimepath(settings_to_array(list)) +-- handy, for now here: + +function fonts.helpers.collectanchors(tfmdata) + + local resources = tfmdata.resources -- todo: use shared + + if not resources or resources.anchors then + return resources.anchors end -} + + local anchors = { } + + local function set(unicode,target,class,anchor) + local a = anchors[unicode] + if not a then + anchors[unicode] = { [target] = { anchor } } + return + end + local t = a[target] + if not t then + a[target] = { anchor } + return + end + local x = anchor[1] + local y = anchor[2] + for k, v in next, t do + if v[1] == x and v[2] == y then + return + end + end + t[#t+1] = anchor + end + + local function getanchors(steps,target) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + for unicode, data in next, coverage do + local class = data[1] + local anchor = data[2] + if anchor[1] ~= 0 or anchor[2] ~= 0 then + set(unicode,target,class,anchor) + end + end + end + end + + local function getcursives(steps) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + for unicode, data in next, coverage do + local class = data[1] + local en = data[2] + local ex = data[3] + if en then + set(unicode,"entry",class,en) + end + if ex then + set(unicode,"exit", class,ex) + end + end + end + end + + local function collect(list) + if list then + for i=1,#list do + local entry = list[i] + local steps = entry.steps + local kind = entry.type + if kind == "gpos_mark2mark" then + getanchors(steps,"mark") + elseif kind == "gpos_mark2base" then + getanchors(steps,"base") + elseif kind == "gpos_mark2ligature" then + getanchors(steps,"ligature") + elseif kind == "gpos_cursive" then + getcursives(steps) + end + end + end + end + + collect(resources.sequences) + collect(resources.sublookups) + + local function sorter(a,b) + if a[1] == b[1] then + return a[2] < b[2] + else + return a[1] < b[1] + end + end + + for unicode, old in next, anchors do + for target, list in next, old do + sort(list,sorter) + end + end + + resources.anchors = anchors + + return anchors + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-def.lua b/Master/texmf-dist/tex/context/base/mkiv/font-def.lua index 97d25f18093..f3d0f818718 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-def.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-def.lua @@ -80,53 +80,6 @@ and prepares a table that will move along as we proceed.

-- name name(sub) name(sub)*spec name*spec -- name@spec*oeps -local splitter, splitspecifiers = nil, "" -- not so nice - -local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc - -local left = P("(") -local right = P(")") -local colon = P(":") -local space = P(" ") - -definers.defaultlookup = "file" - -local prefixpattern = P(false) - -local function addspecifier(symbol) - splitspecifiers = splitspecifiers .. symbol - local method = S(splitspecifiers) - local lookup = C(prefixpattern) * colon - local sub = left * C(P(1-left-right-method)^1) * right - local specification = C(method) * C(P(1)^1) - local name = C((1-sub-specification)^1) - splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc(""))) -end - -local function addlookup(str,default) - prefixpattern = prefixpattern + P(str) -end - -definers.addlookup = addlookup - -addlookup("file") -addlookup("name") -addlookup("spec") - -local function getspecification(str) - return lpegmatch(splitter,str or "") -- weird catch -end - -definers.getspecification = getspecification - -function definers.registersplit(symbol,action,verbosename) - addspecifier(symbol) - variants[symbol] = action - if verbosename then - variants[verbosename] = action - end -end - local function makespecification(specification,lookup,name,sub,method,detail,size) size = size or 655360 if not lookup or lookup == "" then @@ -151,13 +104,65 @@ local function makespecification(specification,lookup,name,sub,method,detail,siz return t end - definers.makespecification = makespecification -function definers.analyze(specification, size) - -- can be optimized with locals - local lookup, name, sub, method, detail = getspecification(specification or "") - return makespecification(specification, lookup, name, sub, method, detail, size) +if context then + + local splitter, splitspecifiers = nil, "" -- not so nice + + local P, C, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.Cs + + local left = P("(") + local right = P(")") + local colon = P(":") + local space = P(" ") + local lbrace = P("{") + local rbrace = P("}") + + definers.defaultlookup = "file" + + local prefixpattern = P(false) + + local function addspecifier(symbol) + splitspecifiers = splitspecifiers .. symbol + local method = S(splitspecifiers) + local lookup = C(prefixpattern) * colon + local sub = left * C(P(1-left-right-method)^1) * right + local specification = C(method) * C(P(1)^1) + local name = Cs((lbrace/"") * (1-rbrace)^1 * (rbrace/"") + (1-sub-specification)^1) + splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc(""))) + end + + local function addlookup(str) + prefixpattern = prefixpattern + P(str) + end + + definers.addlookup = addlookup + + addlookup("file") + addlookup("name") + addlookup("spec") + + local function getspecification(str) + return lpegmatch(splitter,str or "") -- weird catch + end + + definers.getspecification = getspecification + + function definers.registersplit(symbol,action,verbosename) + addspecifier(symbol) + variants[symbol] = action + if verbosename then + variants[verbosename] = action + end + end + + function definers.analyze(specification, size) + -- can be optimized with locals + local lookup, name, sub, method, detail = getspecification(specification or "") + return makespecification(specification, lookup, name, sub, method, detail, size) + end + end --[[ldx-- @@ -203,9 +208,9 @@ function resolvers.name(specification) features.normal = normal end normal.instance = instance - if not callbacks.supported.glyph_stream_provider then - normal.variableshapes = true -- for the moment - end + -- if not callbacks.supported.glyph_stream_provider then + -- normal.variableshapes = true -- for the moment + -- end end -- local suffix = lower(suffixonly(resolved)) @@ -335,7 +340,7 @@ local function checkfeatures(tfmdata) for script, languages in next, scripts do if languages["*"] then -- ok - elseif not languages[usedlanguage] then + elseif context and not languages[usedlanguage] then report_defining("font %!font:name!, feature %a, script %a, no language %a", tfmdata,feature,script,usedlanguage) end @@ -355,7 +360,7 @@ local function checkfeatures(tfmdata) if not languages["*"] then for i=1,#foundlanguages do local language = foundlanguages[i] - if not languages[language] then + if context and not languages[language] then report_defining("font %!font:name!, feature %a, script %a, no language %a", tfmdata,feature,script,language) end @@ -377,6 +382,7 @@ function definers.loadfont(specification) -- todo: also hash by instance / factors local tfmdata = loadedfonts[hash] -- hashes by size ! if not tfmdata then + -- normally context will not end up here often (if so there is an issue somewhere) local forced = specification.forced or "" if forced ~= "" then local reader = readers[lower(forced)] -- normally forced is already lowered diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua b/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua index 02e5a7df697..046ba285057 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-dsp.lua @@ -51,7 +51,10 @@ if not modules then modules = { } end modules ['font-dsp'] = { -- All this packing in the otf format is somewhat obsessive as nowadays 4K resolution -- multi-gig videos pass through our networks and storage and memory is abundant. -local next, type = next, type +-- Although we use a few table readers there i sno real gain in there (apart from having +-- less code. After all there are often not that many demanding features. + +local next, type, tonumber = next, type, tonumber local band = bit32.band local extract = bit32.extract local bor = bit32.bor @@ -68,12 +71,13 @@ local reversed = table.reversed local sort = table.sort local insert = table.insert local round = math.round -local lpegmatch = lpeg.match +local settings_to_hash = utilities.parsers.settings_to_hash_colon_too local setmetatableindex = table.setmetatableindex local formatters = string.formatters local sortedkeys = table.sortedkeys local sortedhash = table.sortedhash +local sequenced = table.sequenced local report = logs.reporter("otf reader") @@ -82,10 +86,11 @@ local streamreader = readers.streamreader local setposition = streamreader.setposition local getposition = streamreader.getposition -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readuinteger = streamreader.readcardinal1 +local readushort = streamreader.readcardinal2 +local readulong = streamreader.readcardinal4 local readinteger = streamreader.readinteger1 -local readshort = streamreader.readinteger2 -- 16-bit signed integer +local readshort = streamreader.readinteger2 local readstring = streamreader.readstring local readtag = streamreader.readtag local readbytes = streamreader.readbytes @@ -93,9 +98,41 @@ local readfixed = streamreader.readfixed4 local read2dot14 = streamreader.read2dot14 local skipshort = streamreader.skipshort local skipbytes = streamreader.skip -local readfword = readshort local readbytetable = streamreader.readbytetable local readbyte = streamreader.readbyte +local readcardinaltable = streamreader.readcardinaltable +local readintegertable = streamreader.readintegertable +local readfword = readshort + +local short = 2 +local ushort = 2 +local ulong = 4 + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + setposition = streamreader.setposition + getposition = streamreader.getposition + readuinteger = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readulong = streamreader.readcardinal4 + readinteger = streamreader.readinteger1 + readshort = streamreader.readinteger2 + readstring = streamreader.readstring + readtag = streamreader.readtag + readbytes = streamreader.readbytes + readfixed = streamreader.readfixed4 + read2dot14 = streamreader.read2dot14 + skipshort = streamreader.skipshort + skipbytes = streamreader.skip + readbytetable = streamreader.readbytetable + readbyte = streamreader.readbyte + readcardinaltable = streamreader.readcardinaltable + readintegertable = streamreader.readintegertable + readfword = readshort + +end) local gsubhandlers = { } local gposhandlers = { } @@ -196,39 +233,6 @@ local read_integer = { streamreader.readinteger4, } --- using helpers doesn't make much sense, subtle differences --- --- local function readushortarray(f,n) --- local t = { } --- for i=1,n do --- t[i] = readushort(f) --- end --- return t --- end --- --- local function readulongarray(f,n) --- local t = { } --- for i=1,n do --- t[i] = readulong(f) --- end --- return t --- end --- --- local function readushortarray(f,target,first,size) --- if not size then --- for i=1,size do --- target[i] = readushort(f) --- end --- else --- for i=1,size do --- target[first+i] = readushort(f) --- end --- end --- return target --- end --- --- so we get some half helper - half non helper mix then - -- Traditionally we use these unique names (so that we can flatten the lookup list -- (we create subsets runtime) but I will adapt the old code to newer names. @@ -300,30 +304,16 @@ end) -- wght:400,wdth:100,ital:1 --- local names = table.setmetatableindex ( { --- weight = "wght", --- width = "wdth", --- italic = "ital", --- }, "self") - --- todo: spaces in name but not before : - -local pattern = lpeg.Cf ( - lpeg.Ct("") * - lpeg.Cg ( - --(lpeg.R("az")^1/names) * lpeg.S(" :") * - lpeg.C((lpeg.R("az","09")+lpeg.P(" "))^1) * lpeg.S(" :=") * - (lpeg.patterns.number/tonumber) * lpeg.S(" ,")^0 - )^1, rawset -) +local function axistofactors(str) + local t = settings_to_hash(str) + for k, v in next, t do + t[k] = tonumber(v) or v -- this also normalizes numbers itself + end + return t +end local hash = table.setmetatableindex(function(t,k) - local v = lpegmatch(pattern,k) - local t = { } - for k, v in sortedhash(v) do - t[#t+1] = k .. "=" .. v - end - v = concat(t,",") + local v = sequenced(axistofactors(k),",") t[k] = v return v end) @@ -340,10 +330,6 @@ function helpers.normalizedaxis(str) return hash[str] or str end -local function axistofactors(str) - return lpegmatch(pattern,str) -end - -- contradicting spec ... (signs) so i'll check it and fix it once we have -- proper fonts @@ -498,10 +484,7 @@ local function readvariationdata(f,storeoffset,factors) -- store local format = readushort(f) local regionoffset = storeoffset + readulong(f) local nofdeltadata = readushort(f) - local deltadata = { } - for i=1,nofdeltadata do - deltadata[i] = readulong(f) - end + local deltadata = readcardinaltable(f,nofdeltadata,ulong) -- regions setposition(f,regionoffset) local nofaxis = readushort(f) @@ -532,10 +515,7 @@ local function readvariationdata(f,storeoffset,factors) -- store end -- we could test before and save a for for i=1,nofdeltasets do - local t = { } -- newtable - for i=1,nofshorts do - t[i] = readshort(f) - end + local t = readintegertable(f,nofshorts,short) for i=nofshorts+1,nofregions do t[i] = readinteger(f) end @@ -560,21 +540,32 @@ helpers.readvariationdata = readvariationdata local function readcoverage(f,offset,simple) setposition(f,offset) local coverageformat = readushort(f) - local coverage = { } if coverageformat == 1 then local nofcoverage = readushort(f) if simple then - for i=1,nofcoverage do - coverage[i] = readushort(f) + -- often 1 or 2 + if nofcoverage == 1 then + return { readushort(f) } + elseif nofcoverage == 2 then + return { readushort(f), readushort(f) } + else + return readcardinaltable(f,nofcoverage,ushort) end + elseif nofcoverage == 1 then + return { [readushort(f)] = 0 } + elseif nofcoverage == 2 then + return { [readushort(f)] = 0, [readushort(f)] = 1 } else + local coverage = { } for i=0,nofcoverage-1 do coverage[readushort(f)] = i -- index in record end + return coverage end elseif coverageformat == 2 then local nofranges = readushort(f) - local n = simple and 1 or 0 -- needs checking + local coverage = { } + local n = simple and 1 or 0 -- needs checking for i=1,nofranges do local firstindex = readushort(f) local lastindex = readushort(f) @@ -591,10 +582,11 @@ local function readcoverage(f,offset,simple) end end end + return coverage else report("unknown coverage format %a ",coverageformat) + return { } end - return coverage end local function readclassdef(f,offset,preset) @@ -828,23 +820,17 @@ local function readfirst(f,offset) return { readushort(f) } end -local function readarray(f,offset,first) +-- quite often 0, 1, 2 + +function readarray(f,offset) if offset then setposition(f,offset) end local n = readushort(f) - if first then - local t = { first } - for i=2,n do - t[i] = readushort(f) - end - return t, n + if n == 1 then + return { readushort(f) }, 1 elseif n > 0 then - local t = { } - for i=1,n do - t[i] = readushort(f) - end - return t, n + return readcardinaltable(f,n,ushort), n end end @@ -1023,8 +1009,9 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n rules = rules, } elseif subtype == 3 then - local current = readarray(f) + local nofglyphs = readushort(f) local noflookups = readushort(f) + local current = readcardinaltable(f,nofglyphs,ushort) local lookups = readlookuparray(f,noflookups,#current) current = readcoveragearray(f,tableoffset,current,true) return { @@ -1231,7 +1218,7 @@ function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofg local delta = readshort(f) -- can be negative local coverage = readcoverage(f,tableoffset+coverage) -- not simple as we need to set key/value anyway for index in next, coverage do - local newindex = index + delta + local newindex = (index + delta) % 65536 -- modulo is new in 1.8.3 if index > nofglyphs or newindex > nofglyphs then report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs) coverage[index] = nil @@ -1245,10 +1232,7 @@ function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofg elseif subtype == 2 then -- in streamreader a seek and fetch is faster than a temp table local coverage = readushort(f) local nofreplacements = readushort(f) - local replacements = { } - for i=1,nofreplacements do - replacements[i] = readushort(f) - end + local replacements = readcardinaltable(f,nofreplacements,ushort) local coverage = readcoverage(f,tableoffset + coverage) -- not simple as we need to set key/value anyway for index, newindex in next, coverage do newindex = newindex + 1 @@ -1276,18 +1260,10 @@ local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyp if subtype == 1 then local coverage = readushort(f) local nofsequence = readushort(f) - local sequences = { } - for i=1,nofsequence do - sequences[i] = readushort(f) - end + local sequences = readcardinaltable(f,nofsequence,ushort) for i=1,nofsequence do setposition(f,tableoffset + sequences[i]) - local n = readushort(f) - local s = { } - for i=1,n do - s[i] = readushort(f) - end - sequences[i] = s + sequences[i] = readcardinaltable(f,readushort(f),ushort) end local coverage = readcoverage(f,tableoffset + coverage) for index, newindex in next, coverage do @@ -1322,19 +1298,20 @@ function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,no if subtype == 1 then local coverage = readushort(f) local nofsets = readushort(f) - local ligatures = { } - for i=1,nofsets do - ligatures[i] = readushort(f) - end + local ligatures = readcardinaltable(f,nofsets,ushort) for i=1,nofsets do local offset = lookupoffset + offset + ligatures[i] setposition(f,offset) local n = readushort(f) - local l = { } - for i=1,n do - l[i] = offset + readushort(f) + if n == 1 then + ligatures[i] = { offset + readushort(f) } + else + local l = { } + for i=1,n do + l[i] = offset + readushort(f) + end + ligatures[i] = l end - ligatures[i] = l end local coverage = readcoverage(f,tableoffset + coverage) for index, newindex in next, coverage do @@ -1982,10 +1959,15 @@ do local parameters = readushort(f) -- feature.parameters local noflookups = readushort(f) if noflookups > 0 then - local lookups = { } +-- local lookups = { } +-- feature.lookups = lookups +-- for j=1,noflookups do +-- lookups[j] = readushort(f) + 1 +-- end + local lookups = readcardinaltable(f,noflookups,ushort) feature.lookups = lookups for j=1,noflookups do - lookups[j] = readushort(f) + 1 + lookups[j] = lookups[j] + 1 end end if parameters > 0 then @@ -2001,11 +1983,8 @@ do local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder) setposition(f,lookupoffset) - local lookups = { } local noflookups = readushort(f) - for i=1,noflookups do - lookups[i] = readushort(f) - end + local lookups = readcardinaltable(f,noflookups,ushort) for lookupid=1,noflookups do local offset = lookups[lookupid] setposition(f,lookupoffset+offset) @@ -2237,7 +2216,7 @@ do report_issue(i,what,sequence,"no") elseif not next(rlookups) then -- can be ok as it aborts a chain sequence - report_issue(i,what,sequence,"empty") + -- report_issue(i,what,sequence,"empty") rule.lookups = nil else -- we can have holes in rlookups flagged false and we can have multiple lookups @@ -2296,9 +2275,7 @@ do end end end --- report("before : % t",rlookups[index]) rlookups[index] = noffound > 0 and found or false --- report("after : % t",rlookups[index]) else rlookups[index] = false end @@ -2322,7 +2299,7 @@ do local function loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder) setposition(f,variationsoffset) - local version = readulong(f) + local version = readulong(f) -- two times readushort local nofrecords = readulong(f) local records = { } for i=1,nofrecords do @@ -2338,11 +2315,12 @@ do record.condition = nil record.matchtype = "always" else - setposition(f,variationsoffset+offset) + local offset = variationsoffset+offset + setposition(f,offset) local nofconditions = readushort(f) local conditions = { } for i=1,nofconditions do - conditions[i] = variationsoffset+offset+readulong(f) + conditions[i] = offset + readulong(f) end record.conditions = conditions record.matchtype = "condition" @@ -2385,10 +2363,7 @@ do setposition(f,tableoffset) local parameters = readulong(f) -- feature parameters local noflookups = readushort(f) - local lookups = { } - for i=1,noflookups do - lookups[i] = readushort(f) -- not sure what to do with these - end + local lookups = readcardinaltable(f,noflookups,ushort) -- not sure what to do with these -- todo : resolve to proper lookups record.substitutions = lookups end @@ -2449,7 +2424,7 @@ do elseif specification.globalkerns then name = "globalkern" else - report("ignoring global kern table using gpos kern feature") + report("ignoring global kern table, using gpos kern feature") return end setposition(f,datatable.offset) @@ -2611,10 +2586,7 @@ function readers.gdef(f,fontdata,specification) local format = readushort(f) if format == 1 then local nofsets = readushort(f) - local sets = { } - for i=1,nofsets do - sets[i] = readulong(f) - end + local sets = readcardinaltable(f,nofsets,ulong) for i=1,nofsets do local offset = sets[i] if offset ~= 0 then @@ -2851,14 +2823,8 @@ local function readmathvariants(f,fontdata,offset) local hcoverage = readushort(f) local vnofglyphs = readushort(f) local hnofglyphs = readushort(f) - local vconstruction = { } - local hconstruction = { } - for i=1,vnofglyphs do - vconstruction[i] = readushort(f) - end - for i=1,hnofglyphs do - hconstruction[i] = readushort(f) - end + local vconstruction = readcardinaltable(f,vnofglyphs,ushort) + local hconstruction = readcardinaltable(f,hnofglyphs,ushort) fontdata.mathconstants.MinConnectorOverlap = minoverlap @@ -3033,10 +2999,7 @@ function readers.cpal(f,fontdata,specification) local nofcolorrecords = readushort(f) local firstcoloroffset = readulong(f) local colorrecords = { } - local palettes = { } - for i=1,nofpalettes do - palettes[i] = readushort(f) - end + local palettes = readcardinaltable(f,nofpalettes,ushort) if version == 1 then -- used for guis local palettettypesoffset = readulong(f) @@ -3109,183 +3072,324 @@ function readers.sbix(f,fontdata,specification) for i=1,nofstrikes do strikes[i] = readulong(f) end - -- if true then - local shapes = { } - local done = 0 - for i=1,nofstrikes do - local strikeoffset = strikes[i] + tableoffset - setposition(f,strikeoffset) - strikes[i] = { - ppem = readushort(f), - ppi = readushort(f), - offset = strikeoffset + local shapes = { } + local done = 0 + for i=1,nofstrikes do + local strikeoffset = strikes[i] + tableoffset + setposition(f,strikeoffset) + strikes[i] = { + ppem = readushort(f), + ppi = readushort(f), + offset = strikeoffset + } + end + -- highest first + sort(strikes,function(a,b) + if b.ppem == a.ppem then + return b.ppi < a.ppi + else + return b.ppem < a.ppem + end + end) + local glyphs = { } + for i=1,nofstrikes do + local strike = strikes[i] + local strikeppem = strike.ppem + local strikeppi = strike.ppi + local strikeoffset = strike.offset + setposition(f,strikeoffset) + for i=0,nofglyphs do + glyphs[i] = readulong(f) + end + local glyphoffset = glyphs[0] + for i=0,nofglyphs-1 do + local nextoffset = glyphs[i+1] + if not shapes[i] then + local datasize = nextoffset - glyphoffset + if datasize > 0 then + setposition(f,strikeoffset + glyphoffset) + shapes[i] = { + x = readshort(f), + y = readshort(f), + tag = readtag(f), -- maybe for tracing + data = readstring(f,datasize-8), + ppem = strikeppem, -- not used, for tracing + ppi = strikeppi, -- not used, for tracing + } + done = done + 1 + if done == nofglyphs then + break + end + end + end + glyphoffset = nextoffset + end + end + fontdata.pngshapes = shapes + end +end + +-- Another bitmap (so not that useful) format. But Luigi found a font that +-- has them , so ... + +do + + local function getmetrics(f) + return { + ascender = readinteger(f), + descender = readinteger(f), + widthmax = readuinteger(f), + caretslopedumerator = readinteger(f), + caretslopedenominator = readinteger(f), + caretoffset = readinteger(f), + minorigin = readinteger(f), + minadvance = readinteger(f), + maxbefore = readinteger(f), + minafter = readinteger(f), + pad1 = readinteger(f), + pad2 = readinteger(f), + } + end + + -- bad names + + local function getbigmetrics(f) + -- bigmetrics, maybe just skip 9 bytes + return { + height = readuinteger(f), + width = readuinteger(f), + horiBearingX = readinteger(f), + horiBearingY = readinteger(f), + horiAdvance = readuinteger(f), + vertBearingX = readinteger(f), + vertBearingY = readinteger(f), + vertAdvance = readuinteger(f), + } + end + + local function getsmallmetrics(f) + -- smallmetrics, maybe just skip 5 bytes + return { + height = readuinteger(f), + width = readuinteger(f), + bearingX = readinteger(f), + bearingY = readinteger(f), + advance = readuinteger(f), + } + end + + function readers.cblc(f,fontdata,specification) + -- should we delay this ? + local ctdttableoffset = gotodatatable(f,fontdata,"cbdt",specification.glyphs) + if not ctdttableoffset then + return + end + local cblctableoffset = gotodatatable(f,fontdata,"cblc",specification.glyphs) + if cblctableoffset then + local majorversion = readushort(f) + local minorversion = readushort(f) + local nofsizetables = readulong(f) + local sizetables = { } + local shapes = { } + local subtables = { } + for i=1,nofsizetables do + sizetables[i] = { + subtables = readulong(f), + indexsize = readulong(f), + nofsubtables = readulong(f), + colorref = readulong(f), + hormetrics = getmetrics(f), + vermetrics = getmetrics(f), + firstindex = readushort(f), + lastindex = readushort(f), + ppemx = readbyte(f), + ppemy = readbyte(f), + bitdepth = readbyte(f), + flags = readbyte(f), } end - -- highest first - sort(strikes,function(a,b) - if b.ppem == a.ppem then - return b.ppi < a.ppi + sort(sizetables,function(a,b) + if b.ppemx == a.ppemx then + return b.bitdepth < a.bitdepth else - return b.ppem < a.ppem + return b.ppemx < a.ppemx end end) - local glyphs = { } - for i=1,nofstrikes do - local strike = strikes[i] - local strikeppem = strike.ppem - local strikeppi = strike.ppi - local strikeoffset = strike.offset - setposition(f,strikeoffset) - for i=0,nofglyphs do - glyphs[i] = readulong(f) + for i=1,nofsizetables do + local s = sizetables[i] + local d = false + for j=s.firstindex,s.lastindex do + if not shapes[j] then + shapes[j] = i + d = true + end end - local glyphoffset = glyphs[0] - for i=0,nofglyphs-1 do - local nextoffset = glyphs[i+1] - if not shapes[i] then - local datasize = nextoffset - glyphoffset - if datasize > 0 then - setposition(f,strikeoffset + glyphoffset) - shapes[i] = { - x = readshort(f), - y = readshort(f), - tag = readtag(f), -- maybe for tracing - data = readstring(f,datasize-8), - ppem = strikeppem, -- not used, for tracing - ppi = strikeppi, -- not used, for tracing - } - done = done + 1 - if done == nofglyphs then - break + if d then + s.used = true + end + end + for i=1,nofsizetables do + local s = sizetables[i] + if s.used then + local offset = s.subtables + setposition(f,cblctableoffset+offset) + for j=1,s.nofsubtables do + local firstindex = readushort(f) + local lastindex = readushort(f) + local tableoffset = readulong(f) + offset + for k=firstindex,lastindex do + if shapes[k] == i then + local s = subtables[tableoffset] + if not s then + s = { + firstindex = firstindex, + lastindex = lastindex, + } + subtables[tableoffset] = s + end + shapes[k] = s end end end - glyphoffset = nextoffset end end - fontdata.sbixshapes = shapes - -- else - -- for i=1,nofstrikes do - -- local strikeoffset = strikes[i] + tableoffset - -- setposition(f,strikeoffset) - -- local glyphs = { } - -- strikes[i] = { - -- ppem = readushort(f), - -- ppi = readushort(f), - -- glyphs = glyphs, - -- } - -- for i=0,nofglyphs do - -- glyphs[i] = readulong(f) - -- end - -- local glyphoffset = glyphs[0] - -- for i=0,nofglyphs-1 do - -- local nextoffset = glyphs[i+1] - -- local datasize = nextoffset - glyphoffset - -- if datasize > 0 then - -- setposition(f,strikeoffset + glyphoffset) - -- glyphs[i] = { - -- x = readshort(f), - -- y = readshort(f), - -- tag = readtag(f), - -- data = readstring(f,datasize-8) - -- } - -- glyphoffset = nextoffset - -- end - -- end - -- end - -- fontdata.sbixshapes = strikes + + -- there is no need to sort in string stream but we have a nicer trace + -- if needed + + for offset, subtable in sortedhash(subtables) do + local tabletype = readushort(f) + subtable.format = readushort(f) + local baseoffset = readulong(f) + ctdttableoffset + local offsets = { } + local metrics = nil + if tabletype == 1 then + -- we have the usual one more to get the size + for i=subtable.firstindex,subtable.lastindex do + offsets[i] = readulong(f) + baseoffset + end + skipbytes(f,4) + elseif tabletype == 2 then + local size = readulong(f) + local done = baseoffset + metrics = getbigmetrics(f) + for i=subtable.firstindex,subtable.lastindex do + offsets[i] = done + done = done + size + end + elseif tabletype == 3 then + -- we have the usual one more to get the size + local n = subtable.lastindex - subtable.firstindex + 2 + for i=subtable.firstindex,subtable.lastindex do + offsets[i] = readushort(f) + baseoffset + end + if math.odd(n) then + skipbytes(f,4) + else + skipbytes(f,2) + end + elseif tabletype == 4 then + for i=1,readulong(f) do + offsets[readushort(f)] = readushort(f) + baseoffset + end + elseif tabletype == 5 then + local size = readulong(f) + local done = baseoffset + metrics = getbigmetrics(f) + local n = readulong(f) + for i=1,n do + offsets[readushort(f)] = done + done = done + size + end + if math.odd(n) then + skipbytes(f,2) + end + else + return -- unsupported format + end + subtable.offsets = offsets + subtable.metrics = metrics + end + + -- we only support a few sensible types ... there are hardly any fonts so + -- why are there so many variants ... not the best spec + + local default = { width = 0, height = 0 } + local glyphs = fontdata.glyphs + + for index, subtable in sortedhash(shapes) do + if type(subtable) == "table" then + local data = nil + local metrics = default + local format = subtable.format + local offset = subtable.offsets[index] + setposition(f,offset) + if format == 17 then + metrics = getsmallmetrics(f) + data = readstring(f,readulong(f)) + elseif format == 18 then + metrics = getbigmetrics(f) + data = readstring(f,readulong(f)) + elseif format == 19 then + metrics = subtable.metrics + data = readstring(f,readulong(f)) + else + -- forget about it + end + local x = metrics.width + local y = metrics.height + shapes[index] = { + -- maybe some metrics + x = x, + y = y, + data = data, + } + -- I'll look into this in more details when needed + -- as we can use the bearings to get better boxes. + local glyph = glyphs[index] + if not glyph.boundingbox then + local width = glyph.width + local height = width * y/x + glyph.boundingbox = { 0, 0, width, height } + end + + else + shapes[index] = { + x = 0, + y = 0, + data = "", + } + end + end + + fontdata.pngshapes = shapes -- we cheat + end + end + + function readers.cbdt(f,fontdata,specification) + -- local tableoffset = gotodatatable(f,fontdata,"ctdt",specification.glyphs) + -- if tableoffset then + -- local majorversion = readushort(f) + -- local minorversion = readushort(f) -- end end -end --- function readers.cblc(f,fontdata,specification) --- local tableoffset = gotodatatable(f,fontdata,"cblc",specification.glyphs) --- if tableoffset then --- end --- end --- --- function readers.cbdt(f,fontdata,specification) --- local tableoffset = gotodatatable(f,fontdata,"ctdt",specification.glyphs) --- if tableoffset then --- --- local function getmetrics(f) --- return { --- ascender = readinteger(f), --- descender = readinteger(f), --- widthmax = readcardinal(f), --- caretslopedumerator = readinteger(f), --- caretslopedenominator = readinteger(f), --- caretoffset = readinteger(f), --- minorigin = readinteger(f), --- minadvance = readinteger(f), --- maxbefore = readinteger(f), --- minafter = readinteger(f), --- pad1 = readinteger(f), --- pad2 = readinteger(f), --- } --- end --- --- local majorversion = readushort(f) --- local minorversion = readushort(f) --- local nofsizetables = readulong(f) --- local sizetable = { } --- for i=1,nofsizetables do --- sizetable[i] = { --- subtables = readulong(f), --- indexsize = readulong(f), --- nofsubtables = readulong(f), --- colorref = readulong(f), --- hormetrics = getmetrics(f), --- vermetrics = getmetrics(f), --- firstindex = readushort(f), --- lastindex = readushort(f), --- ppemx = readbyte(f), --- ppemy = readbyte(f), --- bitdepth = readbyte(f), --- flags = readbyte(f), --- } --- end --- --- sort(sizetable,function(a,b) --- if b.ppemx == a.ppemx then --- return b.bitdepth < a.bitdepth --- else --- return b.ppemx < a.ppemx --- end --- end) --- --- local shapes = { } --- --- for i=1,nofsizetables do --- local s = sizetables[i] --- for j=firstindex,lastindex do --- if not shapes[j] then --- shapes[j] = { --- i --- } --- end --- end --- end --- --- inspect(shapes) --- --- end --- end + -- function readers.ebdt(f,fontdata,specification) + -- if specification.glyphs then + -- end + -- end --- function readers.ebdt(f,fontdata,specification) --- if specification.glyphs then --- end --- end + -- function readers.ebsc(f,fontdata,specification) + -- if specification.glyphs then + -- end + -- end --- function readers.ebsc(f,fontdata,specification) --- if specification.glyphs then --- end --- end + -- function readers.eblc(f,fontdata,specification) + -- if specification.glyphs then + -- end + -- end --- function readers.eblc(f,fontdata,specification) --- if specification.glyphs then --- end --- end +end -- + AVAR : optional -- + CFF2 : otf outlines @@ -3398,7 +3502,8 @@ function readers.avar(f,fontdata,specification) local lastfrom = false local lastto = false for i=1,nofvalues do - local f, t = read2dot14(f), read2dot14(f) + local f = read2dot14(f) + local t = read2dot14(f) if lastfrom and f <= lastfrom then -- ignore elseif lastto and t >= lastto then @@ -3426,11 +3531,10 @@ function readers.avar(f,fontdata,specification) return false end - local majorversion = readushort(f) -- 1 - local minorversion = readushort(f) -- 0 - local reserved = readushort(f) - local nofaxis = readushort(f) - local segments = { } + local version = readulong(f) -- 0x00010000 + local reserved = readushort(f) + local nofaxis = readushort(f) + local segments = { } for i=1,nofaxis do segments[i] = collect() end @@ -3441,7 +3545,7 @@ end function readers.fvar(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"fvar",true) -- specification.variable or specification.instancenames if tableoffset then - local version = readulong(f) -- 1.0 + local version = readulong(f) -- 0x00010000 local offsettoaxis = tableoffset + readushort(f) local reserved = skipshort(f) -- pair 1 @@ -3527,7 +3631,7 @@ function readers.hvar(f,fontdata,specification) return end - local version = readulong(f) -- 1.0 + local version = readulong(f) -- 0x00010000 local variationoffset = tableoffset + readulong(f) -- the store local advanceoffset = tableoffset + readulong(f) local lsboffset = tableoffset + readulong(f) @@ -3624,7 +3728,7 @@ end function readers.mvar(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"mvar",specification.variable) if tableoffset then - local version = readulong(f) -- 1.0 + local version = readulong(f) -- 0x00010000 local reserved = skipshort(f,1) local recordsize = readushort(f) local nofrecords = readushort(f) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi index 1b6d46798ba..b5c09d4c265 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-emp.mkvi @@ -227,12 +227,22 @@ %D their style as good as possible. These macros are obsolete %D in \MKIV. -\unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} -\unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} -\unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} -\unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} - -\unexpanded\def\emph {\groupedcommand{\em}{}} +% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} +% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} +% \unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} +% \unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} +% \unexpanded\def\emph {\groupedcommand{\em}{}} + +\unexpanded\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}} +\unexpanded\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}} +\unexpanded\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}} +\unexpanded\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}} + +\unexpanded\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf} +\unexpanded\def\emphit{\triggergroupedcommandcs\font_emphasis_it} +\unexpanded\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl} +\unexpanded\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf} +\unexpanded\def\emph {\triggergroupedcommandcs\em} \unexpanded\def\emphasized{\bgroup\em\let\nexttoken} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua index b1fcd9be8df..9ec116d47f3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-enh.lua @@ -115,7 +115,7 @@ local registerotffeature = otffeatures.register ----- tosixteen = fonts.mappings.tounicode16 -local function initializeunicoding(tfmdata) +local function initialize(tfmdata) local goodies = tfmdata.goodies local newcoding = nil for i=1,#goodies do @@ -165,18 +165,14 @@ local function initializeunicoding(tfmdata) end end -local unicoding_specification = { +local specification = { name = "unicoding", description = "adapt unicode table", initializers = { - base = initializeunicoding, - node = initializeunicoding, + base = initialize, + node = initialize, }, - -- manipulators = { - -- base = finalizeunicoding, - -- node = finalizeunicoding, - -- } } -registerotffeature(unicoding_specification) -registerafmfeature(unicoding_specification) +registerotffeature(specification) +registerafmfeature(specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua deleted file mode 100644 index d873dccd4d3..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ext.lua +++ /dev/null @@ -1,1856 +0,0 @@ -if not modules then modules = { } end modules ['font-ext'] = { - version = 1.001, - comment = "companion to font-ini.mkiv and hand-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local next, type, tonumber = next, type, tonumber -local byte, find, formatters = string.byte, string.find, string.formatters -local utfchar = utf.char -local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort - -local context = context -local fonts = fonts -local utilities = utilities - -local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end) -local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end) - -local report_expansions = logs.reporter("fonts","expansions") -local report_protrusions = logs.reporter("fonts","protrusions") - ---[[ldx-- -

When we implement functions that deal with features, most of them -will depend of the font format. Here we define the few that are kind -of neutral.

---ldx]]-- - -local handlers = fonts.handlers -local hashes = fonts.hashes -local otf = handlers.otf -local afm = handlers.afm - -local registerotffeature = otf.features.register -local registerafmfeature = afm.features.register - -local fontdata = hashes.identifiers -local fontproperties = hashes.properties - -local constructors = fonts.constructors -local getprivate = constructors.getprivate - -local allocate = utilities.storage.allocate -local settings_to_array = utilities.parsers.settings_to_array -local settings_to_hash = utilities.parsers.settings_to_hash -local getparameters = utilities.parsers.getparameters -local gettexdimen = tex.getdimen -local family_font = node.family_font - -local setmetatableindex = table.setmetatableindex - -local implement = interfaces.implement -local variables = interfaces.variables - - -local v_background = variables.background -local v_frame = variables.frame -local v_empty = variables.empty -local v_none = variables.none - --- -- -- -- -- -- --- shared --- -- -- -- -- -- - -local function get_class_and_vector(tfmdata,value,where) -- "expansions" - local g_where = tfmdata.goodies and tfmdata.goodies[where] - local f_where = fonts[where] - local g_classes = g_where and g_where.classes - local f_classes = f_where and f_where.classes - local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value]) - if class then - local class_vector = class.vector - local g_vectors = g_where and g_where.vectors - local f_vectors = f_where and f_where.vectors - local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector]) - return class, vector - end -end - --- -- -- -- -- -- --- expansion (hz) --- -- -- -- -- -- - -local expansions = fonts.expansions or allocate() - -fonts.expansions = expansions - -local classes = expansions.classes or allocate() -local vectors = expansions.vectors or allocate() - -expansions.classes = classes -expansions.vectors = vectors - --- beware, pdftex itself uses percentages * 10 --- --- todo: get rid of byte() here - -classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 } - -classes['quality'] = { - stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1 -} - -vectors['default'] = { - [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7, - [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7, - [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7, - [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7, - [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7, - [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7, - [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7, - [byte('w')] = 0.7, [byte('z')] = 0.7, - [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7, -} - -vectors['quality'] = vectors['default'] -- metatable ? - -local function initializeexpansion(tfmdata,value) - if value then - local class, vector = get_class_and_vector(tfmdata,value,"expansions") - if class then - if vector then - local stretch = class.stretch or 0 - local shrink = class.shrink or 0 - local step = class.step or 0 - local factor = class.factor or 1 - if trace_expansion then - report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a", - value,class.vector,factor,stretch,shrink,step) - end - tfmdata.parameters.expansion = { - stretch = 10 * stretch, - shrink = 10 * shrink, - step = 10 * step, - factor = factor, - } - local data = characters and characters.data - for i, chr in next, tfmdata.characters do - local v = vector[i] - if data and not v then -- we could move the data test outside (needed for plain) - local d = data[i] - if d then - local s = d.shcode - if not s then - -- sorry - elseif type(s) == "table" then - v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2 - else - v = vector[s] or 0 - end - end - end - if v and v ~= 0 then - chr.expansion_factor = v*factor - else -- can be option - chr.expansion_factor = factor - end - end - elseif trace_expansion then - report_expansions("unknown vector %a in class %a",class.vector,value) - end - elseif trace_expansion then - report_expansions("unknown class %a",value) - end - end -end - -local expansion_specification = { - name = "expansion", - description = "apply hz optimization", - initializers = { - base = initializeexpansion, - node = initializeexpansion, - } -} - -registerotffeature(expansion_specification) -registerafmfeature(expansion_specification) - -fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end) - -implement { - name = "setupfontexpansion", - arguments = "2 strings", - actions = function(class,settings) getparameters(classes,class,'preset',settings) end -} - --- -- -- -- -- -- --- protrusion --- -- -- -- -- -- - -fonts.protrusions = allocate() -local protrusions = fonts.protrusions - -protrusions.classes = allocate() -protrusions.vectors = allocate() - -local classes = protrusions.classes -local vectors = protrusions.vectors - --- the values need to be revisioned - -classes.preset = { factor = 1, left = 1, right = 1 } - -classes['pure'] = { - vector = 'pure', factor = 1 -} -classes['punctuation'] = { - vector = 'punctuation', factor = 1 -} -classes['alpha'] = { - vector = 'alpha', factor = 1 -} -classes['quality'] = { - vector = 'quality', factor = 1 -} - -vectors['pure'] = { - - [0x002C] = { 0, 1 }, -- comma - [0x002E] = { 0, 1 }, -- period - [0x003A] = { 0, 1 }, -- colon - [0x003B] = { 0, 1 }, -- semicolon - [0x002D] = { 0, 1 }, -- hyphen - [0x00AD] = { 0, 1 }, -- also hyphen - [0x2013] = { 0, 0.50 }, -- endash - [0x2014] = { 0, 0.33 }, -- emdash - [0x3001] = { 0, 1 }, -- ideographic comma 、 - [0x3002] = { 0, 1 }, -- ideographic full stop 。 - [0x060C] = { 0, 1 }, -- arabic comma ، - [0x061B] = { 0, 1 }, -- arabic semicolon ؛ - [0x06D4] = { 0, 1 }, -- arabic full stop ۔ - -} - -vectors['punctuation'] = { - - [0x003F] = { 0, 0.20 }, -- ? - [0x00BF] = { 0, 0.20 }, -- ¿ - [0x0021] = { 0, 0.20 }, -- ! - [0x00A1] = { 0, 0.20 }, -- ¡ - [0x0028] = { 0.05, 0 }, -- ( - [0x0029] = { 0, 0.05 }, -- ) - [0x005B] = { 0.05, 0 }, -- [ - [0x005D] = { 0, 0.05 }, -- ] - [0x002C] = { 0, 0.70 }, -- comma - [0x002E] = { 0, 0.70 }, -- period - [0x003A] = { 0, 0.50 }, -- colon - [0x003B] = { 0, 0.50 }, -- semicolon - [0x002D] = { 0, 0.70 }, -- hyphen - [0x00AD] = { 0, 0.70 }, -- also hyphen - [0x2013] = { 0, 0.30 }, -- endash - [0x2014] = { 0, 0.20 }, -- emdash - [0x060C] = { 0, 0.70 }, -- arabic comma - [0x061B] = { 0, 0.50 }, -- arabic semicolon - [0x06D4] = { 0, 0.70 }, -- arabic full stop - [0x061F] = { 0, 0.20 }, -- ؟ - - -- todo: left and right quotes: .5 double, .7 single - - [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹ - [0x203A] = { 0.70, 0.70 }, -- right single guillemet › - [0x00AB] = { 0.50, 0.50 }, -- left guillemet « - [0x00BB] = { 0.50, 0.50 }, -- right guillemet » - - [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘ - [0x2019] = { 0, 0.70 }, -- right single quotation mark ’ - [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark , - [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛ - [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “ - [0x201D] = { 0, 0.50 }, -- right double quotation mark ” - [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „ - [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟ - -} - -vectors['alpha'] = { - - [byte("A")] = { .05, .05 }, - [byte("F")] = { 0, .05 }, - [byte("J")] = { .05, 0 }, - [byte("K")] = { 0, .05 }, - [byte("L")] = { 0, .05 }, - [byte("T")] = { .05, .05 }, - [byte("V")] = { .05, .05 }, - [byte("W")] = { .05, .05 }, - [byte("X")] = { .05, .05 }, - [byte("Y")] = { .05, .05 }, - - [byte("k")] = { 0, .05 }, - [byte("r")] = { 0, .05 }, - [byte("t")] = { 0, .05 }, - [byte("v")] = { .05, .05 }, - [byte("w")] = { .05, .05 }, - [byte("x")] = { .05, .05 }, - [byte("y")] = { .05, .05 }, - -} - -vectors['quality'] = table.merged( - vectors['punctuation'], - vectors['alpha'] -) - --- As this is experimental code, users should not depend on it. The implications are still --- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the --- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The --- double trick should not be needed it proper hanging punctuation is used in which case --- values < 1 can be used. --- --- preferred (in context, usine vectors): --- --- \definefontfeature[whatever][default][mode=node,protrusion=quality] --- --- using lfbd and rtbd, with possibibility to enable only one side : --- --- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn] --- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn] --- --- idem, using multiplier --- --- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn] --- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn] --- --- idem, using named feature file (less frozen): --- --- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea] - -classes['double'] = { -- for testing opbd - factor = 2, left = 1, right = 1, -} - -local function map_opbd_onto_protrusion(tfmdata,value,opbd) - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local properties = tfmdata.properties - local resources = tfmdata.resources - local rawdata = tfmdata.shared.rawdata - local lookuphash = rawdata.lookuphash - local lookuptags = resources.lookuptags - local script = properties.script - local language = properties.language - local done, factor, left, right = false, 1, 1, 1 - local class = classes[value] - if class then - factor = class.factor or 1 - left = class.left or 1 - right = class.right or 1 - else - factor = tonumber(value) or 1 - end - if opbd ~= "right" then - local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language) - if validlookups then - for i=1,#lookuplist do - local lookup = lookuplist[i] - local steps = lookup.steps - if steps then - if trace_protrusion then - report_protrusions("setting left using lfbd") - end - for i=1,#steps do - local step = steps[i] - local coverage = step.coverage - if coverage then - for k, v in next, coverage do - -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same - local p = - (v[1] / 1000) * factor * left - characters[k].left_protruding = p - if trace_protrusion then - report_protrusions("lfbd -> %C -> %p",k,p) - end - end - end - end - done = true - end - end - end - end - if opbd ~= "left" then - local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language) - if validlookups then - for i=1,#lookuplist do - local lookup = lookuplist[i] - local steps = lookup.steps - if steps then - if trace_protrusion then - report_protrusions("setting right using rtbd") - end - for i=1,#steps do - local step = steps[i] - local coverage = step.coverage - if coverage then - for k, v in next, coverage do - -- local p = v[3] / descriptions[k].width -- or 3 - local p = (v[1] / 1000) * factor * right - characters[k].right_protruding = p - if trace_protrusion then - report_protrusions("rtbd -> %C -> %p",k,p) - end - end - end - end - end - done = true - end - end - end -end - --- The opbd test is just there because it was discussed on the context development list. However, --- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported --- till we have a proper test font. - -local function initializeprotrusion(tfmdata,value) - if value then - local opbd = tfmdata.shared.features.opbd - if opbd then - -- possible values: left right both yes no (experimental) - map_opbd_onto_protrusion(tfmdata,value,opbd) - else - local class, vector = get_class_and_vector(tfmdata,value,"protrusions") - if class then - if vector then - local factor = class.factor or 1 - local left = class.left or 1 - local right = class.right or 1 - if trace_protrusion then - report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a", - value,class.vector,factor,left,right) - end - local data = characters.data - local emwidth = tfmdata.parameters.quad - tfmdata.parameters.protrusion = { - factor = factor, - left = left, - right = right, - } - for i, chr in next, tfmdata.characters do - local v, pl, pr = vector[i], nil, nil - if v then - pl, pr = v[1], v[2] - else - local d = data[i] - if d then - local s = d.shcode - if not s then - -- sorry - elseif type(s) == "table" then - local vl, vr = vector[s[1]], vector[s[#s]] - if vl then pl = vl[1] end - if vr then pr = vr[2] end - else - v = vector[s] - if v then - pl, pr = v[1], v[2] - end - end - end - end - if pl and pl ~= 0 then - chr.left_protruding = left *pl*factor - end - if pr and pr ~= 0 then - chr.right_protruding = right*pr*factor - end - end - elseif trace_protrusion then - report_protrusions("unknown vector %a in class %a",class.vector,value) - end - elseif trace_protrusion then - report_protrusions("unknown class %a",value) - end - end - end -end - -local protrusion_specification = { - name = "protrusion", - description = "l/r margin character protrusion", - initializers = { - base = initializeprotrusion, - node = initializeprotrusion, - } -} - -registerotffeature(protrusion_specification) -registerafmfeature(protrusion_specification) - -fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end) - -implement { - name = "setupfontprotrusion", - arguments = "2 strings", - actions = function(class,settings) getparameters(classes,class,'preset',settings) end -} - --- -- -- - -local function initializenostackmath(tfmdata,value) - tfmdata.properties.nostackmath = value and true -end - -registerotffeature { - name = "nostackmath", - description = "disable math stacking mechanism", - initializers = { - base = initializenostackmath, - node = initializenostackmath, - } -} - -local function initializerealdimensions(tfmdata,value) - tfmdata.properties.realdimensions = value and true -end - -registerotffeature { - name = "realdimensions", - description = "accept negative dimenions", - initializers = { - base = initializerealdimensions, - node = initializerealdimensions, - } -} - -local function initializeitlc(tfmdata,value) -- hm, always value - if value then - -- the magic 40 and it formula come from Dohyun Kim but we might need another guess - local parameters = tfmdata.parameters - local italicangle = parameters.italicangle - if italicangle and italicangle ~= 0 then - local properties = tfmdata.properties - local factor = tonumber(value) or 1 - properties.hasitalics = true - properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 - end - end -end - -local italic_specification = { - name = "itlc", - description = "italic correction", - initializers = { - base = initializeitlc, - node = initializeitlc, - } -} - -registerotffeature(italic_specification) -registerafmfeature(italic_specification) - -local function initializetextitalics(tfmdata,value) -- yes no delay - tfmdata.properties.textitalics = toboolean(value) -end - -local textitalics_specification = { - name = "textitalics", - description = "use alternative text italic correction", - initializers = { - base = initializetextitalics, - node = initializetextitalics, - } -} - -registerotffeature(textitalics_specification) -registerafmfeature(textitalics_specification) - --- local function initializemathitalics(tfmdata,value) -- yes no delay --- tfmdata.properties.mathitalics = toboolean(value) --- end --- --- local mathitalics_specification = { --- name = "mathitalics", --- description = "use alternative math italic correction", --- initializers = { --- base = initializemathitalics, --- node = initializemathitalics, --- } --- } - --- registerotffeature(mathitalics_specification) --- registerafmfeature(mathitalics_specification) - --- slanting - -local function initializeslant(tfmdata,value) - value = tonumber(value) - if not value then - value = 0 - elseif value > 1 then - value = 1 - elseif value < -1 then - value = -1 - end - tfmdata.parameters.slantfactor = value -end - -local slant_specification = { - name = "slant", - description = "slant glyphs", - initializers = { - base = initializeslant, - node = initializeslant, - } -} - -registerotffeature(slant_specification) -registerafmfeature(slant_specification) - -local function initializeextend(tfmdata,value) - value = tonumber(value) - if not value then - value = 0 - elseif value > 10 then - value = 10 - elseif value < -10 then - value = -10 - end - tfmdata.parameters.extendfactor = value -end - -local extend_specification = { - name = "extend", - description = "scale glyphs horizontally", - initializers = { - base = initializeextend, - node = initializeextend, - } -} - -registerotffeature(extend_specification) -registerafmfeature(extend_specification) - --- For Wolfgang Schuster: --- --- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}] --- \definedfont[file:kozminpr6nregular*thisway] --- --- For the moment we don't mess with the descriptions. - -local function manipulatedimensions(tfmdata,key,value) - if type(value) == "string" and value ~= "" then - local characters = tfmdata.characters - local parameters = tfmdata.parameters - local emwidth = parameters.quad - local exheight = parameters.xheight - local newwidth = false - local newheight = false - local newdepth = false - if value == "strut" then - newheight = gettexdimen("strutht") - newdepth = gettexdimen("strutdp") - elseif value == "mono" then - newwidth = emwidth - else - local spec = settings_to_array(value) - newwidth = tonumber(spec[1]) - newheight = tonumber(spec[2]) - newdepth = tonumber(spec[3]) - if newwidth then newwidth = newwidth * emwidth end - if newheight then newheight = newheight * exheight end - if newdepth then newdepth = newdepth * exheight end - end - if newwidth or newheight or newdepth then - local additions = { } - for unicode, old_c in next, characters do - local oldwidth = old_c.width - local oldheight = old_c.height - local olddepth = old_c.depth - local width = newwidth or oldwidth or 0 - local height = newheight or oldheight or 0 - local depth = newdepth or olddepth or 0 - if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then - local private = getprivate(tfmdata) - local newslot = { "slot", 1, private } -- { "slot", 0, private } - local new_c - local commands = oldwidth ~= width and { - { "right", (width - oldwidth) / 2 }, - newslot, - } or { - newslot, - } - if height > 0 then - if depth > 0 then - new_c = { - width = width, - height = height, - depth = depth, - commands = commands, - } - else - new_c = { - width = width, - height = height, - commands = commands, - } - end - else - if depth > 0 then - new_c = { - width = width, - depth = depth, - commands = commands, - } - else - new_c = { - width = width, - commands = commands, - } - end - end - setmetatableindex(new_c,old_c) - characters[unicode] = new_c - additions[private] = old_c - end - end - for k, v in next, additions do - characters[k] = v - end - -- elseif height > 0 and depth > 0 then - -- for unicode, old_c in next, characters do - -- old_c.height = height - -- old_c.depth = depth - -- end - -- elseif height > 0 then - -- for unicode, old_c in next, characters do - -- old_c.height = height - -- end - -- elseif depth > 0 then - -- for unicode, old_c in next, characters do - -- old_c.depth = depth - -- end - end - end -end - -local dimensions_specification = { - name = "dimensions", - description = "force dimensions", - manipulators = { - base = manipulatedimensions, - node = manipulatedimensions, - } -} - -registerotffeature(dimensions_specification) -registerafmfeature(dimensions_specification) - --------------------------------------------------------------------------------------------------------------- - --- local function fakemonospace(tfmdata) --- local resources = tfmdata.resources --- local gposfeatures = resources.features.gpos --- local characters = tfmdata.characters --- local descriptions = tfmdata.descriptions --- local sequences = resources.sequences --- local coverage = { } --- local units = tfmdata.shared.rawdata.metadata.units --- for k, v in next, characters do --- local w = descriptions[k].width --- local d = units - w --- coverage[k] = { -d/2, 0, units, 0 } --- end --- local f = { dflt = { dflt = true } } --- local s = #sequences + 1 --- local t = { --- features = { fakemono = f }, --- flags = { false, false, false, false }, --- index = s, --- name = "p_s_" .. s, --- nofsteps = 1, --- order = { "fakemono" }, --- skiphash = false, --- type = "gpos_single", --- steps = { --- { --- format = "single", --- coverage = coverage, --- } --- } --- } --- gposfeatures["fakemono"] = f --- sequences[s] = t --- end --- --- fonts.constructors.features.otf.register { --- name = "fakemono", --- description = "fake monospaced", --- initializers = { --- node = fakemonospace, --- }, --- } - --------------------------------------------------------------------------------------------------------------- - --- for zhichu chen (see mailing list archive): we might add a few more variants --- in due time --- --- \definefontfeature[boxed][default][boundingbox=yes] % paleblue --- --- maybe: --- --- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression --- --- local gray = { "pdf", "origin", "/Tr1 gs .75 g" } --- local black = { "pdf", "origin", "/Tr0 gs 0 g" } - - --- boundingbox={yes|background|frame|empty|} - -local push = { "push" } -local pop = { "pop" } - ------ gray = { "pdf", "origin", ".75 g .75 G" } ------ black = { "pdf", "origin", "0 g 0 G" } ------ gray = { "pdf", ".75 g" } ------ black = { "pdf", "0 g" } - --- local bp = number.dimenfactors.bp --- --- local downcache = setmetatableindex(function(t,d) --- local v = { "down", d } --- t[d] = v --- return v --- end) --- --- local backcache = setmetatableindex(function(t,h) --- local h = h * bp --- local v = setmetatableindex(function(t,w) --- -- local v = { "rule", h, w } --- local v = { "pdf", "origin", formatters["0 0 %.6F %.6F re F"](w*bp,h) } --- t[w] = v --- return v --- end) --- t[h] = v --- return v --- end) --- --- local forecache = setmetatableindex(function(t,h) --- local h = h * bp --- local v = setmetatableindex(function(t,w) --- local v = { "pdf", "origin", formatters["%.6F w 0 0 %.6F %.6F re S"](0.25*65536*bp,w*bp,h) } --- t[w] = v --- return v --- end) --- t[h] = v --- return v --- end) - -local bp = number.dimenfactors.bp -local r = 16384 * bp -- 65536 // 4 - -local backcache = setmetatableindex(function(t,h) - local h = h * bp - local v = setmetatableindex(function(t,d) - local d = d * bp - local v = setmetatableindex(function(t,w) - local v = { "pdf", "origin", formatters["%.6F w 0 %.6F %.6F %.6F re f"](r,-d,w*bp,h+d) } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -local forecache = setmetatableindex(function(t,h) - local h = h * bp - local v = setmetatableindex(function(t,d) - local d = d * bp - local v = setmetatableindex(function(t,w) - -- the frame goes through the boundingbox - -- local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F re S"](r,-d,w*bp,h+d) } - local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"](r,r/2,-d+r/2,w*bp-r,h+d-r) } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -local startcolor = nil -local stopcolor = nil - -local function showboundingbox(tfmdata,key,value) - if value then - if not backcolors then - local vfspecials = backends.pdf.tables.vfspecials - startcolor = vfspecials.startcolor - stopcolor = vfspecials.stopcolor - end - local characters = tfmdata.characters - local additions = { } - local rulecache = backcache - local showchar = true - local color = "palegray" - if type(value) == "string" then - value = settings_to_array(value) - for i=1,#value do - local v = value[i] - if v == v_frame then - rulecache = forecache - elseif v == v_background then - rulecache = backcache - elseif v == v_empty then - showchar = false - elseif v == v_none then - color = nil - else - color = v - end - end - end - local gray = color and startcolor(color) or nil - local black = gray and stopcolor or nil - for unicode, old_c in next, characters do - local private = getprivate(tfmdata) - local width = old_c.width or 0 - local height = old_c.height or 0 - local depth = old_c.depth or 0 - local char = showchar and { "slot", 1, private } or nil -- { "slot", 0, private } - -- local new_c - -- if depth == 0 then - -- new_c = { - -- width = width, - -- height = height, - -- commands = { - -- push, - -- gray, - -- rulecache[height][width], - -- black, - -- pop, - -- char, - -- } - -- } - -- else - -- new_c = { - -- width = width, - -- height = height, - -- depth = depth, - -- commands = { - -- push, - -- downcache[depth], - -- gray, - -- rulecache[height+depth][width], - -- black, - -- pop, - -- char, - -- } - -- } - -- end - local rule = rulecache[height][depth][width] - local new_c = { - width = width, - height = height, - depth = depth, - commands = gray and { - -- push, - gray, - rule, - black, - -- pop, - char, - } or { - rule, - char, - } - } - setmetatableindex(new_c,old_c) - characters[unicode] = new_c - additions[private] = old_c - end - for k, v in next, additions do - characters[k] = v - end - end -end - -registerotffeature { - name = "boundingbox", - description = "show boundingbox", - manipulators = { - base = showboundingbox, - node = showboundingbox, - } -} - --- -- for notosans but not general --- --- do --- --- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local" --- --- local utfbyte = utf.byte --- --- local function initialize(tfmdata,key,value) --- local characters = tfmdata.characters --- local parameters = tfmdata.parameters --- local oldchar = 32 --- local newchar = 32 --- if value == "locl" or value == v_local then --- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar --- elseif value == true then --- -- use normal space --- elseif value then --- newchar = utfbyte(value) --- else --- return --- end --- local newchar = newchar and characters[newchar] --- local newspace = newchar and newchar.width --- if newspace > 0 then --- parameters.space = newspace --- parameters.space_stretch = newspace/2 --- parameters.space_shrink = newspace/3 --- parameters.extra_space = parameters.space_shrink --- end --- end --- --- registerotffeature { --- name = 'space', -- true|false|locl|character --- description = 'space settings', --- manipulators = { --- base = initialize, --- node = initialize, --- } --- } --- --- end - -do - - local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match - - local amount, stretch, shrink, extra - - local factor = lpegpatterns.unsigned - local space = lpegpatterns.space - local pattern = ( - (factor / function(n) amount = tonumber(n) or amount end) - + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end) - + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end) - + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end) - + space^1 - )^1 - - local function initialize(tfmdata,key,value) - local characters = tfmdata.characters - local parameters = tfmdata.parameters - if type(value) == "string" then - local emwidth = parameters.quad - amount, stretch, shrink, extra = 0, 0, 0, false - lpegmatch(pattern,value) - if not extra then - if shrink ~= 0 then - extra = shrink - elseif stretch ~= 0 then - extra = stretch - else - extra = amount - end - end - parameters.space = amount * emwidth - parameters.space_stretch = stretch * emwidth - parameters.space_shrink = shrink * emwidth - parameters.extra_space = extra * emwidth - end - end - - -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins - - registerotffeature { - name = "spacing", - description = "space settings", - manipulators = { - base = initialize, - node = initialize, - } - } - -end - --- -- historic stuff, move from font-ota (handled differently, typo-rep) --- --- local delete_node = nodes.delete --- local fontdata = fonts.hashes.identifiers --- --- local nodecodes = nodes.nodecodes --- local glyph_code = nodecodes.glyph --- --- local strippables = allocate() --- fonts.strippables = strippables --- --- strippables.joiners = table.tohash { --- 0x200C, -- zwnj --- 0x200D, -- zwj --- } --- --- strippables.all = table.tohash { --- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B, --- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C, --- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178, --- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026, --- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030, --- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A, --- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044, --- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E, --- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058, --- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062, --- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C, --- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076, --- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F, --- } --- --- strippables[true] = strippables.joiners --- --- local function processformatters(head,font) --- local subset = fontdata[font].shared.features.formatters --- local vector = subset and strippables[subset] --- if vector then --- local current, done = head, false --- while current do --- if current.id == glyph_code and current.subtype<256 and current.font == font then --- local char = current.char --- if vector[char] then --- head, current = delete_node(head,current) --- done = true --- else --- current = current.next --- end --- else --- current = current.next --- end --- end --- return head, done --- else --- return head, false --- end --- end --- --- registerotffeature { --- name = "formatters", --- description = "hide formatting characters", --- methods = { --- base = processformatters, --- node = processformatters, --- } --- } - --- not to be used! experimental code, only needed when testing - -local is_letter = characters.is_letter -local always = true - -local function collapseitalics(tfmdata,key,value) - local threshold = value == true and 100 or tonumber(value) - if threshold and threshold > 0 then - if threshold > 100 then - threshold = 100 - end - for unicode, data in next, tfmdata.characters do - if always or is_letter[unicode] or is_letter[data.unicode] then - local italic = data.italic - if italic and italic ~= 0 then - local width = data.width - if width and width ~= 0 then - local delta = threshold * italic / 100 - data.width = width + delta - data.italic = italic - delta - end - end - end - end - end -end - -local dimensions_specification = { - name = "collapseitalics", - description = "collapse italics", - manipulators = { - base = collapseitalics, - node = collapseitalics, - } -} - -registerotffeature(dimensions_specification) -registerafmfeature(dimensions_specification) - --- a handy helper (might change or be moved to another namespace) - -local nodepool = nodes.pool -local new_glyph = nodepool.glyph - -local helpers = fonts.helpers -local currentfont = font.current - -local currentprivate = 0xE000 -local maximumprivate = 0xEFFF - --- if we run out of space we can think of another range but by sharing we can --- use these privates for mechanisms like alignments-on-character and such - -local sharedprivates = setmetatableindex(function(t,k) - v = currentprivate - if currentprivate < maximumprivate then - currentprivate = currentprivate + 1 - else - -- reuse last slot, todo: warning - end - t[k] = v - return v -end) - -function helpers.addprivate(tfmdata,name,characterdata) - local properties = tfmdata.properties - local characters = tfmdata.characters - local privates = properties.privates - if not privates then - privates = { } - properties.privates = privates - end - if not name then - name = formatters["anonymous_private_0x%05X"](currentprivate) - end - local usedprivate = sharedprivates[name] - privates[name] = usedprivate - characters[usedprivate] = characterdata - return usedprivate -end - -local function getprivateslot(id,name) - if not name then - name = id - id = currentfont() - end - local properties = fontproperties[id] - local privates = properties and properties.privates - return privates and privates[name] -end - -local function getprivatenode(tfmdata,name) - if type(tfmdata) == "number" then - tfmdata = fontdata[tfmdata] - end - local properties = tfmdata.properties - local font = properties.id - local slot = getprivateslot(font,name) - if slot then - -- todo: set current attribibutes - local char = tfmdata.characters[slot] - local tonode = char.tonode - if tonode then - return tonode(font,char) - else - return new_glyph(font,slot) - end - end -end - -local function getprivatecharornode(tfmdata,name) - if type(tfmdata) == "number" then - tfmdata = fontdata[tfmdata] - end - local properties = tfmdata.properties - local font = properties.id - local slot = getprivateslot(font,name) - if slot then - -- todo: set current attributes - local char = tfmdata.characters[slot] - local tonode = char.tonode - if tonode then - return "node", tonode(tfmdata,char) - else - return "char", slot - end - end -end - -helpers.getprivateslot = getprivateslot -helpers.getprivatenode = getprivatenode -helpers.getprivatecharornode = getprivatecharornode - -function helpers.getprivates(tfmdata) - if type(tfmdata) == "number" then - tfmdata = fontdata[tfmdata] - end - local properties = tfmdata.properties - return properties and properties.privates -end - -function helpers.hasprivate(tfmdata,name) - if type(tfmdata) == "number" then - tfmdata = fontdata[tfmdata] - end - local properties = tfmdata.properties - local privates = properties and properties.privates - return privates and privates[name] or false -end - --- relatively new: - -do - - local extraprivates = { } - - function fonts.helpers.addextraprivate(name,f) - extraprivates[#extraprivates+1] = { name, f } - end - - local function addextraprivates(tfmdata) - for i=1,#extraprivates do - local e = extraprivates[i] - local c = e[2](tfmdata) - if c then - fonts.helpers.addprivate(tfmdata, e[1], c) - end - end - end - - constructors.newfeatures.otf.register { - name = "extraprivates", - description = "extra privates", - default = true, - manipulators = { - base = addextraprivates, - node = addextraprivates, - } - } - -end - -implement { - name = "getprivatechar", - arguments = "string", - actions = function(name) - local p = getprivateslot(name) - if p then - context(utfchar(p)) - end - end -} - -implement { - name = "getprivatemathchar", - arguments = "string", - actions = function(name) - local p = getprivateslot(family_font(0),name) - if p then - context(utfchar(p)) - end - end -} - -implement { - name = "getprivateslot", - arguments = "string", - actions = function(name) - local p = getprivateslot(name) - if p then - context(p) - end - end -} - --- requested for latex but not supported unless really needed in context: --- --- registerotffeature { --- name = "ignoremathconstants", --- description = "ignore math constants table", --- initializers = { --- base = function(tfmdata,value) --- if value then --- tfmdata.mathparameters = nil --- end --- end --- } --- } - --- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0 - -do - - local splitter = lpeg.splitat(",",tonumber) - local lpegmatch = lpeg.match - - local function initialize(tfmdata,value) - local mathparameters = tfmdata.mathparameters - if mathparameters then - local sup, sub - if type(value) == "string" then - sup, sub = lpegmatch(splitter,value) - if not sup then - sub, sup = 0, 0 - elseif not sub then - sub, sup = sup, 0 - end - elseif type(value) == "number" then - sup, sub = 0, value - end - mathparameters.NoLimitSupFactor = sup - mathparameters.NoLimitSubFactor = sub - end - end - - registerotffeature { - name = "mathnolimitsmode", - description = "influence nolimits placement", - initializers = { - base = initialize, - node = initialize, - } - } - -end - -do - - local function initialize(tfmdata,value) - local properties = tfmdata.properties - if properties then - properties.identity = value == "vertical" and "vertical" or "horizontal" - end - end - - registerotffeature { - name = "identity", - description = "set font identity", - initializers = { - base = initialize, - node = initialize, - } - } - - local function initialize(tfmdata,value) - local properties = tfmdata.properties - if properties then - properties.writingmode = value == "vertical" and "vertical" or "horizontal" - end - end - - registerotffeature { - name = "writingmode", - description = "set font direction", - initializers = { - base = initialize, - node = initialize, - } - } - -end - -do -- another hack for a crappy font - - local function additalictowidth(tfmdata,key,value) - local characters = tfmdata.characters - local additions = { } - for unicode, old_c in next, characters do - -- maybe check for math - local oldwidth = old_c.width - local olditalic = old_c.italic - if olditalic and olditalic ~= 0 then - local private = getprivate(tfmdata) - local new_c = { - width = oldwidth + olditalic, - height = old_c.height, - depth = old_c.depth, - commands = { - -- { "slot", 1, private }, - -- { "slot", 0, private }, - { "char", private }, - { "right", olditalic }, - }, - } - setmetatableindex(new_c,old_c) - characters[unicode] = new_c - additions[private] = old_c - end - end - for k, v in next, additions do - characters[k] = v - end - end - - registerotffeature { - name = "italicwidths", - description = "add italic to width", - manipulators = { - base = additalictowidth, - -- node = additalictowidth, -- only makes sense for math - } - } - -end - -do - - local tounicode = fonts.mappings.tounicode - - local function check(tfmdata,key,value) - if value == "ligatures" then - local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 - local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata) - if collected and next(collected)then - for unicode, char in next, tfmdata.characters do - if true then -- if unicode >= private or (unicode >= 0xE000 and unicode <= 0xF8FF) then - local u = collected[unicode] - if u then - local n = #u - for i=1,n do - if u[i] > private then - n = 0 - break - end - end - if n > 0 then - if n == 1 then - u = u[1] - end - char.unicode = u - char.tounicode = tounicode(u) - end - end - end - end - end - end - end - - -- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji) - -- - -- kind of like: \enabletrackers[fonts.mapping.forceligatures] - - registerotffeature { - name = "forceunicodes", - description = "forceunicodes", - manipulators = { - base = check, - node = check, - } - } - -end - -do - - -- This is a rather special test-only feature that I added for the sake of testing - -- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a - -- font, in spite of what the description of handling arabic suggests. And indeed, - -- mixed-in lookups of other features (like all these ss* in husayni) are handled - -- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort - -- according to the "assumed" order so e.g. the ss* move to after the standard - -- features. The observed difference in rendering is an indication that uniscribe is - -- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some - -- interference, apart from some hard coded init etc expectations). Anyway, it means - -- that we're okay with the (generic) node processor. A pitfall is that in context - -- we can actually control more, so we can trigger an analyze pass with e.g. - -- dflt/dflt while the libraries depend on the script settings for that. Uniscribe - -- probably also parses the string and when seeing arabic will follow a different - -- code path, although it seems to treat all features equal. - - local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end) - local report_reorder = logs.reporter("fonts","reorder") - - local vectors = { } - - vectors.arab = { - gsub = { - ccmp = 1, - isol = 2, - fina = 3, - medi = 4, - init = 5, - rlig = 6, - rclt = 7, - calt = 8, - liga = 9, - dlig = 10, - cswh = 11, - mset = 12, - }, - gpos = { - curs = 1, - kern = 2, - mark = 3, - mkmk = 4, - }, - } - - function otf.reorderlookups(tfmdata,vector) - local order = vectors[vector] - if not order then - return - end - local oldsequences = tfmdata.resources.sequences - if oldsequences then - local sequences = { } - for i=1,#oldsequences do - sequences[i] = oldsequences[i] - end - for i=1,#sequences do - local s = sequences[i] - local features = s.features - local kind = s.type - local index = s.index - if features then - local when - local what - for feature in sortedhash(features) do - if not what then - what = find(kind,"^gsub") and "gsub" or "gpos" - end - local newwhen = order[what][feature] - if not newwhen then - -- skip - elseif not when then - when = newwhen - elseif newwhen < when then - when = newwhen - end - end - s.ondex = s.index - s.index = i - s.what = what == "gsub" and 1 or 2 - s.when = when or 99 - else - s.ondex = s.index - s.index = i - s.what = 1 - s.when = 99 - end - end - sort(sequences,function(a,b) - local what_a = a.what - local what_b = b.what - if what_a ~= what_b then - return a.index < b.index - end - local when_a = a.when - local when_b = b.when - if when_a == when_b then - return a.index < b.index - else - return when_a < when_b - end - end) - local swapped = 0 - for i=1,#sequences do - local sequence = sequences[i] - local features = sequence.features - if features then - local index = sequence.index - if index ~= i then - swapped = swapped + 1 - end - if trace_reorder then - if swapped == 1 then - report_reorder() - report_reorder("start swapping lookups in font %!font:name!",tfmdata) - report_reorder() - report_reorder("gsub order: % t",table.swapped(order.gsub)) - report_reorder("gpos order: % t",table.swapped(order.gpos)) - report_reorder() - end - report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t", - i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99, - (index > i and "-") or (index < i and "+") or "=",sortedkeys(features)) - end - end - sequence.what = nil - sequence.when = nil - sequence.index = sequence.ondex - end - if swapped > 0 then - if trace_reorder then - report_reorder() - report_reorder("stop swapping lookups, %i lookups swapped",swapped) - report_reorder() - end --- tfmdata.resources.sequences = sequences - tfmdata.shared.reorderedsequences = sequences - end - end - end - - -- maybe delay till ra is filled - - local function reorderlookups(tfmdata,key,value) - if value then - otf.reorderlookups(tfmdata,value) - end - end - - registerotffeature { - name = "reorderlookups", - description = "reorder lookups", - manipulators = { - base = reorderlookups, - node = reorderlookups, - } - } - -end - --- maybe useful - -local function initializeoutline(tfmdata,value) - value = tonumber(value) - if not value then - value = 0 - else - value = tonumber(value) or 0 - end - if value then - value = value * 1000 - end - tfmdata.parameters.mode = 1 - tfmdata.parameters.width = value -end - -local outline_specification = { - name = "outline", - description = "outline glyphs", - initializers = { - base = initializeoutline, - node = initializeoutline, - } -} - -registerotffeature(outline_specification) -registerafmfeature(outline_specification) - --- definitely ugly - -local report_effect = logs.reporter("fonts","effect") -local trace_effect = false - -trackers.register("fonts.effect", function(v) trace_effect = v end) - -local effects = { - inner = 0, - normal = 0, - outer = 1, - outline = 1, - both = 2, - hidden = 3, -} - -local function initializeeffect(tfmdata,value) - local spec - if type(value) == "number" then - spec = { width = value } - else - spec = settings_to_hash(value) - end - local effect = spec.effect or "both" - local width = tonumber(spec.width) or 0 - local mode = effects[effect] - if not mode then - report_effect("invalid effect %a",effect) - elseif width == 0 and mode == 0 then - report_effect("invalid width %a for effect %a",width,effect) - else - local parameters = tfmdata.parameters - local properties = tfmdata.properties - parameters.mode = mode - parameters.width = width * 1000 - local factor = tonumber(spec.factor) or 0 - local hfactor = tonumber(spec.vfactor) or factor - local vfactor = tonumber(spec.hfactor) or factor - local delta = tonumber(spec.delta) or 1 - local wdelta = tonumber(spec.wdelta) or delta - local hdelta = tonumber(spec.hdelta) or delta - local ddelta = tonumber(spec.ddelta) or hdelta - properties.effect = { - effect = effect, - width = width, - factor = factor, - hfactor = hfactor, - vfactor = vfactor, - wdelta = wdelta, - hdelta = hdelta, - ddelta = ddelta, - } - end -end - -local function manipulateeffect(tfmdata) - local effect = tfmdata.properties.effect - if effect then - local characters = tfmdata.characters - local parameters = tfmdata.parameters - local multiplier = effect.width * 100 - local wdelta = effect.wdelta * parameters.hfactor * multiplier - local hdelta = effect.hdelta * parameters.vfactor * multiplier - local ddelta = effect.ddelta * parameters.vfactor * multiplier - local hshift = wdelta / 2 - local factor = (1 + effect.factor) * parameters.factor - local hfactor = (1 + effect.hfactor) * parameters.hfactor - local vfactor = (1 + effect.vfactor) * parameters.vfactor - for unicode, old_c in next, characters do - local oldwidth = old_c.width - local oldheight = old_c.height - local olddepth = old_c.depth - if oldwidth and oldwidth > 0 then - old_c.width = oldwidth + wdelta - old_c.commands = { - { "right", hshift }, - { "char", unicode }, - } - end - if oldheight and oldheight > 0 then - old_c.height = oldheight + hdelta - end - if olddepth and olddepth > 0 then - old_c.depth = olddepth + ddelta - end - end - parameters.factor = factor - parameters.hfactor = hfactor - parameters.vfactor = vfactor - if trace_effect then - report_effect("applying effect") - report_effect(" effect : %s", effect.effect) - report_effect(" width : %s => %s", effect.width, multiplier) - report_effect(" factor : %s => %s", effect.factor, factor ) - report_effect(" hfactor : %s => %s", effect.hfactor,hfactor) - report_effect(" vfactor : %s => %s", effect.vfactor,vfactor) - report_effect(" wdelta : %s => %s", effect.wdelta, wdelta) - report_effect(" hdelta : %s => %s", effect.hdelta, hdelta) - report_effect(" ddelta : %s => %s", effect.ddelta, ddelta) - end - end -end - -local effect_specification = { - name = "effect", - description = "apply effects to glyphs", - initializers = { - base = initializeeffect, - node = initializeeffect, - }, - manipulators = { - base = manipulateeffect, - node = manipulateeffect, - }, -} - -registerotffeature(effect_specification) -registerafmfeature(effect_specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua index 79ebc3f2557..122e43ddc71 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-fbk.lua @@ -14,38 +14,38 @@ local next = next

This is very experimental code!

--ldx]]-- -local trace_combining_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_combining_visualize = v end) -local trace_combining_define = false trackers.register("fonts.composing.define", function(v) trace_combining_define = v end) +local trace_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_visualize = v end) +local trace_define = false trackers.register("fonts.composing.define", function(v) trace_define = v end) -trackers.register("fonts.combining", "fonts.composing.define") -- for old times sake (and manuals) -trackers.register("fonts.combining.all", "fonts.composing.*") -- for old times sake (and manuals) - -local report_combining = logs.reporter("fonts","combining") - -local force_combining = false -- just for demo purposes (see mk) +local report = logs.reporter("fonts","combining") local allocate = utilities.storage.allocate local fonts = fonts local handlers = fonts.handlers local constructors = fonts.constructors +local helpers = fonts.helpers local otf = handlers.otf local afm = handlers.afm local registerotffeature = otf.features.register local registerafmfeature = afm.features.register +local addotffeature = otf.addfeature + local unicodecharacters = characters.data local unicodefallbacks = characters.fallbacks -local vf = handlers.vf -local commands = vf.combiner.commands -local push = vf.predefined.push -local pop = vf.predefined.pop +local vfcommands = helpers.commands +local charcommand = vfcommands.char +local rightcommand = vfcommands.right +local downcommand = vfcommands.down +local upcommand = vfcommands.up +local push = vfcommands.push +local pop = vfcommands.pop -local force_composed = false -local cache = { } -- we could make these weak -local fraction = 0.15 -- 30 units for lucida +local force_combining = false -- just for demo purposes (see mk) +local fraction = 0.15 -- 30 units for lucida -- todo: we also need to update the feature hashes ... i'll do that when i'm in the mood -- and/or when i need it @@ -65,15 +65,15 @@ local function composecharacters(tfmdata) local italicfactor = parameters.italicfactor or 0 local vfspecials = backends.tables.vfspecials --brr local red, green, blue, black - if trace_combining_visualize then + if trace_visualize then red = vfspecials.startcolor("red") green = vfspecials.startcolor("green") blue = vfspecials.startcolor("blue") black = vfspecials.stopcolor end local compose = fonts.goodies.getcompositions(tfmdata) - if compose and trace_combining_visualize then - report_combining("using compose information from goodies file") + if compose and trace_visualize then + report("using compose information from goodies file") end local done = false for i, c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory @@ -105,31 +105,25 @@ local function composecharacters(tfmdata) acc = unicodefallbacks[acc] charsacc = acc and characters[acc] end - local chr_t = cache[chr] - if not chr_t then - -- chr_t = { "slot", 1, chr } - -- chr_t = { "slot", 0, chr } - chr_t = { "char", chr } - cache[chr] = chr_t - end + local chr_t = charcommand[chr] if charsacc then - if trace_combining_define then - report_combining("composed %C, base %C, accent %C",i,chr,acc) - end - local acc_t = cache[acc] - if not acc_t then - -- acc_t = { "slot", 1, acc } - -- acc_t = { "slot", 0, acc } - acc_t = { "char", acc } - cache[acc] = acc_t + if trace_define then + report("composed %C, base %C, accent %C",i,chr,acc) end + local acc_t = charcommand[acc] local cb = descriptions[chr].boundingbox local ab = descriptions[acc].boundingbox -- todo: adapt height if cb and ab then - local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4] - local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4] - local done = false + local c_llx = scale*cb[1] + local c_lly = scale*cb[2] + local c_urx = scale*cb[3] + local c_ury = scale*cb[4] + local a_llx = scale*ab[1] + local a_lly = scale*ab[2] + local a_urx = scale*ab[3] + local a_ury = scale*ab[4] + local done = false if compose then local i_compose = compose[i] local i_anchored = i_compose and i_compose.anchored @@ -148,26 +142,30 @@ local function composecharacters(tfmdata) local ay = a_anchor.y or 0 local dx = cx - ax local dy = cy - ay - if trace_combining_define then - report_combining("building %C from %C and %C",i,chr,acc) - report_combining(" boundingbox:") - report_combining(" chr: %3i %3i %3i %3i",unpack(cb)) - report_combining(" acc: %3i %3i %3i %3i",unpack(ab)) - report_combining(" anchors:") - report_combining(" chr: %3i %3i",cx,cy) - report_combining(" acc: %3i %3i",ax,ay) - report_combining(" delta:") - report_combining(" %s: %3i %3i",i_anchored,dx,dy) + if trace_define then + report("building %C from %C and %C",i,chr,acc) + report(" boundingbox:") + report(" chr: %3i %3i %3i %3i",unpack(cb)) + report(" acc: %3i %3i %3i %3i",unpack(ab)) + report(" anchors:") + report(" chr: %3i %3i",cx,cy) + report(" acc: %3i %3i",ax,ay) + report(" delta:") + report(" %s: %3i %3i",i_anchored,dx,dy) end - if trace_combining_visualize then - t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, green, acc_t, black, pop, chr_t } - -- t.commands = { - -- push, {"right", scale*cx}, {"down", -scale*cy}, red, {"rule",10000,10000,10000}, pop, - -- push, {"right", scale*ax}, {"down", -scale*ay}, blue, {"rule",10000,10000,10000}, pop, - -- push, {"right", scale*dx}, {"down", -scale*dy}, green, acc_t, black, pop, chr_t - -- } + local right = rightcommand[scale*dx] + local down = upcommand[scale*dy] + if trace_visualize then + t.commands = { + push, right, down, + green, acc_t, black, + pop, chr_t, + } else - t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, acc_t, pop, chr_t } + t.commands = { + push, right, down, + acc_t, pop, chr_t, + } end done = true end @@ -179,10 +177,17 @@ local function composecharacters(tfmdata) local dx = (c_urx - a_urx - a_llx + c_llx)/2 local dd = (c_urx - c_llx)*italicfactor if a_ury < 0 then - if trace_combining_visualize then - t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t } + local right = rightcommand[dx-dd] + if trace_visualize then + t.commands = { + push, right, red, acc_t, + black, pop, chr_t, + } else - t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t } + t.commands = { + push, right, acc_t, pop, + chr_t, + } end elseif c_ury > a_lly then -- messy test local dy @@ -214,27 +219,46 @@ local function composecharacters(tfmdata) else dy = - deltaxheight + extraxheight end - if trace_combining_visualize then - t.commands = { push, { "right", dx+dd }, { "down", dy }, green, acc_t, black, pop, chr_t } + local right = rightcommand[dx+dd] + local down = downcommand[dy] + if trace_visualize then + t.commands = { + push, right, down, green, + acc_t, black, pop, chr_t, + } else - t.commands = { push, { "right", dx+dd }, { "down", dy }, acc_t, pop, chr_t } + t.commands = { + push, right, down, acc_t, + pop, chr_t, + } end else - if trace_combining_visualize then - t.commands = { push, { "right", dx+dd }, blue, acc_t, black, pop, chr_t } + local right = rightcommand[dx+dd] + if trace_visualize then + t.commands = { + push, right, blue, acc_t, + black, pop, chr_t, + } else - t.commands = { push, { "right", dx+dd }, acc_t, pop, chr_t } + t.commands = { + push, right, acc_t, pop, + chr_t, + } end end end else - t.commands = { chr_t } -- else index mess + t.commands = { + chr_t, -- else index mess + } end else - if trace_combining_define then - report_combining("%C becomes simplified %C",i,chr) + if trace_define then + report("%C becomes simplified %C",i,chr) end - t.commands = { chr_t } -- else index mess + t.commands = { + chr_t, -- else index mess + } end done = true characters[i] = t @@ -254,7 +278,7 @@ local function composecharacters(tfmdata) end end -local compose_specification = { +local specification = { name = "compose", description = "additional composed characters", manipulators = { @@ -263,75 +287,71 @@ local compose_specification = { } } -registerotffeature(compose_specification) -registerafmfeature(compose_specification) +registerotffeature(specification) +registerafmfeature(specification) -vf.helpers.composecharacters = composecharacters +addotffeature { + name = "char-ligatures", + type = "ligature", + data = characters.splits.char, + order = { "char-ligatures" }, + prepend = true, +} --- This installs the builder into the regular virtual font builder, --- which only makes sense as demo. +addotffeature { + name = "compat-ligatures", + type = "ligature", + data = characters.splits.compat, + order = { "compat-ligatures" }, + prepend = true, +} -commands["compose.trace.enable"] = function() - trace_combining_visualize = true -end +registerotffeature { + name = 'char-ligatures', + description = 'unicode char specials to ligatures', +} -commands["compose.trace.disable"] = function() - trace_combining_visualize = false -end +registerotffeature { + name = 'compat-ligatures', + description = 'unicode compat specials to ligatures', +} -commands["compose.force.enable"] = function() - force_combining = true -end +do -commands["compose.force.disable"] = function() - force_combining = false -end + -- This installs the builder into the regular virtual font builder, + -- which only makes sense as demo. -commands["compose.trace.set"] = function(g,v) - if v[2] == nil then - trace_combining_visualize = true - else - trace_combining_visualize = v[2] - end -end - -commands["compose.apply"] = function(g,v) - composecharacters(g) -end + local vf = handlers.vf + local commands = vf.combiner.commands --- vf builder + vf.helpers.composecharacters = composecharacters --- { "pdf", "origin", "q " .. s .. " 0 0 " .. s .. " 0 0 cm" }, --- { "pdf", "origin", "q 1 0 0 1 " .. -w .. " " .. -h .. " cm" }, --- { "pdf", "origin", "/Fm\XX\space Do" }, --- { "pdf", "origin", "Q" }, --- { "pdf", "origin", "Q" }, + commands["compose.trace.enable"] = function() + trace_visualize = true + end --- new and experimental + commands["compose.trace.disable"] = function() + trace_visualize = false + end -local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } -local noflags = { } + commands["compose.force.enable"] = function() + force_combining = true + end -local char_specification = { - type = "ligature", - features = everywhere, - data = characters.splits.char, - order = { "char-ligatures" }, - flags = noflags, - prepend = true, -} + commands["compose.force.disable"] = function() + force_combining = false + end -local compat_specification = { - type = "ligature", - features = everywhere, - data = characters.splits.compat, - order = { "compat-ligatures" }, - flags = noflags, - prepend = true, -} + commands["compose.trace.set"] = function(g,v) + if v[2] == nil then + trace_visualize = true + else + trace_visualize = v[2] + end + end -otf.addfeature("char-ligatures", char_specification) -- xlig (extra) -otf.addfeature("compat-ligatures",compat_specification) -- plig (pseudo) + commands["compose.apply"] = function(g,v) + composecharacters(g) + end -registerotffeature { name = 'char-ligatures', description = 'unicode char specials to ligatures' } -registerotffeature { name = 'compat-ligatures', description = 'unicode compat specials to ligatures' } +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi index 5f65543ab9e..4a5356090e9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-fea.mkvi @@ -368,11 +368,19 @@ % \doifelsecurrentfonthasfeature{crap}{YES}{NO} % \doifelsecurrentfonthasfeature{kern}{YES}{NO} -\def\doifelsecurrentfonthasfeature#feature% +\def\doifelsecurrentfonthasfeature#feature% expandable {\clf_doifelsecurrentfonthasfeature{#feature}} \let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature +\def\doifelsefontfeature#feature% expandable + {\clf_doifelsefontfeature{#feature}} + +\let\doiffontfeatureelse\doifelsefontfeature + +\def\doifunknownfontfeature#feature% expandable + {\clf_doifunknownfontfeature{#feature}} + % new: \clf_registerlanguagefeatures diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi index 01fa4a3380e..16ce57f8ad9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-fil.mkvi @@ -42,19 +42,17 @@ % % \setupbodyfont[palatino] -\let\fontclass\empty - \unexpanded\def\startfontclass {\dosingleempty\font_basics_start_font_class} \def\font_basics_start_font_class[#class]% - {\pushmacro\fontclass + {\push_macro_fontclass \doifelse{#class}\v!each {\let\fontclass\empty} {\doifsomething{#class}{\def\fontclass{#class}}}} \unexpanded\def\stopfontclass - {\popmacro\fontclass} + {\pop_macro_fontclass} \def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt] @@ -109,11 +107,14 @@ \let\p_designsize\undefined \expandafter\font_basics_get_font_parameter_yes#specification,]=,} +% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that +% can be default then: \let\mathsizesuffix\relax .. i need to play with it first + \def\font_basics_get_font_parameter_nop#key=#value,% {\if]#key% \font_basics_get_font_parameter_nop_finish \else - \expandafter\normaldef\csname p_#key\endcsname{#value}% + \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix \expandafter\font_basics_get_font_parameter_nop \fi} @@ -121,13 +122,13 @@ {\if]#key% \font_basics_get_font_parameter_yes_finish \else - \expandafter\normaldef\csname p_#key\endcsname{#value}% + \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix \expandafter\font_basics_get_font_parameter_yes \fi} % helpers, some day these will be toks and counts -% \def\fntsetdefname {\global\let\somefontname\defaultfontfile} +% \def\fntsetdefname {\glet\somefontname\defaultfontfile} % \def\fntsetsomename{\gdef\somefontname} % takes argument % \def\fntsetnopsize {\let\somefontsize\empty} % \def\fntsetsomesize{\def\somefontsize} % takes argument @@ -145,10 +146,10 @@ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\undefined} \def\font_basics_define_font_synonym_yes_nil - {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined} + {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined} \def\font_basics_get_font_parameter_nop_finish {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\p_features @@ -157,10 +158,10 @@ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize} \def\font_basics_get_font_parameter_yes_finish - {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies - \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize} + {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies + \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize} %\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}] % @@ -306,6 +307,8 @@ #2% \fi\fi} +\installmacrostack\fontclass + %D Files or names can have properties and these need to be consulted %D at some point. They can inherit them. diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua deleted file mode 100644 index 8f1acac65a5..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/font-gbn.lua +++ /dev/null @@ -1,262 +0,0 @@ -if not modules then modules = { } end modules ['font-gbn'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- generic [base|node] mode handler - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local next = next - -local fonts = fonts -local nodes = nodes - -local nuts = nodes.nuts -- context abstraction of direct nodes - -local traverse_id = nuts.traverse_id -local flush_node = nuts.flush_node - -local glyph_code = nodes.nodecodes.glyph -local disc_code = nodes.nodecodes.disc - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getboth = nuts.getboth -local getprev = nuts.getprev -local getnext = nuts.getnext -local getdisc = nuts.getdisc -local setchar = nuts.setchar -local setlink = nuts.setlink -local setprev = nuts.setprev - --- from now on we apply ligaturing and kerning here because it might interfere with complex --- opentype discretionary handling where the base ligature pass expect some weird extra --- pointers (which then confuse the tail slider that has some checking built in) - -local n_ligaturing = node.ligaturing -local n_kerning = node.kerning - -local ligaturing = nuts.ligaturing -local kerning = nuts.kerning - -local basemodepass = true - -local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning = nil end -local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning = nil end - -function node.ligaturing(...) - if basemodepass and l_warning then - l_warning() - end - return n_ligaturing(...) -end - -function node.kerning(...) - if basemodepass and k_warning then - k_warning() - end - return n_kerning(...) -end - -function nodes.handlers.setbasemodepass(v) - basemodepass = v -end - --------- nodes.handlers.nodepass(head) -function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) - local fontdata = fonts.hashes.identifiers - if fontdata then - local nuthead = tonut(head) - local usedfonts = { } - local basefonts = { } - local prevfont = nil - local basefont = nil - local variants = nil - local redundant = nil - local nofused = 0 - for n in traverse_id(glyph_code,nuthead) do - local font = getfont(n) - if font ~= prevfont then - if basefont then - basefont[2] = getprev(n) - end - prevfont = font - local used = usedfonts[font] - if not used then - local tfmdata = fontdata[font] -- - if tfmdata then - local shared = tfmdata.shared -- we need to check shared, only when same features - if shared then - local processors = shared.processes - if processors and #processors > 0 then - usedfonts[font] = processors - nofused = nofused + 1 - elseif basemodepass then - basefont = { n, nil } - basefonts[#basefonts+1] = basefont - end - end - local resources = tfmdata.resources - variants = resources and resources.variants - variants = variants and next(variants) and variants or false - end - else - local tfmdata = fontdata[prevfont] - if tfmdata then - local resources = tfmdata.resources - variants = resources and resources.variants - variants = variants and next(variants) and variants or false - end - end - end - if variants then - local char = getchar(n) - if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then - local hash = variants[char] - if hash then - local p = getprev(n) - if p and getid(p) == glyph_code then - local variant = hash[getchar(p)] - if variant then - setchar(p,variant) - end - end - end - -- per generic user request we always remove selectors - if not redundant then - redundant = { n } - else - redundant[#redundant+1] = n - end - end - end - end - local nofbasefonts = #basefonts - if redundant then - for i=1,#redundant do - local r = redundant[i] - local p, n = getboth(r) - if r == nuthead then - nuthead = n - setprev(n) - else - setlink(p,n) - end - if nofbasefonts > 0 then - for i=1,nofbasefonts do - local bi = basefonts[i] - if r == bi[1] then - bi[1] = n - end - if r == bi[2] then - bi[2] = n - end - end - end - flush_node(r) - end - end - for d in traverse_id(disc_code,nuthead) do - local _, _, r = getdisc(d) - if r then - for n in traverse_id(glyph_code,r) do - local font = getfont(n) - if font ~= prevfont then - prevfont = font - local used = usedfonts[font] - if not used then - local tfmdata = fontdata[font] -- - if tfmdata then - local shared = tfmdata.shared -- we need to check shared, only when same features - if shared then - local processors = shared.processes - if processors and #processors > 0 then - usedfonts[font] = processors - nofused = nofused + 1 - end - end - end - end - end - end - end - end - if next(usedfonts) then - for font, processors in next, usedfonts do - for i=1,#processors do - head = processors[i](head,font,0,direction,nofused) or head - end - end - end - if basemodepass and nofbasefonts > 0 then - for i=1,nofbasefonts do - local range = basefonts[i] - local start = range[1] - local stop = range[2] - if start then - local front = nuthead == start - local prev, next - if stop then - next = getnext(stop) - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) - else - prev = getprev(start) - start = ligaturing(start) - start = kerning(start) - end - if prev then - setlink(prev,start) - end - if next then - setlink(stop,next) - end - if front and nuthead ~= start then - head = tonode(start) - end - end - end - end - return head, true - else - return head, false - end -end - -function nodes.handlers.basepass(head) - if basemodepass then - head = n_ligaturing(head) - head = n_kerning(head) - end - return head, true -end - -local nodepass = nodes.handlers.nodepass -local basepass = nodes.handlers.basepass -local injectpass = nodes.injections.handler -local protectpass = nodes.handlers.protectglyphs - -function nodes.simple_font_handler(head,groupcode,size,packtype,direction) - if head then - head = nodepass(head,groupcode,size,packtype,direction) - head = injectpass(head) - if not basemodepass then - head = basepass(head) - end - protectpass(head) - return head, true - else - return head, false - end -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi index 549ede46f6c..05cf087903c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-gds.mkvi @@ -62,7 +62,7 @@ % % \definedfont[husayni*husayni-colored at 36pt] % -% \starttext \pardir TRT \textdir TRT +% \starttext \righttoleft % % \setfontcolorscheme[1] % diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua b/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua index 60a27c043b8..8d1e85145fb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-hsh.lua @@ -18,48 +18,50 @@ fonts.hashes = hashes -- todo: autoallocate ... just create on the fly .. use constructors.keys (problem: plurals) -local identifiers = hashes.identifiers or allocate() -local characters = hashes.characters or allocate() -- chardata -local descriptions = hashes.descriptions or allocate() -local parameters = hashes.parameters or allocate() -local properties = hashes.properties or allocate() -local resources = hashes.resources or allocate() -local spacings = hashes.spacings or allocate() -local spaces = hashes.spaces or allocate() -local quads = hashes.quads or allocate() -- maybe also spacedata -local xheights = hashes.xheights or allocate() -local csnames = hashes.csnames or allocate() -- namedata -local features = hashes.features or allocate() -local marks = hashes.marks or allocate() -local classes = hashes.classes or allocate() -local italics = hashes.italics or allocate() -local lastmathids = hashes.lastmathids or allocate() -local dynamics = hashes.dynamics or allocate() -local unicodes = hashes.unicodes or allocate() -local originals = hashes.originals or allocate() -local modes = hashes.modes or allocate() -local variants = hashes.variants or allocate() - -hashes.characters = characters -hashes.descriptions = descriptions -hashes.parameters = parameters -hashes.properties = properties -hashes.resources = resources -hashes.spacings = spacings -hashes.spaces = spaces -hashes.quads = quads hashes.emwidths = quads -hashes.xheights = xheights hashes.exheights = xheights -hashes.csnames = csnames -hashes.features = features -hashes.marks = marks -hashes.classes = classes -hashes.italics = italics -hashes.lastmathids = lastmathids -hashes.dynamics = dynamics -hashes.unicodes = unicodes -hashes.originals = originals -hashes.modes = modes -hashes.variants = variants +local identifiers = hashes.identifiers or allocate() +local characters = hashes.characters or allocate() -- chardata +local descriptions = hashes.descriptions or allocate() +local parameters = hashes.parameters or allocate() +local mathparameters = hashes.mathparameters or allocate() +local properties = hashes.properties or allocate() +local resources = hashes.resources or allocate() +local spacings = hashes.spacings or allocate() +local spaces = hashes.spaces or allocate() +local quads = hashes.quads or allocate() -- maybe also spacedata +local xheights = hashes.xheights or allocate() +local csnames = hashes.csnames or allocate() -- namedata +local features = hashes.features or allocate() +local marks = hashes.marks or allocate() +local classes = hashes.classes or allocate() +local italics = hashes.italics or allocate() +local lastmathids = hashes.lastmathids or allocate() +local dynamics = hashes.dynamics or allocate() +local unicodes = hashes.unicodes or allocate() +local originals = hashes.originals or allocate() +local modes = hashes.modes or allocate() +local variants = hashes.variants or allocate() + +hashes.characters = characters +hashes.descriptions = descriptions +hashes.parameters = parameters +hashes.mathparameters = mathparameters +hashes.properties = properties +hashes.resources = resources +hashes.spacings = spacings +hashes.spaces = spaces +hashes.quads = quads hashes.emwidths = quads +hashes.xheights = xheights hashes.exheights = xheights +hashes.csnames = csnames +hashes.features = features +hashes.marks = marks +hashes.classes = classes +hashes.italics = italics +hashes.lastmathids = lastmathids +hashes.dynamics = dynamics +hashes.unicodes = unicodes +hashes.originals = originals +hashes.modes = modes +hashes.variants = variants local nodepool = nodes and nodes.pool local dummyglyph = nodepool and nodepool.register(nodepool.glyph()) @@ -68,7 +70,9 @@ local nulldata = allocate { name = "nullfont", characters = { }, descriptions = { }, - properties = { }, + properties = { + designsize = 786432, + }, parameters = { -- lmromanregular @ 12pt slantperpoint = 0, spacing = { @@ -87,6 +91,7 @@ local nulldata = allocate { x_height = 338952, -- 5 quad = 786432, -- 6 extra_space = 85459, -- 7 + size = 786432, }, } @@ -148,6 +153,16 @@ setmetatableindex(parameters, function(t,k) end end) +setmetatableindex(mathparameters, function(t,k) + if k == true then + return mathparameters[currentfont()] + else + local mathparameters = identifiers[k].mathparameters + t[k] = mathparameters + return mathparameters + end +end) + setmetatableindex(properties, function(t,k) if k == true then return properties[currentfont()] diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-dimensions.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-dimensions.lua new file mode 100644 index 00000000000..a7125625da7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-dimensions.lua @@ -0,0 +1,115 @@ +if not modules then modules = { } end modules ['font-imp-dimensions'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next, type, tonumber = next, type, tonumber + +local fonts = fonts +local utilities = utilities + +local helpers = fonts.helpers +local prependcommands = helpers.prependcommands +local charcommand = helpers.commands.char +local rightcommand = helpers.commands.right + +local handlers = fonts.handlers +local otf = handlers.otf +local afm = handlers.afm + +local registerotffeature = otf.features.register +local registerafmfeature = afm.features.register + +local settings_to_array = utilities.parsers.settings_to_array +local gettexdimen = tex.getdimen + +-- For Wolfgang Schuster: +-- +-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}] +-- \definedfont[file:kozminpr6nregular*thisway] + +local function initialize(tfmdata,key,value) + if type(value) == "string" and value ~= "" then + local characters = tfmdata.characters + local parameters = tfmdata.parameters + local emwidth = parameters.quad + local exheight = parameters.xheight + local newwidth = false + local newheight = false + local newdepth = false + if value == "strut" then + newheight = gettexdimen("strutht") + newdepth = gettexdimen("strutdp") + elseif value == "mono" then + newwidth = emwidth + else + local spec = settings_to_array(value) + newwidth = tonumber(spec[1]) + newheight = tonumber(spec[2]) + newdepth = tonumber(spec[3]) + if newwidth then newwidth = newwidth * emwidth end + if newheight then newheight = newheight * exheight end + if newdepth then newdepth = newdepth * exheight end + end + if newwidth or newheight or newdepth then + for unicode, character in next, characters do + local oldwidth = character.width + local oldheight = character.height + local olddepth = character.depth + local width = newwidth or oldwidth or 0 + local height = newheight or oldheight or 0 + local depth = newdepth or olddepth or 0 + if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then + character.width = width + character.height = height + character.depth = depth + if oldwidth ~= width then + local commands = character.commands + local hshift = rightcommand[(width - oldwidth) / 2] + if commands then + character.commands = prependcommands ( + commands, + hshift + ) + else + character.commands = { + hshift, + charcommand[unicode], + } + end + end + end + end + end + end +end + +local specification = { + name = "dimensions", + description = "force dimensions", + manipulators = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local function initialize(tfmdata,value) + tfmdata.properties.realdimensions = value and true +end + +registerotffeature { + name = "realdimensions", + description = "accept negative dimenions", + initializers = { + base = initialize, + node = initialize, + } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-effects.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-effects.lua new file mode 100644 index 00000000000..cc6e4c0bf88 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-effects.lua @@ -0,0 +1,414 @@ +if not modules then modules = { } end modules ['font-imp-effects'] = { + version = 1.001, + 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" +} + +-- todo: pickup from goodies: if type(effect) then ... + +local next, type, tonumber = next, type, tonumber +local is_boolean = string.is_boolean + +local fonts = fonts + +local handlers = fonts.handlers +local registerotffeature = handlers.otf.features.register +local registerafmfeature = handlers.afm.features.register + +local settings_to_hash = utilities.parsers.settings_to_hash_colon_too + +local helpers = fonts.helpers +local prependcommands = helpers.prependcommands +local charcommand = helpers.commands.char +local leftcommand = helpers.commands.left +local rightcommand = helpers.commands.right +local upcommand = helpers.commands.up +local downcommand = helpers.commands.down +local dummycommand = helpers.commands.dummy + +----- constructors = fonts.constructors +----- getmathparameter = constructors.getmathparameter +----- setmathparameter = constructors.setmathparameter + +local report_effect = logs.reporter("fonts","effect") +local report_slant = logs.reporter("fonts","slant") +local report_extend = logs.reporter("fonts","extend") +local report_squeeze = logs.reporter("fonts","squeeze") + +local trace = false + +trackers.register("fonts.effect", function(v) trace = v end) +trackers.register("fonts.slant", function(v) trace = v end) +trackers.register("fonts.extend", function(v) trace = v end) +trackers.register("fonts.squeeze",function(v) trace = v end) + +local function initializeslant(tfmdata,value) + value = tonumber(value) + if not value then + value = 0 + elseif value > 1 then + value = 1 + elseif value < -1 then + value = -1 + end + if trace then + report_slant("applying %0.3f",value) + end + tfmdata.parameters.slantfactor = value +end + +local specification = { + name = "slant", + description = "slant glyphs", + initializers = { + base = initializeslant, + node = initializeslant, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local function initializeextend(tfmdata,value) + value = tonumber(value) + if not value then + value = 0 + elseif value > 10 then + value = 10 + elseif value < -10 then + value = -10 + end + if trace then + report_extend("applying %0.3f",value) + end + tfmdata.parameters.extendfactor = value +end + +local specification = { + name = "extend", + description = "scale glyphs horizontally", + initializers = { + base = initializeextend, + node = initializeextend, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local function initializesqueeze(tfmdata,value) + value = tonumber(value) + if not value then + value = 0 + elseif value > 10 then + value = 10 + elseif value < -10 then + value = -10 + end + if trace then + report_squeeze("applying %0.3f",value) + end + tfmdata.parameters.squeezefactor = value +end + +local specification = { + name = "squeeze", + description = "scale glyphs vertically", + initializers = { + base = initializesqueeze, + node = initializesqueeze, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local effects = { + inner = 0, + normal = 0, + outer = 1, + outline = 1, + both = 2, + hidden = 3, +} + +local function initializeeffect(tfmdata,value) + local spec + if type(value) == "number" then + spec = { width = value } + else + spec = settings_to_hash(value) + end + local effect = spec.effect or "both" + local width = tonumber(spec.width) or 0 + local mode = effects[effect] + if not mode then + report_effect("invalid effect %a",effect) + elseif width == 0 and mode == 0 then + report_effect("invalid width %a for effect %a",width,effect) + else + local parameters = tfmdata.parameters + local properties = tfmdata.properties + parameters.mode = mode + parameters.width = width * 1000 + if is_boolean(spec.auto) == true then + local squeeze = 1 - width/20 + local average = (1 - squeeze) * width * 100 + spec.squeeze = squeeze + spec.extend = 1 + width/2 + spec.wdelta = average + spec.hdelta = average/2 + spec.ddelta = average/2 + spec.vshift = average/2 + end + local factor = tonumber(spec.factor) or 0 + local hfactor = tonumber(spec.hfactor) or factor + local vfactor = tonumber(spec.vfactor) or factor + local delta = tonumber(spec.delta) or 1 + local wdelta = tonumber(spec.wdelta) or delta + local hdelta = tonumber(spec.hdelta) or delta + local ddelta = tonumber(spec.ddelta) or hdelta + local vshift = tonumber(spec.vshift) or 0 + local slant = spec.slant + local extend = spec.extend + local squeeze = spec.squeeze + if slant then + initializeslant(tfmdata,slant) + end + if extend then + initializeextend(tfmdata,extend) + end + if squeeze then + initializesqueeze(tfmdata,squeeze) + end + properties.effect = { + effect = effect, + width = width, + factor = factor, + hfactor = hfactor, + vfactor = vfactor, + wdelta = wdelta, + hdelta = hdelta, + ddelta = ddelta, + vshift = vshift, + slant = tfmdata.parameters.slantfactor, + extend = tfmdata.parameters.extendfactor, + squeeze = tfmdata.parameters.squeezefactor, + } + end +end + +local rules = { + "RadicalRuleThickness", + "OverbarRuleThickness", + "FractionRuleThickness", + "UnderbarRuleThickness", +} + +-- local commands = char.commands +-- if commands then +-- local command = commands[1] +-- if command and command[1] == "right" then +-- commands[1] = rightcommand[command[2]-snap] +-- end +-- end + +local function setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze) + if delta ~= 0 then + for i=1,#rules do + local name = rules[i] + local value = mathparameters[name] + if value then + mathparameters[name] = (squeeze or 1) * (value + dx) + end + end + end +end + +local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta) + + local function wdpatch(char) + if wsnap ~= 0 then + char.width = char.width + wdelta/2 + end + end + + local function htpatch(char) + if hsnap ~= 0 then + local height = char.height + if height then + char.height = char.height + 2 * dy + end + end + end + + local character = characters[0x221A] + + if character and character.next then +-- print("base char",0x221A,table.sequenced(character)) + local char = character + local next = character.next + wdpatch(char) + htpatch(char) + while next do + char = characters[next] + wdpatch(char) + htpatch(char) +-- print("next char",next,table.sequenced(char)) + next = char.next + end + if char then + local v = char.vert_variants + if v then + local top = v[#v] + if top then + local char = characters[top.glyph] +-- print("top char",top.glyph,table.sequenced(char)) + htpatch(char) + end + end + end + end +end + +-- local show_effect = { "lua", function(f,c) +-- report_effect("font id %i, char %C",f,c) +-- inspect(fonts.hashes.characters[f][c]) +-- end } + +-- local show_effect = { "lua", "print('!')" } + +local function manipulateeffect(tfmdata) + local effect = tfmdata.properties.effect + if effect then + local characters = tfmdata.characters + local parameters = tfmdata.parameters + local mathparameters = tfmdata.mathparameters + local multiplier = effect.width * 100 + local factor = parameters.factor + local hfactor = parameters.hfactor + local vfactor = parameters.vfactor + local wdelta = effect.wdelta * hfactor * multiplier + local hdelta = effect.hdelta * vfactor * multiplier + local ddelta = effect.ddelta * vfactor * multiplier + local vshift = effect.vshift * vfactor * multiplier + local squeeze = effect.squeeze + local hshift = wdelta / 2 + local dx = multiplier * vfactor + local dy = vshift + local factor = (1 + effect.factor) * factor + local hfactor = (1 + effect.hfactor) * hfactor + local vfactor = (1 + effect.vfactor) * vfactor + local vshift = vshift ~= 0 and upcommand[vshift] or false + for unicode, character in next, characters do + local oldwidth = character.width + local oldheight = character.height + local olddepth = character.depth + if oldwidth and oldwidth > 0 then + character.width = oldwidth + wdelta + local commands = character.commands + local hshift = rightcommand[hshift] + if vshift then + if commands then + prependcommands ( commands, +-- show_effect, + hshift, + vshift + ) + else + character.commands = { +-- show_effect, + hshift, + vshift, + charcommand[unicode] + } + end + else + if commands then + prependcommands ( commands, +-- show_effect, + hshift + ) + else + character.commands = { +-- show_effect, + hshift, + charcommand[unicode] + } + end + end + end + if oldheight and oldheight > 0 then + character.height = oldheight + hdelta + end + if olddepth and olddepth > 0 then + character.depth = olddepth + ddelta + end + end + if mathparameters then + setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze) + setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta) + end + parameters.factor = factor + parameters.hfactor = hfactor + parameters.vfactor = vfactor + if trace then + report_effect("applying") + report_effect(" effect : %s", effect.effect) + report_effect(" width : %s => %s", effect.width, multiplier) + report_effect(" factor : %s => %s", effect.factor, factor ) + report_effect(" hfactor : %s => %s", effect.hfactor,hfactor) + report_effect(" vfactor : %s => %s", effect.vfactor,vfactor) + report_effect(" wdelta : %s => %s", effect.wdelta, wdelta) + report_effect(" hdelta : %s => %s", effect.hdelta, hdelta) + report_effect(" ddelta : %s => %s", effect.ddelta, ddelta) + end + end +end + +local specification = { + name = "effect", + description = "apply effects to glyphs", + initializers = { + base = initializeeffect, + node = initializeeffect, + }, + manipulators = { + base = manipulateeffect, + node = manipulateeffect, + }, +} + +registerotffeature(specification) +registerafmfeature(specification) + +local function initializeoutline(tfmdata,value) + value = tonumber(value) + if not value then + value = 0 + else + value = tonumber(value) or 0 + end + local parameters = tfmdata.parameters + local properties = tfmdata.properties + parameters.mode = effects.outline + parameters.width = value * 1000 + properties.effect = { + effect = effect, + width = width, + } +end + +local specification = { + name = "outline", + description = "outline glyphs", + initializers = { + base = initializeoutline, + node = initializeoutline, + } +} + +registerotffeature(specification) +registerafmfeature(specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-italics.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-italics.lua new file mode 100644 index 00000000000..83c785d3876 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-italics.lua @@ -0,0 +1,147 @@ +if not modules then modules = { } end modules ['font-imp-italics'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local next = next + +local fonts = fonts +local handlers = fonts.handlers +local registerotffeature = handlers.otf.features.register +local registerafmfeature = handlers.afm.features.register + +local function initialize(tfmdata,key,value) + for unicode, character in next, tfmdata.characters do + local olditalic = character.italic + if olditalic and olditalic ~= 0 then + character.width = character.width + olditalic + character.italic = 0 + end + end +end + +local specification = { + name = "italicwidths", + description = "add italic to width", + manipulators = { + base = initialize, + node = initialize, -- only makes sense for math + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local function initialize(tfmdata,value) -- hm, always value + if value then + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess + local parameters = tfmdata.parameters + local italicangle = parameters.italicangle + if italicangle and italicangle ~= 0 then + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 + end + end +end + +local specification = { + name = "itlc", + description = "italic correction", + initializers = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +if context then + + local function initialize(tfmdata,value) -- yes no delay + tfmdata.properties.textitalics = toboolean(value) + end + + local specification = { + name = "textitalics", + description = "use alternative text italic correction", + initializers = { + base = initialize, + node = initialize, + } + } + + registerotffeature(specification) + registerafmfeature(specification) + +end + +-- no longer used + +-- if context then +-- +-- -- local function initializemathitalics(tfmdata,value) -- yes no delay +-- -- tfmdata.properties.mathitalics = toboolean(value) +-- -- end +-- -- +-- -- local specification = { +-- -- name = "mathitalics", +-- -- description = "use alternative math italic correction", +-- -- initializers = { +-- -- base = initializemathitalics, +-- -- node = initializemathitalics, +-- -- } +-- -- } +-- -- +-- -- registerotffeature(specification) +-- -- registerafmfeature(specification) +-- +-- end + +-- -- also not used, only when testing + +if context then + + local letter = characters.is_letter + local always = true + + local function collapseitalics(tfmdata,key,value) + local threshold = value == true and 100 or tonumber(value) + if threshold and threshold > 0 then + if threshold > 100 then + threshold = 100 + end + for unicode, data in next, tfmdata.characters do + if always or letter[unicode] or letter[data.unicode] then + local italic = data.italic + if italic and italic ~= 0 then + local width = data.width + if width and width ~= 0 then + local delta = threshold * italic / 100 + data.width = width + delta + data.italic = italic - delta + end + end + end + end + end + end + + local dimensions_specification = { + name = "collapseitalics", + description = "collapse italics", + manipulators = { + base = collapseitalics, + node = collapseitalics, + } + } + + registerotffeature(dimensions_specification) + registerafmfeature(dimensions_specification) + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-ligatures.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-ligatures.lua new file mode 100644 index 00000000000..091eb5d4b45 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-ligatures.lua @@ -0,0 +1,136 @@ +if not modules then modules = { } end modules ['font-imp-ligatures'] = { + version = 1.001, + 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 lpegmatch = lpeg.match +local utfsplit = utf.split +local settings_to_array = utilities.parsers.settings_to_array + +local fonts = fonts +local otf = fonts.handlers.otf +local registerotffeature = otf.features.register +local addotffeature = otf.addfeature + +-- This is a quick and dirty hack. + +local lookups = { } +local protect = { } +local revert = { } +local zwjchar = 0x200C +local zwj = { zwjchar } + +addotffeature { + name = "blockligatures", + type = "chainsubstitution", + nocheck = true, -- because there is no 0x200C in the font + prepend = true, -- make sure we do it early + future = true, -- avoid nilling due to no steps yet + lookups = { + { + type = "multiple", + data = lookups, + }, + }, + data = { + rules = protect, + } +} + +addotffeature { + name = "blockligatures", + type = "chainsubstitution", + nocheck = true, -- because there is no 0x200C in the font + append = true, -- this is done late + overload = false, -- we don't want to overload the previous definition + lookups = { + { + type = "ligature", + data = lookups, + }, + }, + data = { + rules = revert, + } +} + +registerotffeature { + name = 'blockligatures', + description = 'block certain ligatures', +} + +local splitter = lpeg.splitat(":") + +local function blockligatures(str) + + local t = settings_to_array(str) + + for i=1,#t do + local ti = t[i] + local before, current, after = lpegmatch(splitter,ti) + if current and after then -- before is returned when no match + -- experimental joke + if before then + before = utfsplit(before) + for i=1,#before do + before[i] = { before[i] } + end + end + if current then + current = utfsplit(current) + end + if after then + after = utfsplit(after) + for i=1,#after do + after[i] = { after[i] } + end + end + else + before = nil + current = utfsplit(ti) + after = nil + end + if #current > 1 then + local one = current[1] + local two = current[2] + lookups[one] = { one, zwjchar } + local one = { one } + local two = { two } + local new = #protect + 1 + protect[new] = { + before = before, + current = { one, two }, + after = after, + lookups = { 1 }, -- not shared ! + } + revert[new] = { + -- before = before, + current = { one, zwj }, + -- after = { two, unpack(after) }, + after = { two }, + lookups = { 1 }, -- not shared ! + } + end + end +end + +-- blockligatures("\0\0") + +otf.helpers.blockligatures = blockligatures + +-- blockligatures("fi,ff") +-- blockligatures("fl") +-- blockligatures("u:fl:age") + +if context then + + interfaces.implement { + name = "blockligatures", + arguments = "string", + actions = blockligatures, + } + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-math.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-math.lua new file mode 100644 index 00000000000..d93ece4059b --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-math.lua @@ -0,0 +1,81 @@ +if not modules then modules = { } end modules ['font-imp-math'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next, type, tonumber = next, type, tonumber + +local fonts = fonts +local helpers = fonts.helpers +local registerotffeature = fonts.handlers.otf.features.register + +local setmetatableindex = table.setmetatableindex + +-- requested for latex but not supported unless really needed in context: +-- +-- registerotffeature { +-- name = "ignoremathconstants", +-- description = "ignore math constants table", +-- initializers = { +-- base = function(tfmdata,value) +-- if value then +-- tfmdata.mathparameters = nil +-- end +-- end +-- } +-- } + +-- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0 + +local splitter = lpeg.splitat(",",tonumber) +local lpegmatch = lpeg.match + +local function initialize(tfmdata,value) + local mathparameters = tfmdata.mathparameters + if mathparameters then + local sup, sub + if type(value) == "string" then + sup, sub = lpegmatch(splitter,value) + if not sup then + sub, sup = 0, 0 + elseif not sub then + sub, sup = sup, 0 + end + elseif type(value) == "number" then + sup, sub = 0, value + end + if sup then + mathparameters.NoLimitSupFactor = sup + end + if sub then + mathparameters.NoLimitSubFactor = sub + end + end +end + +registerotffeature { + name = "mathnolimitsmode", + description = "influence nolimits placement", + initializers = { + base = initialize, + node = initialize, + } +} + +local function initialize(tfmdata,value) + tfmdata.properties.nostackmath = value and true +end + +registerotffeature { + name = "nostackmath", + description = "disable math stacking mechanism", + initializers = { + base = initialize, + node = initialize, + } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-notused.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-notused.lua new file mode 100644 index 00000000000..be36c98988e --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-notused.lua @@ -0,0 +1,168 @@ +if not modules then modules = { } end modules ['font-imp-notused'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +-- local next = next +-- local utfbyte = utf.byte +-- +-- local fonts = fonts +-- +-- local handlers = fonts.handlers +-- local otf = handlers.otf +-- local afm = handlers.afm +-- +-- local registerotffeature = otf.features.register +-- local registerafmfeature = afm.features.register + +-- local function initialize(tfmdata) +-- local resources = tfmdata.resources +-- local gposfeatures = resources.features.gpos +-- local characters = tfmdata.characters +-- local descriptions = tfmdata.descriptions +-- local sequences = resources.sequences +-- local coverage = { } +-- local units = tfmdata.shared.rawdata.metadata.units +-- for k, v in next, characters do +-- local w = descriptions[k].width +-- local d = units - w +-- coverage[k] = { -d/2, 0, units, 0 } +-- end +-- local f = { dflt = { dflt = true } } +-- local s = #sequences + 1 +-- local t = { +-- features = { fakemono = f }, +-- flags = { false, false, false, false }, +-- index = s, +-- name = "p_s_" .. s, +-- nofsteps = 1, +-- order = { "fakemono" }, +-- skiphash = false, +-- type = "gpos_single", +-- steps = { +-- { +-- format = "single", +-- coverage = coverage, +-- } +-- } +-- } +-- gposfeatures["fakemono"] = f +-- sequences[s] = t +-- end +-- +-- registerotffeature { +-- name = "fakemono", +-- description = "fake monospaced", +-- initializers = { +-- node = initialize, +-- }, +-- } + +-- -- for notosans but not general +-- +-- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local" +-- +-- local function initialize(tfmdata,key,value) +-- local characters = tfmdata.characters +-- local parameters = tfmdata.parameters +-- local oldchar = 32 +-- local newchar = 32 +-- if value == "locl" or value == v_local then +-- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar +-- elseif value == true then +-- -- use normal space +-- elseif value then +-- newchar = utfbyte(value) +-- else +-- return +-- end +-- local newchar = newchar and characters[newchar] +-- local newspace = newchar and newchar.width +-- if newspace > 0 then +-- parameters.space = newspace +-- parameters.space_stretch = newspace/2 +-- parameters.space_shrink = newspace/3 +-- parameters.extra_space = parameters.space_shrink +-- end +-- end +-- +-- registerotffeature { +-- name = 'space', -- true|false|locl|character +-- description = 'space settings', +-- manipulators = { +-- base = initialize, +-- node = initialize, +-- } +-- } + +-- -- historic stuff, move from font-ota (handled differently, typo-rep) +-- +-- local delete_node = nodes.delete +-- local fontdata = fonts.hashes.identifiers +-- +-- local nodecodes = nodes.nodecodes +-- local glyph_code = nodecodes.glyph +-- +-- local strippables = allocate() +-- fonts.strippables = strippables +-- +-- strippables.joiners = table.tohash { +-- 0x200C, -- zwnj +-- 0x200D, -- zwj +-- } +-- +-- strippables.all = table.tohash { +-- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B, +-- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C, +-- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178, +-- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026, +-- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030, +-- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A, +-- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044, +-- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E, +-- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058, +-- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062, +-- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C, +-- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076, +-- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F, +-- } +-- +-- strippables[true] = strippables.joiners +-- +-- local function processformatters(head,font) +-- local subset = fontdata[font].shared.features.formatters +-- local vector = subset and strippables[subset] +-- if vector then +-- local current, done = head, false +-- while current do +-- if current.id == glyph_code and current.subtype<256 and current.font == font then +-- local char = current.char +-- if vector[char] then +-- head, current = delete_node(head,current) +-- done = true +-- else +-- current = current.next +-- end +-- else +-- current = current.next +-- end +-- end +-- return head, done +-- else +-- return head, false +-- end +-- end +-- +-- registerotffeature { +-- name = "formatters", +-- description = "hide formatting characters", +-- methods = { +-- base = processformatters, +-- node = processformatters, +-- } +-- } diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-properties.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-properties.lua new file mode 100644 index 00000000000..5805235b780 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-properties.lua @@ -0,0 +1,130 @@ +if not modules then modules = { } end modules ['font-imp-properties'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next, type, tonumber, select = next, type, tonumber, select +local byte, find, formatters = string.byte, string.find, string.formatters +local utfchar = utf.char +local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort +local insert = table.insert + +local context = context +local fonts = fonts +local utilities = utilities + +local helpers = fonts.helpers + +local handlers = fonts.handlers +local hashes = fonts.hashes +local otf = handlers.otf +local afm = handlers.afm + +local registerotffeature = otf.features.register +local registerafmfeature = afm.features.register + +local fontdata = hashes.identifiers +local fontproperties = hashes.properties + +local constructors = fonts.constructors +local getprivate = constructors.getprivate + +local allocate = utilities.storage.allocate +local family_font = node.family_font + +local setmetatableindex = table.setmetatableindex + +local implement = interfaces.implement + +do + + local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match + + local amount, stretch, shrink, extra + + local factor = lpegpatterns.unsigned + local space = lpegpatterns.space + local pattern = ( + (factor / function(n) amount = tonumber(n) or amount end) + + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end) + + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end) + + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end) + + space^1 + )^1 + + local function initialize(tfmdata,key,value) + local characters = tfmdata.characters + local parameters = tfmdata.parameters + if type(value) == "string" then + local emwidth = parameters.quad + amount, stretch, shrink, extra = 0, 0, 0, false + lpegmatch(pattern,value) + if not extra then + if shrink ~= 0 then + extra = shrink + elseif stretch ~= 0 then + extra = stretch + else + extra = amount + end + end + parameters.space = amount * emwidth + parameters.space_stretch = stretch * emwidth + parameters.space_shrink = shrink * emwidth + parameters.extra_space = extra * emwidth + end + end + + -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins + + registerotffeature { + name = "spacing", + description = "space settings", + manipulators = { + base = initialize, + node = initialize, + } + } + +end + +do + + local function initialize(tfmdata,value) + local properties = tfmdata.properties + if properties then + properties.identity = value == "vertical" and "vertical" or "horizontal" + end + end + + registerotffeature { + name = "identity", + description = "set font identity", + initializers = { + base = initialize, + node = initialize, + } + } + + local function initialize(tfmdata,value) + local properties = tfmdata.properties + if properties then + properties.writingmode = value == "vertical" and "vertical" or "horizontal" + end + end + + registerotffeature { + name = "writingmode", + description = "set font direction", + initializers = { + base = initialize, + node = initialize, + } + } + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-quality.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-quality.lua new file mode 100644 index 00000000000..01f0afe6309 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-quality.lua @@ -0,0 +1,527 @@ +if not modules then modules = { } end modules ['font-imp-quality'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next, type, tonumber = next, type, tonumber +local byte = string.byte +local insert = table.insert + +local fonts = fonts +local utilities = utilities + +local handlers = fonts.handlers +local otf = handlers.otf +local afm = handlers.afm +local registerotffeature = otf.features.register +local registerafmfeature = afm.features.register + +local allocate = utilities.storage.allocate +local getparameters = utilities.parsers.getparameters + +local implement = interfaces and interfaces.implement + +local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end) +local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end) + +local report_expansions = logs.reporter("fonts","expansions") +local report_protrusions = logs.reporter("fonts","protrusions") + +-- -- -- -- -- -- +-- shared +-- -- -- -- -- -- + +local function get_class_and_vector(tfmdata,value,where) -- "expansions" + local g_where = tfmdata.goodies and tfmdata.goodies[where] + local f_where = fonts[where] + local g_classes = g_where and g_where.classes + local f_classes = f_where and f_where.classes + local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value]) + if class then + local class_vector = class.vector + local g_vectors = g_where and g_where.vectors + local f_vectors = f_where and f_where.vectors + local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector]) + return class, vector + end +end + +-- -- -- -- -- -- +-- expansion (hz) +-- -- -- -- -- -- + +local expansions = fonts.expansions or allocate() + +fonts.expansions = expansions + +local classes = expansions.classes or allocate() +local vectors = expansions.vectors or allocate() + +expansions.classes = classes +expansions.vectors = vectors + +-- beware, pdftex itself uses percentages * 10 +-- +-- todo: get rid of byte() here + +classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 } + +classes['quality'] = { + stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1 +} + +vectors['default'] = { + [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7, + [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7, + [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7, + [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7, + [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7, + [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7, + [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7, + [byte('w')] = 0.7, [byte('z')] = 0.7, + [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7, +} + +vectors['quality'] = vectors['default'] -- metatable ? + +local function initialize(tfmdata,value) + if value then + local class, vector = get_class_and_vector(tfmdata,value,"expansions") + if class then + if vector then + local stretch = class.stretch or 0 + local shrink = class.shrink or 0 + local step = class.step or 0 + local factor = class.factor or 1 + if trace_expansion then + report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a", + value,class.vector,factor,stretch,shrink,step) + end + tfmdata.parameters.expansion = { + stretch = 10 * stretch, + shrink = 10 * shrink, + step = 10 * step, + factor = factor, + } + local data = characters and characters.data + for i, chr in next, tfmdata.characters do + local v = vector[i] + if data and not v then -- we could move the data test outside (needed for plain) + local d = data[i] + if d then + local s = d.shcode + if not s then + -- sorry + elseif type(s) == "table" then + v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2 + else + v = vector[s] or 0 + end + end + end + if v and v ~= 0 then + chr.expansion_factor = v*factor + else -- can be option + chr.expansion_factor = factor + end + end + elseif trace_expansion then + report_expansions("unknown vector %a in class %a",class.vector,value) + end + elseif trace_expansion then + report_expansions("unknown class %a",value) + end + end +end + +local specification = { + name = "expansion", + description = "apply hz optimization", + initializers = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end) + +if context then + + implement { + name = "setupfontexpansion", + arguments = "2 strings", + actions = function(class,settings) getparameters(classes,class,'preset',settings) end + } + +end + +-- -- -- -- -- -- +-- protrusion +-- -- -- -- -- -- + +fonts.protrusions = allocate() +local protrusions = fonts.protrusions + +protrusions.classes = allocate() +protrusions.vectors = allocate() + +local classes = protrusions.classes +local vectors = protrusions.vectors + +-- the values need to be revisioned + +classes.preset = { factor = 1, left = 1, right = 1 } + +classes['pure'] = { + vector = 'pure', factor = 1 +} +classes['punctuation'] = { + vector = 'punctuation', factor = 1 +} +classes['alpha'] = { + vector = 'alpha', factor = 1 +} +classes['quality'] = { + vector = 'quality', factor = 1 +} + +vectors['pure'] = { + + [0x002C] = { 0, 1 }, -- comma + [0x002E] = { 0, 1 }, -- period + [0x003A] = { 0, 1 }, -- colon + [0x003B] = { 0, 1 }, -- semicolon + [0x002D] = { 0, 1 }, -- hyphen + [0x00AD] = { 0, 1 }, -- also hyphen + [0x2013] = { 0, 0.50 }, -- endash + [0x2014] = { 0, 0.33 }, -- emdash + [0x3001] = { 0, 1 }, -- ideographic comma 、 + [0x3002] = { 0, 1 }, -- ideographic full stop 。 + [0x060C] = { 0, 1 }, -- arabic comma ، + [0x061B] = { 0, 1 }, -- arabic semicolon ؛ + [0x06D4] = { 0, 1 }, -- arabic full stop ۔ + +} + +vectors['punctuation'] = { + + [0x003F] = { 0, 0.20 }, -- ? + [0x00BF] = { 0.20, 0 }, -- ¿ + [0x0021] = { 0, 0.20 }, -- ! + [0x00A1] = { 0.20, 0, }, -- ¡ + [0x0028] = { 0.05, 0 }, -- ( + [0x0029] = { 0, 0.05 }, -- ) + [0x005B] = { 0.05, 0 }, -- [ + [0x005D] = { 0, 0.05 }, -- ] + [0x002C] = { 0, 0.70 }, -- comma + [0x002E] = { 0, 0.70 }, -- period + [0x003A] = { 0, 0.50 }, -- colon + [0x003B] = { 0, 0.50 }, -- semicolon + [0x002D] = { 0, 0.70 }, -- hyphen + [0x00AD] = { 0, 0.70 }, -- also hyphen + [0x2013] = { 0, 0.30 }, -- endash + [0x2014] = { 0, 0.20 }, -- emdash + [0x060C] = { 0, 0.70 }, -- arabic comma + [0x061B] = { 0, 0.50 }, -- arabic semicolon + [0x06D4] = { 0, 0.70 }, -- arabic full stop + [0x061F] = { 0, 0.20 }, -- ؟ + + -- todo: left and right quotes: .5 double, .7 single + + [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹ + [0x203A] = { 0.70, 0.70 }, -- right single guillemet › + [0x00AB] = { 0.50, 0.50 }, -- left guillemet « + [0x00BB] = { 0.50, 0.50 }, -- right guillemet » + + [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘ + [0x2019] = { 0, 0.70 }, -- right single quotation mark ’ + [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark , + [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛ + [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “ + [0x201D] = { 0, 0.50 }, -- right double quotation mark ” + [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „ + [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟ + +} + +vectors['alpha'] = { + + [byte("A")] = { .05, .05 }, + [byte("F")] = { 0, .05 }, + [byte("J")] = { .05, 0 }, + [byte("K")] = { 0, .05 }, + [byte("L")] = { 0, .05 }, + [byte("T")] = { .05, .05 }, + [byte("V")] = { .05, .05 }, + [byte("W")] = { .05, .05 }, + [byte("X")] = { .05, .05 }, + [byte("Y")] = { .05, .05 }, + + [byte("k")] = { 0, .05 }, + [byte("r")] = { 0, .05 }, + [byte("t")] = { 0, .05 }, + [byte("v")] = { .05, .05 }, + [byte("w")] = { .05, .05 }, + [byte("x")] = { .05, .05 }, + [byte("y")] = { .05, .05 }, + +} + +vectors['quality'] = table.merged( + vectors['punctuation'], + vectors['alpha'] +) + +-- As this is experimental code, users should not depend on it. The implications are still +-- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the +-- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The +-- double trick should not be needed it proper hanging punctuation is used in which case +-- values < 1 can be used. +-- +-- preferred (in context, usine vectors): +-- +-- \definefontfeature[whatever][default][mode=node,protrusion=quality] +-- +-- using lfbd and rtbd, with possibibility to enable only one side : +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn] +-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn] +-- +-- idem, using multiplier +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn] +-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn] +-- +-- idem, using named feature file (less frozen): +-- +-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea] + +classes['double'] = { -- for testing opbd + factor = 2, left = 1, right = 1, +} + +local function map_opbd_onto_protrusion(tfmdata,value,opbd) + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local properties = tfmdata.properties + local parameters = tfmdata.parameters + local resources = tfmdata.resources + local rawdata = tfmdata.shared.rawdata + local lookuphash = rawdata.lookuphash + local lookuptags = resources.lookuptags + local script = properties.script + local language = properties.language + local units = parameters.units + local done, factor, left, right = false, 1, 1, 1 + local class = classes[value] + if class then + factor = class.factor or 1 + left = class.left or 1 + right = class.right or 1 + else + factor = tonumber(value) or 1 + end + local lfactor = left * factor + local rfactor = right * factor + if trace_protrusion then + report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor) + end + tfmdata.parameters.protrusion = { + factor = factor, + left = left, + right = right, + } + if opbd ~= "right" then + local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language) + if validlookups then + for i=1,#lookuplist do + local lookup = lookuplist[i] + local steps = lookup.steps + if steps then + if trace_protrusion then + report_protrusions("setting left using lfbd") + end + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + if coverage then + for k, v in next, coverage do + if v == true then + -- zero + else + local w = descriptions[k].width + local d = - v[1] + if w == 0 or d == 0 then + -- ignored + else + local p = lfactor * d/units + characters[k].left_protruding = p + if trace_protrusion then + report_protrusions("lfbd -> %0.3F %C",p,k) + end + end + end + end + end + end + done = true + end + end + end + end + if opbd ~= "left" then + local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language) + if validlookups then + for i=1,#lookuplist do + local lookup = lookuplist[i] + local steps = lookup.steps + if steps then + if trace_protrusion then + report_protrusions("setting right using rtbd") + end + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + if coverage then + for k, v in next, coverage do + if v == true then + -- zero + else + local w = descriptions[k].width + local d = - v[3] + if w == 0 or d == 0 then + -- ignored + else + local p = rfactor * d/units + characters[k].right_protruding = p + if trace_protrusion then + report_protrusions("rtbd -> %0.3F %C",p,k) + end + end + end + end + end + end + end + done = true + end + end + end +end + +-- The opbd test is just there because it was discussed on the context development list. However, +-- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported +-- till we have a proper test font. + +local function initialize(tfmdata,value) + if value then + local opbd = tfmdata.shared.features.opbd + if opbd then + -- possible values: left right both yes no (experimental) + map_opbd_onto_protrusion(tfmdata,value,opbd) + else + local class, vector = get_class_and_vector(tfmdata,value,"protrusions") + if class then + if vector then + local factor = class.factor or 1 + local left = class.left or 1 + local right = class.right or 1 + if trace_protrusion then + report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a", + value,class.vector,factor,left,right) + end + local data = characters.data + local emwidth = tfmdata.parameters.quad + local lfactor = left * factor + local rfactor = right * factor + if trace_protrusion then + report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor) + end + tfmdata.parameters.protrusion = { + factor = factor, + left = left, + right = right, + } + for i, chr in next, tfmdata.characters do + local v = vector[i] + local pl = nil + local pr = nil + if v then + pl = v[1] + pr = v[2] + else + local d = data[i] + if d then + local s = d.shcode + if not s then + -- sorry + elseif type(s) == "table" then + local vl = vector[s[1]] + local vr = vector[s[#s]] + if vl then pl = vl[1] end + if vr then pr = vr[2] end + else + v = vector[s] + if v then + pl = v[1] + pr = v[2] + end + end + end + end + if pl and pl ~= 0 then + local p = pl * lfactor + chr.left_protruding = p + if trace_protrusion then + report_protrusions("left -> %0.3F %C ",p,i) + end + end + if pr and pr ~= 0 then + local p = pr * rfactor + chr.right_protruding = p + if trace_protrusion then + report_protrusions("right -> %0.3F %C",p,i) + end + end + end + elseif trace_protrusion then + report_protrusions("unknown vector %a in class %a",class.vector,value) + end + elseif trace_protrusion then + report_protrusions("unknown class %a",value) + end + end + end +end + +local specification = { + name = "protrusion", + description = "l/r margin character protrusion", + initializers = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end) + +if context then + + implement { + name = "setupfontprotrusion", + arguments = "2 strings", + actions = function(class,settings) getparameters(classes,class,'preset',settings) end + } + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-reorder.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-reorder.lua new file mode 100644 index 00000000000..b2dec781c7d --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-reorder.lua @@ -0,0 +1,174 @@ +if not modules then modules = { } end modules ['font-imp-reorder'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next = next +local find = string.find +local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort + +local fonts = fonts +local otf = fonts.handlers.otf +local registerotffeature = otf.features.register + +-- This is a rather special test-only feature that I added for the sake of testing +-- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a +-- font, in spite of what the description of handling arabic suggests. And indeed, +-- mixed-in lookups of other features (like all these ss* in husayni) are handled +-- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort +-- according to the "assumed" order so e.g. the ss* move to after the standard +-- features. The observed difference in rendering is an indication that uniscribe is +-- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some +-- interference, apart from some hard coded init etc expectations). Anyway, it means +-- that we're okay with the (generic) node processor. A pitfall is that in context +-- we can actually control more, so we can trigger an analyze pass with e.g. +-- dflt/dflt while the libraries depend on the script settings for that. Uniscribe +-- probably also parses the string and when seeing arabic will follow a different +-- code path, although it seems to treat all features equal. + +local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end) +local report_reorder = logs.reporter("fonts","reorder") + +local vectors = { } + +vectors.arab = { + gsub = { + ccmp = 1, + isol = 2, + fina = 3, + medi = 4, + init = 5, + rlig = 6, + rclt = 7, + calt = 8, + liga = 9, + dlig = 10, + cswh = 11, + mset = 12, + }, + gpos = { + curs = 1, + kern = 2, + mark = 3, + mkmk = 4, + }, +} + +local function compare(a,b) + local what_a = a.what + local what_b = b.what + if what_a ~= what_b then + return a.index < b.index + end + local when_a = a.when + local when_b = b.when + if when_a == when_b then + return a.index < b.index + else + return when_a < when_b + end +end + +function otf.reorderlookups(tfmdata,vector) + local order = vectors[vector] + if not order then + return + end + local oldsequences = tfmdata.resources.sequences + if oldsequences then + local sequences = { } + for i=1,#oldsequences do + sequences[i] = oldsequences[i] + end + for i=1,#sequences do + local s = sequences[i] + local features = s.features + local kind = s.type + local index = s.index + if features then + local when + local what + for feature in sortedhash(features) do + if not what then + what = find(kind,"^gsub") and "gsub" or "gpos" + end + local newwhen = order[what][feature] + if not newwhen then + -- skip + elseif not when then + when = newwhen + elseif newwhen < when then + when = newwhen + end + end + s.ondex = s.index + s.index = i + s.what = what == "gsub" and 1 or 2 + s.when = when or 99 + else + s.ondex = s.index + s.index = i + s.what = 1 + s.when = 99 + end + end + sort(sequences,compare) + local swapped = 0 + for i=1,#sequences do + local sequence = sequences[i] + local features = sequence.features + if features then + local index = sequence.index + if index ~= i then + swapped = swapped + 1 + end + if trace_reorder then + if swapped == 1 then + report_reorder() + report_reorder("start swapping lookups in font %!font:name!",tfmdata) + report_reorder() + report_reorder("gsub order: % t",table.swapped(order.gsub)) + report_reorder("gpos order: % t",table.swapped(order.gpos)) + report_reorder() + end + report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t", + i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99, + (index > i and "-") or (index < i and "+") or "=",sortedkeys(features)) + end + end + sequence.what = nil + sequence.when = nil + sequence.index = sequence.ondex + end + if swapped > 0 then + if trace_reorder then + report_reorder() + report_reorder("stop swapping lookups, %i lookups swapped",swapped) + report_reorder() + end + tfmdata.shared.reorderedsequences = sequences + end + end +end + +-- maybe delay till ra is filled + +local function initialize(tfmdata,key,value) + if value then + otf.reorderlookups(tfmdata,value) + end +end + +registerotffeature { + name = "reorderlookups", + description = "reorder lookups", + manipulators = { + base = initialize, + node = initialize, + } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-tex.lua new file mode 100644 index 00000000000..b4b9a7b6943 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-tex.lua @@ -0,0 +1,144 @@ +if not modules then modules = { } end modules ['font-imp-tex'] = { + version = 1.001, + 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 next = next + +local fonts = fonts +local otf = fonts.handlers.otf +local registerotffeature = otf.features.register +local addotffeature = otf.addfeature + +-- tlig (we need numbers for some fonts so ...) + +local specification = { + type = "ligature", + order = { "tlig" }, + prepend = true, + data = { + -- endash = "hyphen hyphen", + -- emdash = "hyphen hyphen hyphen", + [0x2013] = { 0x002D, 0x002D }, + [0x2014] = { 0x002D, 0x002D, 0x002D }, + -- quotedblleft = "quoteleft quoteleft", + -- quotedblright = "quoteright quoteright", + -- quotedblleft = "grave grave", + -- quotedblright = "quotesingle quotesingle", + -- quotedblbase = "comma comma", + }, +} + +addotffeature("tlig",specification) + +registerotffeature { + -- this makes it a known feature (in tables) + name = "tlig", + description = "tex ligatures", +} + +-- trep + +local specification = { + type = "substitution", + order = { "trep" }, + prepend = true, + data = { + -- [0x0022] = 0x201D, + [0x0027] = 0x2019, + -- [0x0060] = 0x2018, + }, +} + +addotffeature("trep",specification) + +registerotffeature { + -- this makes it a known feature (in tables) + name = "trep", + description = "tex replacements", +} + +-- some day this will be moved to font-imp-scripts.lua + +-- anum + +local anum_arabic = { + [0x0030] = 0x0660, + [0x0031] = 0x0661, + [0x0032] = 0x0662, + [0x0033] = 0x0663, + [0x0034] = 0x0664, + [0x0035] = 0x0665, + [0x0036] = 0x0666, + [0x0037] = 0x0667, + [0x0038] = 0x0668, + [0x0039] = 0x0669, +} + +local anum_persian = { + [0x0030] = 0x06F0, + [0x0031] = 0x06F1, + [0x0032] = 0x06F2, + [0x0033] = 0x06F3, + [0x0034] = 0x06F4, + [0x0035] = 0x06F5, + [0x0036] = 0x06F6, + [0x0037] = 0x06F7, + [0x0038] = 0x06F8, + [0x0039] = 0x06F9, +} + +local function valid(data) + local features = data.resources.features + if features then + for k, v in next, features do + for k, v in next, v do + if v.arab then + return true + end + end + end + end +end + +local specification = { + { + type = "substitution", + features = { arab = { urd = true, dflt = true } }, + order = { "anum" }, + data = anum_arabic, + valid = valid, + }, + { + type = "substitution", + features = { arab = { urd = true } }, + order = { "anum" }, + data = anum_persian, + valid = valid, + }, +} + +addotffeature("anum",specification) + +registerotffeature { + -- this makes it a known feature (in tables) + name = "anum", + description = "arabic digits", +} + +-- -- example: +-- +-- fonts.handlers.otf.addfeature { +-- name = "hangulfix", +-- type = "substitution", +-- features = { ["hang"] = { ["*"] = true } }, +-- data = { +-- [0x1160] = 0x119E, +-- }, +-- order = { "hangulfix" }, +-- flags = { }, +-- prepend = true, +-- }) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-tracing.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-tracing.lua new file mode 100644 index 00000000000..6ce44514372 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-tracing.lua @@ -0,0 +1,281 @@ +if not modules then modules = { } end modules ['font-imp-tracing'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next, type = next, type +local concat = table.concat +local formatters = string.formatters + +local fonts = fonts + +local handlers = fonts.handlers +local registerotffeature = handlers.otf.features.register +local registerafmfeature = handlers.afm.features.register + +local settings_to_array = utilities.parsers.settings_to_array +local setmetatableindex = table.setmetatableindex + +local helpers = fonts.helpers +local appendcommandtable = helpers.appendcommandtable +local prependcommands = helpers.prependcommands +local charcommand = helpers.commands.char + +local variables = interfaces.variables + +local v_background = variables.background +local v_frame = variables.frame +local v_empty = variables.empty +local v_none = variables.none + +-- for zhichu chen (see mailing list archive): we might add a few more variants +-- in due time +-- +-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue +-- +-- maybe: +-- +-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression +-- +-- local gray = { "pdf", "origin", "/Tr1 gs .75 g" } +-- local black = { "pdf", "origin", "/Tr0 gs 0 g" } + +-- boundingbox={yes|background|frame|empty|} + +local bp = number.dimenfactors.bp +local r = 16384 * bp -- 65536 // 4 +local f_1 = formatters["%.6F w 0 %.6F %.6F %.6F re f"] +local f_2 = formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"] + +-- change this into w h d instead of h d w + +local backcache = setmetatableindex(function(t,h) + local h = h * bp + local v = setmetatableindex(function(t,d) + local d = d * bp + local v = setmetatableindex(function(t,w) + local v = { "pdf", "origin", f_1(r,-d,w*bp,h+d) } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) + +local forecache = setmetatableindex(function(t,h) + local h = h * bp + local v = setmetatableindex(function(t,d) + local d = d * bp + local v = setmetatableindex(function(t,w) + -- the frame goes through the boundingbox + local v = { "pdf", "origin", f_2(r,r/2,-d+r/2,w*bp-r,h+d-r) } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v +end) + +local startcolor = nil +local stopcolor = nil + +local function initialize(tfmdata,key,value) + if value then + if not backcolors then + local vfspecials = backends.pdf.tables.vfspecials + startcolor = vfspecials.startcolor + stopcolor = vfspecials.stopcolor + end + local characters = tfmdata.characters + local rulecache = backcache + local showchar = true + local color = "palegray" + if type(value) == "string" then + value = settings_to_array(value) + for i=1,#value do + local v = value[i] + if v == v_frame then + rulecache = forecache + elseif v == v_background then + rulecache = backcache + elseif v == v_empty then + showchar = false + elseif v == v_none then + color = nil + else + color = v + end + end + end + local gray = color and startcolor(color) or nil + local black = gray and stopcolor or nil + for unicode, character in next, characters do + local width = character.width or 0 + local height = character.height or 0 + local depth = character.depth or 0 + local rule = rulecache[height][depth][width] + if showchar then + local commands = character.commands + if commands then + if gray then + character.commands = prependcommands ( + commands, gray, rule, black + ) + else + character.commands = prependcommands ( + commands, rule + ) + end + else + local char = charcommand[unicode] + if gray then + character.commands = { + gray, rule, black, char + } + else + character.commands = { + rule, char + } + end + end + else + if gray then + character.commands = { + gray, rule, black + } + else + character.commands = { + rule + } + end + end + end + end +end + +local specification = { + name = "boundingbox", + description = "show boundingbox", + manipulators = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) + +local f_m = formatters["%F %F m"] +local f_l = formatters["%F %F l"] +local f_b = formatters["[] 0 d 0 J %.6F w"] +local f_e = formatters["s"] + +local function ladder(list,docolor,nocolor,lst,offset,sign,default) + local l = lst[1] + local x1 = bp * (offset + l.kern) * sign + local y1 = bp * l.height + local t = { f_b(r,r/2), f_m(x1,y1) } + local n = 2 + local m = #lst + if default > 0 then + default = default * bp + r + else + default = default * bp - r + end + if m == 1 then + n = n + 1 t[n] = f_l(x1,default) + else + for i=1,m do + local l = lst[i] + local x2 = bp * (offset + l.kern) * sign + local y2 = bp * l.height + if i > 1 and y2 == 0 then + y2 = default + end + n = n + 1 t[n] = f_l(x2,y1) + n = n + 1 t[n] = f_l(x2,y2) + x1, y1 = x2, y2 + end + end + n = n + 1 t[n] = f_e() + list[#list+1] = docolor + list[#list+1] = { "pdf", "origin", concat(t," ") } + list[#list+1] = nocolor +end + +local function initialize(tfmdata,key,value) + if value then + if not backcolors then + local vfspecials = backends.pdf.tables.vfspecials + startcolor = vfspecials.startcolor + stopcolor = vfspecials.stopcolor + end + local characters = tfmdata.characters + local brcolor = startcolor("darkred") + local trcolor = startcolor("darkgreen") + local blcolor = startcolor("darkblue") + local tlcolor = startcolor("darkyellow") + local black = stopcolor + for unicode, character in next, characters do + local mathkern = character.mathkern + if mathkern then + -- more efficient would be co collect more in one pdf + -- directive but this is hardly used so not worth the + -- effort + local width = character.width or 0 + local height = character.height or 0 + local depth = character.depth or 0 + local list = { } + local br = mathkern.bottom_right + local tr = mathkern.top_right + local bl = mathkern.bottom_left + local tl = mathkern.top_left + if br then + ladder(list,brcolor,black,br,width,1,height) + end + if tr then + ladder(list,trcolor,black,tr,width,1,-depth) + end + if bl then + ladder(list,blcolor,black,bl,0,-1,height) + end + if tl then + ladder(list,tlcolor,black,tl,0,-1,-depth) + end + if #list > 0 then + local commands = character.commands + if commands then + character.commands = appendcommandtable(commands,list) + else + list[#list+1] = charcommand[unicode] + character.commands = list + end + end + end + end + end +end + +local specification = { + name = "staircase", + description = "show staircase kerns", + position=1, + manipulators = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-imp-unicode.lua b/Master/texmf-dist/tex/context/base/mkiv/font-imp-unicode.lua new file mode 100644 index 00000000000..ddb965ec977 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-imp-unicode.lua @@ -0,0 +1,82 @@ +if not modules then modules = { } end modules ['font-imp-unicode'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local next = next + +local fonts = fonts +local helpers = fonts.helpers +local constructors = fonts.constructors +local registerotffeature = fonts.handlers.otf.features.register + +local extraprivates = helpers.extraprivates +local addprivate = helpers.addprivate + +local function initialize(tfmdata) + for i=1,#extraprivates do + local e = extraprivates[i] + local c = e[2](tfmdata) + if c then + addprivate(tfmdata, e[1], c) + end + end +end + +constructors.newfeatures.otf.register { + name = "extraprivates", + description = "extra privates", + default = true, + manipulators = { + base = initialize, + node = initialize, + } +} + +local tounicode = fonts.mappings.tounicode + +local function initialize(tfmdata,key,value) + if value == "ligatures" then + local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 + local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata) + if collected and next(collected)then + for unicode, char in next, tfmdata.characters do + local u = collected[unicode] + if u then + local n = #u + for i=1,n do + if u[i] > private then + n = 0 + break + end + end + if n > 0 then + if n == 1 then + u = u[1] + end + char.unicode = u + char.tounicode = tounicode(u) + end + end + end + end + end +end + +-- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji) +-- +-- kind of like: \enabletrackers[fonts.mapping.forceligatures] + +registerotffeature { + name = "forceunicodes", + description = "forceunicodes", + manipulators = { + base = initialize, + node = initialize, + } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua index 3d5dd27a2d5..462e30bf909 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ini.lua @@ -10,22 +10,45 @@ if not modules then modules = { } end modules ['font-ini'] = {

Not much is happening here.

--ldx]]-- -local allocate = utilities.storage.allocate +local allocate = utilities.storage.allocate +local sortedhash = table.sortedhash -fonts = fonts or { } -local fonts = fonts +fonts = fonts or { } +local fonts = fonts -fonts.hashes = fonts.hashes or { identifiers = allocate() } -fonts.tables = fonts.tables or { } -fonts.helpers = fonts.helpers or { } -fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata -fonts.specifiers = fonts.specifiers or { } -- in format ! +local identifiers = allocate() -fonts.analyzers = { } -- not needed here -fonts.readers = { } -fonts.definers = { methods = { } } -fonts.loggers = { register = function() end } +fonts.hashes = fonts.hashes or { identifiers = identifiers } +fonts.tables = fonts.tables or { } +fonts.helpers = fonts.helpers or { } +fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata +fonts.specifiers = fonts.specifiers or { } -- in format ! + +fonts.analyzers = { } -- not needed here +fonts.readers = { } +fonts.definers = { methods = { } } +fonts.loggers = { register = function() end } if context then + + font.originaleach = font.each + + function font.each() + return sortedhash(identifiers) + end + fontloader = nil + end + +-- Outside context one can bump textbase to some higher value but only the +-- textbase given here is officially supported (read: bug testing etc will +-- use the values below). + +fonts.privateoffsets = { + textbase = 0xF0000, -- used for hidden (opentype features) + textextrabase = 0xFD000, -- used for visible by name + mathextrabase = 0xFE000, -- used for visible by code + mathbase = 0xFF000, -- used for hidden (virtual math) + keepnames = false, -- when set to true names are always kept (not for context) +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi index 69318291929..dd8a5f14834 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ini.mkvi @@ -341,12 +341,16 @@ \the\everybodyfont \settrue\c_font_synchronize} +\let\savedfont\empty + +\installmacrostack\savedfont + \unexpanded\def\savefont {\edef\savedfont{\the\font}% gives \csname - \pushmacro\savedfont} + \push_macro_savedfont} \unexpanded\def\restorefont - {\popmacro\savedfont + {\pop_macro_savedfont \savedfont} \unexpanded\def\pushcurrentfont @@ -424,7 +428,7 @@ % % \def\normalizebodyfontsize_indeed#macro#body% % {\edef#macro{\ctxcommand{nbfs(\number\dimexpr#body,\number\fontdigits)}}% -% \global\expandafter\let\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro} +% \expandafter\glet\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro} % % \def\thenormalizedbodyfontsize#body% % {\ctxcommand{nbfs(\number\dimexpr#body\relax,\number\fontdigits)}} @@ -439,7 +443,7 @@ \def\normalizebodyfontsize_indeed#macro#body% {\edef#macro{\clf_nbfs\dimexpr#body\relax}% - \global\expandafter\let\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro} + \expandafter\glet\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro} \def\thenormalizedbodyfontsize#body% {\clf_nbfs\dimexpr#body\relax} @@ -583,8 +587,7 @@ \def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ... {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw) \font_helpers_register_style{#style}% - % todo: apptoks - \t_font_style_commands\expandafter{\the\t_font_style_commands\m_font_style_command{#style}}% + \toksapp\t_font_style_commands{\m_font_style_command{#style}}% \fi \processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}} @@ -595,17 +598,14 @@ \unexpanded\def\definefontsize[#size]% {\ifcsname\??fontsizeknown#size\endcsname \else \font_helpers_register_size{#size}% - \t_font_size_commands\expandafter{\the\t_font_size_commands - \m_font_size_command{#size}}% + \toksapp\t_font_size_commands{\m_font_size_command{#size}}% \fi \font_helpers_check_fontname_combinations} \unexpanded\def\definefontalternative[#alternative]% {\ifcsname\??fontalternativeknown#alternative\endcsname \else \font_helpers_register_alternative{#alternative}% - % todo: apptoks - \t_font_alternative_commands\expandafter{\the\t_font_alternative_commands - \m_font_alternative_command{#alternative}}% + \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}% \fi \font_helpers_check_fontname_combinations} @@ -775,7 +775,7 @@ \unexpanded\def\font_helpers_low_level_define#specification#csname% {% we can now set more at the lua end - \global\let\somefontname\defaultfontfile + \glet\somefontname\defaultfontfile \let\somefontsize\empty \clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen % sets \scaledfontmode and \somefontname and \somefontsize @@ -912,7 +912,7 @@ %D The following macros are used at the \LUA\ end. Watch the \type {\normal} %D hackery: this makes the mkvi parser happy. -% \normaldef\fntsetdefname {\global\let\somefontname\defaultfontfile} % do before calling +% \normaldef\fntsetdefname {\glet\somefontname\defaultfontfile} % do before calling % \normaldef\fntsetnopsize {\let\somefontsize\empty} % do before calling % \normaldef\fntsetsomename{\normalgdef\somefontname} % takes argument % \normaldef\fntsetsomesize{\normaldef\somefontsize} % takes argument @@ -1038,7 +1038,7 @@ {\begingroup \font_basics_define_font[#name][#specification][#settings]% \csname#name\endcsname - \global\let\lastglobalrawfontcall\lastrawfontcall + \glet\lastglobalrawfontcall\lastrawfontcall \endgroup \expandafter\let\csname#name\endcsname\lastglobalrawfontcall} @@ -1377,16 +1377,16 @@ %D settings (just to be sure, as it's not really needed). \def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]% - {\pushmacro\fontclass + {\push_macro_fontclass \let\fontclass\empty \font_basics_define_body_font_environment_class[][#body][#settings]% - \popmacro\fontclass} + \pop_macro_fontclass} \def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]% - {\pushmacro\fontclass + {\push_macro_fontclass \let\fontclass\empty \font_basics_define_body_font_environment_class[][#body][]% - \popmacro\fontclass} + \pop_macro_fontclass} %D We don't check too soon as we can refer to later definitions. @@ -1397,13 +1397,13 @@ \ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname % environment and size already defined \else\ifproductionrun - \pushmacro\fontclass + \push_macro_fontclass \edef\fontclass{#class}% \font_helpers_register_environment{#class}{#normalizedbody}% \settrue\c_font_defining_environment_state \font_helpers_define_unknown_font{#normalizedbody}% current class \setfalse\c_font_defining_environment_state - \popmacro\fontclass + \pop_macro_fontclass \fi\fi \font_helpers_register_fontbody{#normalizedbody}} @@ -1527,12 +1527,12 @@ \fi} \def\font_basics_define_body_font_class_given[#1][#2][#3]#4% - {\pushmacro\fontclass + {\push_macro_fontclass \doifelse{#4}\s!default {\let\fontclass\empty} {\def\fontclass{#4}}% \definebodyfont[#1][#2][#3]% - \popmacro\fontclass} + \pop_macro_fontclass} \def\font_basics_define_body_font_class_known {\ifthirdargument @@ -1644,13 +1644,13 @@ \unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi - \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined + \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% - \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined + \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% - \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined + \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% } @@ -1673,9 +1673,9 @@ \unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi - \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined - % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined - % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined + \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined + % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined + % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% } @@ -1727,7 +1727,8 @@ \font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}% \ifconditional\c_font_defining_state \ifconditional\c_font_defining_environment_state\else - \showmessage\m!fonts{14}{#body}% main + %\showmessage\m!fonts{14}{#body}% main + \clf_registerunknownbodysize{#body}% \fi \setfalse\c_font_defining_state \font_helpers_register_fontbody{#body}% @@ -1741,13 +1742,6 @@ \fi \fi} -% \def\font_helpers_define_unknown_check_sizes#body#relativesize% -% {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ? -% % how \lastnamedcs here -% \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}% -% \settrue\c_font_defining_state -% \fi} - \def\font_helpers_define_unknown_check_sizes#body#relativesize% {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ? \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}% @@ -2363,7 +2357,7 @@ \noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }% \noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }% }% - \global\expandafter\let\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces} + \expandafter\glet\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces} % \def\currentbodyfontdimension#parameter% % {\the\dimexpr @@ -2505,15 +2499,15 @@ %D \stoptyping % \unexpanded\def\usebodyfont[#1]% -% {\pushmacro\fontclass +% {\push_macro_fontclass % \switchtobodyfont[#1]% -% \popmacro\fontclass +% \pop_macro_fontclass % \ifx\fontclass\empty\else\setupbodyfont\relax\fi} % \unexpanded\def\usebodyfont[#1]% -% {\pushmacro\fontclass +% {\push_macro_fontclass % \font_helpers_set_font\zerocount{#1}% -% \popmacro\fontclass +% \pop_macro_fontclass % \ifx\fontclass\empty \else % \font_basics_setupbodyfont_nop % \fi} @@ -2716,7 +2710,7 @@ \unexpanded\def\font_basics_predefine#1#2% {\font_basics_defined_font_yes[#2]% - \global\expandafter\let\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname} + \expandafter\glet\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname} \unexpanded\def\font_basics_predefined#1% {\font_basics_predefine{\??predefinedfont#1}{#1}} @@ -2763,7 +2757,26 @@ \expandafter\getprivatechar \fi} -% new +%D Some fonts can have color specifiers: +%D +%D \starttyping +%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes] +%D \definefontsynonym[emoji][seguiemj*seguiemj-cl] +%D +%D \definecolor[emoji-red] [r=.4] +%D \definecolor[emoji-gray][s=1,t=.5,a=1] +%D +%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad +%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] % okay +%D +%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r] +%D +%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt] +%D +%D \startTEXpage[offset=10pt] +%D \MyEmojiR\resolvedemoji{triangular ruler} +%D \stopTEXpage +%D \stoptyping \unexpanded\def\definefontcolorpalette {\dodoubleargument\font_define_color_palette} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi index 24ab687817a..3cff8175161 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-lib.mkvi @@ -26,22 +26,27 @@ % the otf font loader: +% helpers + + \registerctxluafile{font-otr}{optimize} % opentype fontloader \registerctxluafile{font-web}{} % opentype fontloader \registerctxluafile{font-cff}{optimize} % quadratic outlines \registerctxluafile{font-ttf}{optimize} % cubic outlines \registerctxluafile{font-dsp}{optimize} % ... for this one \registerctxluafile{font-hsh}{} % hashes used by context -\registerctxluafile{font-nod}{} +\registerctxluafile{font-vfc}{} +\registerctxluafile{font-prv}{} % needs hashes +\registerctxluafile{font-nod}{optimize} \registerctxluafile{font-oti}{} % otf initialization \registerctxluafile{font-ott}{} % otf tables (first) \registerctxluafile{font-otl}{} \registerctxluafile{font-oto}{} -\registerctxluafile{font-otj}{} +\registerctxluafile{font-otj}{optimize} \registerctxluafile{font-oup}{} \registerctxluafile{font-ota}{} -\registerctxluafile{font-ots}{} -\registerctxluafile{font-otd}{} +\registerctxluafile{font-ots}{optimize} +\registerctxluafile{font-otd}{optimize} \registerctxluafile{font-otc}{} \registerctxluafile{font-oth}{} \registerctxluafile{font-osd}{} @@ -55,7 +60,12 @@ % tfm -\registerctxluafile{font-tfm}{} +\doifelsefileexists {font-tpk.lua} { + \registerctxluafile{font-tpk}{optimize} + \registerctxluafile{font-tfm}{} +} { + \registerctxluafile{font-tfm}{} +} % name database @@ -87,7 +97,28 @@ \registerctxluafile{font-def}{} \registerctxluafile{font-ctx}{} % after def as it overloads -\registerctxluafile{font-ext}{} +% extensions, order matters + +\registerctxluafile{font-imp-ligatures}{} +\registerctxluafile{font-imp-tex}{} +\registerctxluafile{font-imp-reorder}{} +\registerctxluafile{font-imp-properties}{} +\registerctxluafile{font-imp-unicode}{} +\registerctxluafile{font-imp-math}{} +\registerctxluafile{font-imp-notused}{} +\registerctxluafile{font-imp-effects}{} +\registerctxluafile{font-imp-quality}{} +\registerctxluafile{font-imp-italics}{} +\registerctxluafile{font-imp-dimensions}{} + +\doifelsefileexists{font-imp-scripts.lua} { + \registerctxluafile{font-imp-scripts}{} +} { + % not yet, lmtx feature +} + +\registerctxluafile{font-imp-tracing}{} % comes last! + \registerctxluafile{font-fbk}{} \registerctxluafile{font-aux}{} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-map.lua b/Master/texmf-dist/tex/context/base/mkiv/font-map.lua index 66cf2db3996..d931b822e55 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-map.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-map.lua @@ -168,44 +168,73 @@ local function tounicode16sequence(unicodes) return concat(t) end -local function tounicode(unicode) - if type(unicode) == "table" then - local t = { } - for l=1,#unicode do - local u = unicode[l] - if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then - t[l] = f_single(u) - else - u = u - 0x10000 - t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00) - end - end - return concat(t) - else - if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then - return f_single(unicode) - else - unicode = unicode - 0x10000 - return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) - end - end -end +-- local function tounicode(unicode) +-- if type(unicode) == "table" then +-- local t = { } +-- for l=1,#unicode do +-- local u = unicode[l] +-- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then +-- t[l] = f_single(u) +-- else +-- u = u - 0x10000 +-- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00) +-- end +-- end +-- return concat(t) +-- else +-- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then +-- return f_single(unicode) +-- else +-- unicode = unicode - 0x10000 +-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) +-- end +-- end +-- end --- no real gain on runs +local unknown = f_single(0xFFFD) --- local hash = table.setmetatableindex(function(t,u) +-- local function tounicode(unicode) +-- if type(unicode) == "table" then +-- local t = { } +-- for l=1,#unicode do +-- t[l] = tounicode(unicode[l]) +-- end +-- return concat(t) +-- elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then +-- return unknown +-- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then +-- return unknown +-- elseif unicode >= 0x100000 and unicode <= 0x10FFFF then +-- return unknown +-- elseif unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then +-- return f_single(unicode) +-- else +-- unicode = unicode - 0x10000 +-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) +-- end +-- end + +-- local hash = table.setmetatableindex(function(t,k) -- local v --- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then --- v = f_single(u) +-- if k >= 0x00E000 and k <= 0x00F8FF then +-- v = unknown +-- elseif k >= 0x0F0000 and k <= 0x0FFFFF then +-- v = unknown +-- elseif k >= 0x100000 and k <= 0x10FFFF then +-- v = unknown +-- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then +-- v = f_single(k) -- else --- u = u - 0x10000 --- v = f_double(rshift(u,10)+0xD800,u%1024+0xDC00) +-- local k = k - 0x10000 +-- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) -- end --- t[u] = v +-- t[k] = v -- return v -- end) -- --- local function tounicode(unicode,name) +-- table.makeweak(hash) +-- +-- local function tounicode(unicode) -- if type(unicode) == "table" then -- local t = { } -- for l=1,#unicode do @@ -217,6 +246,69 @@ end -- end -- end +local hash = { } +local conc = { } + +-- table.makeweak(hash) + +-- table.setmetatableindex(hash,function(t,k) +-- if type(k) == "table" then +-- local n = #k +-- for l=1,n do +-- conc[l] = hash[k[l]] +-- end +-- return concat(conc,"",1,n) +-- end +-- local v +-- if k >= 0x00E000 and k <= 0x00F8FF then +-- v = unknown +-- elseif k >= 0x0F0000 and k <= 0x0FFFFF then +-- v = unknown +-- elseif k >= 0x100000 and k <= 0x10FFFF then +-- v = unknown +-- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then +-- v = f_single(k) +-- else +-- local k = k - 0x10000 +-- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) +-- end +-- t[k] = v +-- return v +-- end) +-- +-- local function tounicode(unicode) +-- return hash[unicode] +-- end + +table.setmetatableindex(hash,function(t,k) + if k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then + v = f_single(k) + else + local k = k - 0x10000 + v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) + end + t[k] = v + return v +end) + +local function tounicode(k) + if type(k) == "table" then + local n = #k + for l=1,n do + conc[l] = hash[k[l]] + end + return concat(conc,"",1,n) + elseif k >= 0x00E000 and k <= 0x00F8FF then + return unknown + elseif k >= 0x0F0000 and k <= 0x0FFFFF then + return unknown + elseif k >= 0x100000 and k <= 0x10FFFF then + return unknown + else + return hash[k] + end +end + local function fromunicode16(str) if #str == 4 then return tonumber(str,16) @@ -431,7 +523,8 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) glyph.unicode = unicode end else - local t, n = { }, 0 + local t = { } + local n = 0 for l=1,nsplit do local base = split[l] local u = unicodes[base] or unicodevector[base] or contextvector[name] @@ -487,12 +580,17 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures) missing[du] = true nofmissing = nofmissing + 1 end + else + -- maybe a message or so end end else local overload = overloads[du] if overload then glyph.unicode = overload.unicode + elseif not glyph.unicode then + missing[du] = true + nofmissing = nofmissing + 1 end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi index 0134f3fe616..64810d3272a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-mat.mkvi @@ -263,12 +263,12 @@ \fi} \def\font_helpers_bidirectional_mathstrategy_nop_changed - {\textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr - \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr - \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr - \textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr + {\textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr \scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr - \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr} + \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr + \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr + \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr + \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr} \appendtoks \ifconditional\c_font_bidirectional_mathstrategy @@ -313,12 +313,12 @@ {\textfont \c_font_fam_mb \textfont \c_font_fam_mr \scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr \scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr - \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl - \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl - \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr - \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr} + \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr + \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl + \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl + \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl} \def\font_helpers_apply_complete_bold_mathstrategy {\ifconditional\c_font_complete_bold_mathstrategy @@ -425,13 +425,16 @@ \ifdefined\mathdefault \else \let\mathdefault\relax \fi +\newconditional\c_math_bold + \unexpanded\def\mr % math regular {\ifmmode \font_helpers_synchronize_math_family_mr \else \font_helpers_set_current_font_alternative\s!mr \fi - \mathdefault} + \mathdefault + \setfalse\c_math_bold} \unexpanded\def\mb % math bold {\ifmmode @@ -439,12 +442,17 @@ \else \font_helpers_set_current_font_alternative\s!mb \fi - \mathdefault} + \mathdefault + \settrue\c_math_bold} \appendtoks \font_helpers_synchronize_math_family % auto bold \to \everymathematics +\appendtoks + \ifconditional\c_math_bold\mb\fi +\to \everymathematics + %D \macros %D {bigmath,nobigmath} %D diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua b/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua index e1f158c83b7..c75b9298454 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-mis.lua @@ -8,20 +8,20 @@ if not modules then modules = { } end modules ['font-mis'] = { fonts = fonts or { } -fonts.helpers = fonts.helpers or { } -local helpers = fonts.helpers +local helpers = fonts.helpers or { } +fonts.helpers = helpers -fonts.handlers = fonts.handlers or { } -local handlers = fonts.handlers +local handlers = fonts.handlers or { } +fonts.handlers = handlers -handlers.otf = handlers.otf or { } -local otf = handlers.otf +local otf = handlers.otf or { } +handlers.otf = otf local readers = otf.readers if readers then - otf.version = otf.version or 3.103 + otf.version = otf.version or 3.107 otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true) function fonts.helpers.getfeatures(name,save) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua b/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua index cde34f2ae22..89583595826 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-mps.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['font-mps'] = { license = "see context related readme files" } +local tostring = tostring local concat = table.concat local formatters = string.formatters @@ -35,6 +36,17 @@ local f_draw = formatters["draw %s;"] local f_boundingbox = formatters["((%.6F,%.6F)--(%.6F,%.6F)--(%.6F,%.6F)--(%.6F,%.6F)--cycle)"] local f_vertical = formatters["((%.6F,%.6F)--(%.6F,%.6F))"] +directives.register("metapost.stripzeros", function() + + f_moveto = formatters["(%.6N,%.6N)"] + f_lineto = formatters["--(%.6N,%.6N)"] + f_curveto = formatters["..controls(%.6N,%.6N)and(%.6N,%.6N)..(%.6N,%.6N)"] + + f_boundingbox = formatters["((%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--cycle)"] + f_vertical = formatters["((%.6N,%.6N)--(%.6N,%.6N))"] + +end) + function metapost.boundingbox(d,factor) local bounds = d.boundingbox local factor = factor or 1 @@ -97,9 +109,12 @@ function metapost.paths(d,xfactor,yfactor) elseif operator =="q" then -- "quadraticto" size = size + 1 -- first is always a moveto - local l_x, l_y = xfactor*sequence[i-2], yfactor*sequence[i-1] - local m_x, m_y = xfactor*sequence[i+1], yfactor*sequence[i+2] - local r_x, r_y = xfactor*sequence[i+3], yfactor*sequence[i+4] + local l_x = xfactor*sequence[i-2] + local l_y = yfactor*sequence[i-1] + local m_x = xfactor*sequence[i+1] + local m_y = yfactor*sequence[i+2] + local r_x = xfactor*sequence[i+3] + local r_y = yfactor*sequence[i+4] path[size] = f_curveto ( l_x + 2/3 * (m_x-l_x), l_y + 2/3 * (m_y-l_y), @@ -137,9 +152,12 @@ function metapost.paths(d,xfactor,yfactor) size = size + 1 -- first is always a moveto local prev = segments[i-1] - local l_x, l_y = xfactor*prev[#prev-2], yfactor*prev[#prev-1] - local m_x, m_y = xfactor*segment[1], yfactor*segment[2] - local r_x, r_y = xfactor*segment[3], yfactor*segment[4] + local l_x = xfactor*prev[#prev-2] + local l_y = yfactor*prev[#prev-1] + local m_x = xfactor*segment[1] + local m_y = yfactor*segment[2] + local r_x = xfactor*segment[3] + local r_y = yfactor*segment[4] path[size] = f_curveto ( l_x + 2/3 * (m_x-l_x), l_y + 2/3 * (m_y-l_y), @@ -196,7 +214,10 @@ function metapost.maxbounds(data,index,factor) local boundingbox = glyph.boundingbox local xmin, ymin, xmax, ymax if not maxbounds then - xmin, ymin, xmax, ymax = 0, 0, 0, 0 + xmin = 0 + ymin = 0 + xmax = 0 + ymax = 0 for i=1,#glyphs do local d = glyphs[i] if d then @@ -240,45 +261,52 @@ end -- right time. It's probably why I like watching https://www.youtube.com/watch?v=c5FqpddnJmc -- so much: precisely (and perfectly) timed too. -local nodecodes = nodes.nodecodes -- no nuts yet - -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local rule_code = nodecodes.rule - -local normal_rule = nodes.rulecodes.normal - -local nuts = nodes.nuts -local getnext = nuts.getnext -local getid = nuts.getid -local getlist = nuts.getlist -local getchar = nuts.getchar -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getfield = nuts.getfield -local getbox = nuts.getbox -local getwhd = nuts.getwhd -local getkern = nuts.getkern -local getshift = nuts.getshift -local getwidth = nuts.getwidth -local getheight = nuts.getheight -local getdepth = nuts.getdepth - -local effective_glue = nuts.effective_glue - -local characters = fonts.hashes.characters -local parameters = fonts.hashes.parameters -local shapes = fonts.hashes.shapes -local topaths = metapost.paths - -local f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6F,%.6F)(%,t);"] -local f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6F,%.6F,%.6F,%.6F);"] -local f_bounds = formatters["checkbounds(%.6F,%.6F,%.6F,%.6F);"] -local s_nothing = "(origin scaled 10)" +local nodecodes = nodes.nodecodes -- no nuts yet +local rulecodes = nodes.rulecodes + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local rule_code = nodecodes.rule + +local normalrule_code = rulecodes.normal + +local nuts = nodes.nuts +local getnext = nuts.getnext +local getid = nuts.getid +local getlist = nuts.getlist +local getsubtype = nuts.getsubtype +local getfield = nuts.getfield +local getbox = nuts.getbox +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getshift = nuts.getshift +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth +local getexpansion = nuts.getexpansion +local isglyph = nuts.isglyph + +local effective_glue = nuts.effective_glue + +local characters = fonts.hashes.characters +local parameters = fonts.hashes.parameters +local shapes = fonts.hashes.shapes +local topaths = metapost.paths + +local f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6F,%.6F,%q)(%,t);"] +local f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6F,%.6F,%.6F,%.6F);"] +local f_bounds = formatters["checkbounds(%.6F,%.6F,%.6F,%.6F);"] +local s_nothing = "(origin scaled 10)" + +directives.register("metapost.stripzeros", function() + f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6N,%.6N,%q)(%,t);"] + f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6N,%.6N,%.6N,%.6N);"] + f_bounds = formatters["checkbounds(%.6N,%.6N,%.6N,%.6N);"] +end) local sc = 10 local fc = number.dimenfactors.bp * sc / 10 @@ -302,13 +330,14 @@ function metapost.output(kind,font,char,advance,shift,ex) local advance = advance or 0 local exfactor = ex or 0 local wfactor = 1 + local detail = kind == "p" and tostring(char) or "" if exfactor ~= 0 then wfactor = (1+(ex/units)/1000) xfactor = xfactor * wfactor end local paths = topaths(glyf,xfactor,yfactor) if paths then - local code = f_code(kind,#paths,advance,shift,paths) + local code = f_code(kind,#paths,advance,shift,detail,paths) return code, character.width * fc * wfactor else return "", 0 @@ -337,9 +366,9 @@ function fonts.metapost.boxtomp(n,kind) horizontal = function(parent,current,xoffset,yoffset) local dx = 0 while current do - local id = getid(current) - if id == glyph_code then - local code, width = metapost.output(kind,getfont(current),getchar(current),xoffset+dx,yoffset,getfield(current,"expansion_factor")) + local char, id = isglyph(current) + if char then + local code, width = metapost.output(kind,id,char,xoffset+dx,yoffset,getexpansion(current)) result[#result+1] = code dx = dx + width elseif id == disc_code then @@ -374,7 +403,7 @@ function fonts.metapost.boxtomp(n,kind) dp = getdepth(parent) end local hd = (ht + dp) * fc - if hd ~= 0 and getsubtype(current) == normal_rule then + if hd ~= 0 and getsubtype(current) == normalrule_code then result[#result+1] = f_rule(kind,xoffset+dx+wd/2,yoffset+hd/2,wd,hd) end dx = dx + wd diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua index 2670a924bbf..a0eb88a252c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-nod.lua @@ -32,6 +32,10 @@ nodes.tasks = tasks local handlers = nodes.handlers or { } nodes.handlers = handlers +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + local injections = nodes.injections or { } nodes.injections = injections @@ -52,23 +56,17 @@ local kern_code = nodecodes.kern local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - local getfield = nuts.getfield local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid local getfont = nuts.getfont local getsubtype = nuts.getsubtype -local getchar = nuts.getchar local getlist = nuts.getlist local getdisc = nuts.getdisc -local getcomponents = nuts.getcomponents local isglyph = nuts.isglyph local getkern = nuts.getkern -local getdir = nuts.getdir +local getdirection = nuts.getdirection local getwidth = nuts.getwidth local setbox = nuts.setbox @@ -78,10 +76,11 @@ local setsubtype = nuts.setsubtype local copy_node_list = nuts.copy_list local hpack_node_list = nuts.hpack local flush_node_list = nuts.flush_list -local traverse_nodes = nuts.traverse ------ traverse_id = nuts.traverse_id local protect_glyphs = nuts.protect_glyphs +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph + local nodepool = nuts.pool local new_glyph = nodepool.glyph @@ -98,11 +97,8 @@ local fontparameters = hashes.parameters local properties = nodes.properties.data --- direct.set_properties_mode(true,false) --- direct.set_properties_mode(true,true) -- default - local function freeze(h,where) - for n in traverse_nodes(tonut(h)) do -- todo: disc but not traced anyway + for n in nextnode, h do -- todo: disc but not traced anyway local p = properties[n] if p then local i = p.injections if i then p.injections = fastcopy(i) end @@ -115,15 +111,15 @@ local function freeze(h,where) end function char_tracers.collect(head,list,tag,n) - head = tonut(head) n = n or 0 - local ok, fn = false, nil + local ok = false + local fn = nil while head do - local c, id = isglyph(head) - if c then - local f = getfont(head) - if f ~= fn then - ok, fn = false, f + local char, id = isglyph(head) + if char then + local font = id + if font ~= fn then + ok, fn = false, font end if not ok then ok = true @@ -132,23 +128,23 @@ function char_tracers.collect(head,list,tag,n) list[n][tag] = { } end local l = list[n][tag] - -- l[#l+1] = { c, f, i } - l[#l+1] = { c, f } + -- l[#l+1] = { char, font, i } + l[#l+1] = { char, font } elseif id == disc_code then -- skip -- local pre, post, replace = getdisc(head) -- if replace then - -- for n in traverse_id(glyph_code,replace) do + -- for n in nextglyph, replace do -- l[#l+1] = { c, f } -- end -- end -- if pre then - -- for n in traverse_id(glyph_code,pre) do + -- for n in nextglyph, pre do -- l[#l+1] = { c, f } -- end -- end -- if post then - -- for n in traverse_id(glyph_code,post) do + -- for n in nextglyph, post do -- l[#l+1] = { c, f } -- end -- end @@ -164,7 +160,8 @@ function char_tracers.equal(ta, tb) return false else for i=1,#ta do - local a, b = ta[i], tb[i] + local a = ta[i] + local b = tb[i] -- if a[1] ~= b[1] or a[2] ~= b[2] or a[3] ~= b[3] then if a[1] ~= b[1] or a[2] ~= b[2] then return false @@ -221,12 +218,12 @@ function char_tracers.start() function handlers.characters(head) local n = #list char_tracers.collect(head,list,'before',n) - local h, d = npc(tonode(head)) -- for the moment tonode + head = npc(head) -- for the moment tonode char_tracers.collect(head,list,'after',n) if #list > n then list[#list+1] = { } end - return h, d + return head end function char_tracers.stop() tracers.list['characters'] = list @@ -297,47 +294,44 @@ end function step_tracers.features() -- we cannot use first_glyph here as it only finds characters with subtype < 256 local f = collection[1] - while f do - if getid(f) == glyph_code then - local tfmdata = fontidentifiers[getfont(f)] - local features = tfmdata.resources.features - local result_1 = { } - local result_2 = { } - local gpos = features and features.gpos or { } - local gsub = features and features.gsub or { } - for feature, value in table.sortedhash(tfmdata.shared.features) do - if feature == "number" or feature == "features" then - value = false - elseif type(value) == "boolean" then - if value then - value = "yes" - else - value = false - end - else - -- use value - end + for n, char, font in nextglyph, f do + local tfmdata = fontidentifiers[font] + local features = tfmdata.resources.features + local result_1 = { } + local result_2 = { } + local gpos = features and features.gpos or { } + local gsub = features and features.gsub or { } + for feature, value in table.sortedhash(tfmdata.shared.features) do + if feature == "number" or feature == "features" then + value = false + elseif type(value) == "boolean" then if value then - if gpos[feature] or gsub[feature] or feature == "language" or feature == "script" then - result_1[#result_1+1] = formatters["%s=%s"](feature,value) - else - result_2[#result_2+1] = formatters["%s=%s"](feature,value) - end + value = "yes" + else + value = false end - end - if #result_1 > 0 then - context("{\\bf[basic:} %, t{\\bf]} ",result_1) else - context("{\\bf[}no basic features{\\bf]} ") + -- use value end - if #result_2 > 0 then - context("{\\bf[extra:} %, t{\\bf]}",result_2) - else - context("{\\bf[}no extra features{\\bf]}") + if value then + if gpos[feature] or gsub[feature] or feature == "language" or feature == "script" then + result_1[#result_1+1] = formatters["%s=%s"](feature,value) + else + result_2[#result_2+1] = formatters["%s=%s"](feature,value) + end end - return end - f = getnext(f) + if #result_1 > 0 then + context("{\\bf[basic:} %, t{\\bf]} ",result_1) + else + context("{\\bf[}no basic features{\\bf]} ") + end + if #result_2 > 0 then + context("{\\bf[extra:} %, t{\\bf]}",result_2) + else + context("{\\bf[}no extra features{\\bf]}") + end + return end end @@ -349,21 +343,15 @@ end function step_tracers.font(command) local c = collection[1] - while c do - local id = getid(c) - if id == glyph_code then - local font = getfont(c) - local name = file.basename(fontproperties[font].filename or "unknown") - local size = fontparameters[font].size or 0 - if command then - context[command](font,name,size) -- size in sp - else - context("[%s: %s @ %p]",font,name,size) - end - return + for n, char, font in nextglyph, c do + local name = file.basename(fontproperties[font].filename or "unknown") + local size = fontparameters[font].size or 0 + if command then + context[command](font,name,size) -- size in sp else - c = getnext(c) + context("[%s: %s @ %p]",font,name,size) end + return end end @@ -376,9 +364,7 @@ local colors = { function step_tracers.codes(i,command,space) local c = collection[i] - local function showchar(c) - local f = getfont(c) - local c = getchar(c) + local function showchar(c,f) if command then local d = fontdescriptions[f] local d = d and d[c] @@ -392,10 +378,10 @@ function step_tracers.codes(i,command,space) if w then context.startcolor(colors[what]) context("%s:",what) - for c in traverse_nodes(w) do - local id = getid(c) + for c, id in nextnode, w do if id == glyph_code then - showchar(c) + local c, f = isglyph(c) + showchar(c,f) else context("[%s]",nodecodes[id]) end @@ -406,11 +392,11 @@ function step_tracers.codes(i,command,space) end while c do - local id = getid(c) - if id == glyph_code then - showchar(c) - elseif id == dir_code or id == localpar_code then - context("[%s]",getdir(c)) + local char, id = isglyph(c) + if char then + showchar(char,id) + elseif id == dir_code or (id == localpar_code and getsubtype(c) == 0) then + context("[%s]",getdirection(c) or "?") elseif id == disc_code then local pre, post, replace = getdisc(c) if pre or post or replace then @@ -453,13 +439,12 @@ end function step_tracers.check(head) if collecting then step_tracers.reset() - local h = tonut(head) - local n = copy_node_list(h) + local n = copy_node_list(head) freeze(n,"check") - injections.keepcounts(n) -- one-time + injections.keepcounts() -- one-time local l = injections.handler(n,"trace") if l then -- hm, can be false - n = tonut(l) + n = l end protect_glyphs(n) collection[1] = n @@ -470,13 +455,12 @@ function step_tracers.register(head) if collecting then local nc = #collection+1 if messages[nc] then - local h = tonut(head) - local n = copy_node_list(h) + local n = copy_node_list(head) freeze(n,"register") - injections.keepcounts(n) -- one-time + injections.keepcounts() -- one-time local l = injections.handler(n,"trace") if l then -- hm, can be false - n = tonut(l) + n = l end protect_glyphs(n) collection[nc] = n @@ -501,14 +485,11 @@ local threshold = 65536 -- 1pt local function toutf(list,result,nofresult,stopcriterium,nostrip) if list then - for n in traverse_nodes(tonut(list)) do - local c, id = isglyph(n) - if c then - local components = getcomponents(n) - if components then - result, nofresult = toutf(components,result,nofresult,false,true) - elseif c > 0 then - local fc = fontcharacters[getfont(n)] + for n, id in nextnode, tonut(list) do + if id == glyph_code then + local c, f = isglyph(n) + if c > 0 then + local fc = fontcharacters[f] if fc then local fcc = fc[c] if fcc then diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua index b17cf991d80..0976cdb21c0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ocl.lua @@ -13,13 +13,20 @@ local round, max = math.round, math.round local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash local setmetatableindex = table.setmetatableindex -local formatters = string.formatters -local tounicode = fonts.mappings.tounicode +local formatters = string.formatters +local tounicode = fonts.mappings.tounicode -local otf = fonts.handlers.otf +local helpers = fonts.helpers -local f_color = formatters["%.3f %.3f %.3f rg"] -local f_gray = formatters["%.3f g"] +local charcommand = helpers.commands.char +local rightcommand = helpers.commands.right +local leftcommand = helpers.commands.left +local downcommand = helpers.commands.down + +local otf = fonts.handlers.otf + +local f_color = formatters["%.3f %.3f %.3f rg"] +local f_gray = formatters["%.3f g"] if context then @@ -56,31 +63,41 @@ end) if context then + -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] -- looks bad + -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] -- looks okay + local colors = attributes.list[attributes.private('color')] or { } local transparencies = attributes.list[attributes.private('transparency')] or { } function otf.registerpalette(name,values) sharedpalettes[name] = values + local color = lpdf.color + local transparency = lpdf.transparency + local register = colors.register for i=1,#values do local v = values[i] - local c = nil - local t = nil - if type(v) == "table" then - c = colors.register(name,"rgb", - max(round((v.r or 0)*255),255)/255, - max(round((v.g or 0)*255),255)/255, - max(round((v.b or 0)*255),255)/255 - ) + if v == "textcolor" then + values[i] = false else - c = colors[v] - t = transparencies[v] - end - if c and t then - values[i] = hash[lpdf.color(1,c) .. " " .. lpdf.transparency(t)] - elseif c then - values[i] = hash[lpdf.color(1,c)] - elseif t then - values[i] = hash[lpdf.color(1,t)] + local c = nil + local t = nil + if type(v) == "table" then + c = register(name,"rgb", + max(round((v.r or 0)*255),255)/255, + max(round((v.g or 0)*255),255)/255, + max(round((v.b or 0)*255),255)/255 + ) + else + c = colors[v] + t = transparencies[v] + end + if c and t then + values[i] = hash[color(1,c) .. " " .. transparency(t)] + elseif c then + values[i] = hash[color(1,c)] + elseif t then + values[i] = hash[color(1,t)] + end end end end @@ -91,11 +108,13 @@ else -- for generic sharedpalettes[name] = values for i=1,#values do local v = values[i] - values[i] = hash[f_color( - max(round((v.r or 0)*255),255)/255, - max(round((v.g or 0)*255),255)/255, - max(round((v.b or 0)*255),255)/255 - )] + if v then + values[i] = hash[f_color( + max(round((v.r or 0)*255),255)/255, + max(round((v.g or 0)*255),255)/255, + max(round((v.b or 0)*255),255)/255 + )] + end end end @@ -127,16 +146,11 @@ local start = { "pdf", "mode", "font" } -- force text mode (so get q Q right) local push = { "pdf", "page", "q" } local pop = { "pdf", "page", "Q" } -if not LUATEXFUNCTIONALITY or LUATEXFUNCTIONALITY < 6472 then - start = { "nop" } - ----- = stop -end - -- -- This one results in color directives inside BT ET but has less q Q pairs. It -- -- only shows the first glyph in acrobat and nothing more. No problem with other -- -- renderers. -- --- local function initializecolr(tfmdata,kind,value) -- hm, always value +-- local function initialize(tfmdata,kind,value) -- hm, always value -- if value then -- local resources = tfmdata.resources -- local palettes = resources.colorpalettes @@ -161,11 +175,6 @@ end -- tfmdata.fonts = { -- { id = 0 } -- } --- local widths = setmetatableindex(function(t,k) --- local v = { "right", -k } --- t[k] = v --- return v --- end) -- -- -- local getactualtext = otf.getactualtext -- local default = colorvalues[#colorvalues] @@ -173,12 +182,6 @@ end -- local actualb = { "pdf", "page", b } -- saves tables -- local actuale = { "pdf", "page", e } -- saves tables -- -- --- local cache = setmetatableindex(function(t,k) --- local v = { "char", k } -- could he a weak shared hash --- t[k] = v --- return v --- end) --- -- -- for unicode, character in next, characters do -- local description = descriptions[unicode] -- if description then @@ -187,7 +190,7 @@ end -- local u = description.unicode or characters[unicode].unicode -- local w = character.width or 0 -- local s = #colorlist --- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same +-- local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same -- local t = { -- start, -- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) } @@ -202,7 +205,7 @@ end -- n = n + 1 t[n] = v -- l = v -- end --- n = n + 1 t[n] = cache[entry.slot] +-- n = n + 1 t[n] = charcommand[entry.slot] -- if s > 1 and i < s and goback then -- n = n + 1 t[n] = goback -- end @@ -221,7 +224,7 @@ end -- -- Here we have no color change in BT .. ET and more q Q pairs but even then acrobat -- -- fails displaying the overlays correctly. Other renderers do it right. -local function initializecolr(tfmdata,kind,value) -- hm, always value +local function initialize(tfmdata,kind,value) if value then local resources = tfmdata.resources local palettes = resources.colorpalettes @@ -232,8 +235,14 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value converted = setmetatableindex(convert) resources.converted = converted end - local colorvalues = sharedpalettes[value] or converted[palettes[tonumber(value) or 1] or palettes[1]] or { } - local classes = #colorvalues + local colorvalues = sharedpalettes[value] + local default = false -- so the text color (bad for icon overloads) + if colorvalues then + default = colorvalues[#colorvalues] + else + colorvalues = converted[palettes[tonumber(value) or 1] or palettes[1]] or { } + end + local classes = #colorvalues if classes == 0 then return end @@ -246,24 +255,12 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value tfmdata.fonts = { { id = 0 } } - local widths = setmetatableindex(function(t,k) - local v = { "right", -k } - t[k] = v - return v - end) -- local getactualtext = otf.getactualtext - local default = colorvalues[#colorvalues] local b, e = getactualtext(tounicode(0xFFFD)) local actualb = { "pdf", "page", b } -- saves tables local actuale = { "pdf", "page", e } -- saves tables -- - local cache = setmetatableindex(function(t,k) - local v = { "char", k } -- could he a weak shared hash - t[k] = v - return v - end) - -- for unicode, character in next, characters do local description = descriptions[unicode] if description then @@ -272,7 +269,7 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value local u = description.unicode or characters[unicode].unicode local w = character.width or 0 local s = #colorlist - local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same + local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same local t = { start, -- really needed not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) } @@ -291,8 +288,14 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value f = true n = n + 1 t[n] = v l = v + else + if f then + n = n + 1 t[n] = pop + end + f = false + l = nil end - n = n + 1 t[n] = cache[entry.slot] + n = n + 1 t[n] = charcommand[entry.slot] if s > 1 and i < s and goback then n = n + 1 t[n] = goback end @@ -314,80 +317,60 @@ fonts.handlers.otf.features.register { name = "colr", description = "color glyphs", manipulators = { - base = initializecolr, - node = initializecolr, + base = initialize, + node = initialize, } } do - -- local f_setstream = formatters[ [[io.savedata("svg-glyph-%05i",%q)]] ] - -- local f_getstream = formatters[ [[svg-glyph-%05i]] ] - - -- function otfsvg.storepdfdata(pdf) - -- nofstreams = nofstreams + 1 - -- storepdfdata = function(pdf) - -- nofstreams = nofstreams + 1 - -- return f_setstream(nofstreams,pdf), f_getstream(nofstreams) - -- end - -- end - local nofstreams = 0 local f_name = formatters[ [[pdf-glyph-%05i]] ] local f_used = context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] local hashed = { } local cache = { } - function otf.storepdfdata(pdf) - local done = hashed[pdf] - if not done then - nofstreams = nofstreams + 1 - local o, n = epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) - cache[n] = o -- we need to keep in mem - done = f_used(n) - hashed[pdf] = done + if epdf then + + local openpdf = epdf.openMemStream + + function otf.storepdfdata(pdf) + local done = hashed[pdf] + if not done then + nofstreams = nofstreams + 1 + local o, n = openpdf(pdf,#pdf,f_name(nofstreams)) + cache[n] = o -- we need to keep in mem + done = f_used(n) + hashed[pdf] = done + end + return done + end + + else + + local openpdf = pdfe.new + ----- prefix = "data:application/pdf," + + function otf.storepdfdata(pdf) + local done = hashed[pdf] + if not done then + nofstreams = nofstreams + 1 + local f = f_name(nofstreams) + local n = openpdf(pdf,#pdf,f) + done = f_used(n) + hashed[pdf] = done + end + return done end - return nil, done, nil - end - -- maybe more efficient but much slower (and we hash already) - -- - -- if context then - -- - -- local storepdfdata = otf.storepdfdata - -- local initialized = false - -- - -- function otf.storepdfdata(pdf) - -- if not initialized then - -- if resolvers.setmemstream then - -- local f_setstream = formatters[ [[resolvers.setmemstream("pdf-glyph-%05i",%q,true)]] ] - -- local f_getstream = formatters[ [[memstream:///pdf-glyph-%05i]] ] - -- local f_nilstream = formatters[ [[resolvers.resetmemstream("pdf-glyph-%05i",true)]] ] - -- storepdfdata = function(pdf) - -- local done = hashed[pdf] - -- local set = nil - -- local reset = nil - -- if not done then - -- nofstreams = nofstreams + 1 - -- set = f_setstream(nofstreams,pdf) - -- done = f_getstream(nofstreams) - -- reset = f_nilstream(nofstreams) - -- hashed[pdf] = done - -- end - -- return set, done, reset - -- end - -- otf.storepdfdata = storepdfdata - -- end - -- initialized = true - -- end - -- return storepdfdata(pdf) - -- end - -- - -- end + end end -local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg +-- I'll probably make a variant for context as we can do it more efficient there than in +-- generic. + +local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg if not tfmdata or not pdfshapes or not kind then return end @@ -400,7 +383,7 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg properties.virtualized = true -- tfmdata.fonts = { - { id = 0 } + { id = 0 } -- not really needed } -- local getactualtext = otf.getactualtext @@ -410,6 +393,12 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg local actualb = { "pdf", "page", b } -- saves tables local actuale = { "pdf", "page", e } -- saves tables -- + local vfimage = lpdf and lpdf.vfimage or function(wd,ht,dp,data,name) + -- needed for generic (if used there at all) + local name = storepdfdata(data) + return { "image", { filename = name, width = wd, height = ht, depth = dp } } + end + -- for unicode, character in sortedhash(characters) do -- sort is nicer for svg local index = character.index if index then @@ -428,31 +417,30 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg dy = 0 end if data then - local setcode, name, nilcode = storepdfdata(data) - if name then - local bt = unicode and getactualtext(unicode) - local wd = character.width or 0 - local ht = character.height or 0 - local dp = character.depth or 0 - character.commands = { - not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, - { "down", dp + dy * hfactor }, - { "right", dx * hfactor }, - -- setcode and { "lua", setcode } or nop, - { "image", { filename = name, width = wd, height = ht, depth = dp } }, - -- nilcode and { "lua", nilcode } or nop, - actuale, - } - character[kind] = true - end + -- We can delay storage by a lua function in commands: but then we need to + -- be able to provide our own mem stream name (so that we can reserve it). + -- Anyway, we will do this different in a future version of context. + local bt = unicode and getactualtext(unicode) + local wd = character.width or 0 + local ht = character.height or 0 + local dp = character.depth or 0 + -- The down and right will change too (we can move that elsewhere). + character.commands = { + not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, + downcommand[dp + dy * hfactor], + rightcommand[dx * hfactor], + vfimage(wd,ht,dp,data,name), + actuale, + } + character[kind] = true end end end end local otfsvg = otf.svg or { } -otf.svg = otfsvg -otf.svgenabled = true +otf.svg = otfsvg +otf.svgenabled = true do @@ -583,27 +571,27 @@ fonts.handlers.otf.features.register { -- This can be done differently e.g. with ffi and gm and we can share code anway. Using -- batchmode in gm is not faster and as it accumulates we would need to flush all --- individual shapes. +-- individual shapes. But ... in context lmtx (and maybe the backport) we will use +-- a different and more efficient method anyway. I'm still wondering if I should +-- keep color code in generic. Maybe it should be optional. -local otfsbix = otf.sbix or { } -otf.sbix = otfsbix -otf.sbixenabled = true +local otfpng = otf.png or { } +otf.png = otfpng +otf.pngenabled = true do - -- for now png but also other bitmap formats - - local report_sbix = logs.reporter("fonts","sbix conversion") + local report_png = logs.reporter("fonts","png conversion") local loaddata = io.loaddata local savedata = io.savedata local remove = os.remove local runner = sandbox and sandbox.registerrunner { - name = "otfsbix", + name = "otfpng", program = "gm", - template = "convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log", - -- reporter = report_sbix, + template = "convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log", + -- reporter = report_png, } if not runner then @@ -611,29 +599,29 @@ do -- poor mans variant for generic: -- runner = function() - return os.execute("gm convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log") + return os.execute("gm convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log") end end -- Alternatively we can create a single pdf file with -adjoin and then pick up pages from -- that file but creating thousands of small files is no fun either. - function otfsbix.topdf(sbixshapes) + function otfpng.topdf(pngshapes) local pdfshapes = { } - local sbixfile = "temp-otf-sbix-shape.sbix" - local pdffile = "temp-otf-sbix-shape.pdf" + local pngfile = "temp-otf-png-shape.png" + local pdffile = "temp-otf-png-shape.pdf" local nofdone = 0 - local indices = sortedkeys(sbixshapes) -- can be sparse + local indices = sortedkeys(pngshapes) -- can be sparse local nofindices = #indices - report_sbix("processing %i sbix containers",nofindices) + report_png("processing %i png containers",nofindices) statistics.starttiming() for i=1,nofindices do local index = indices[i] - local entry = sbixshapes[index] - local data = entry.data + local entry = pngshapes[index] + local data = entry.data -- or placeholder local x = entry.x local y = entry.y - savedata(sbixfile,data) + savedata(pngfile,data) runner() pdfshapes[index] = { x = x ~= 0 and x or nil, @@ -642,43 +630,44 @@ do } nofdone = nofdone + 1 if nofdone % 100 == 0 then - report_sbix("%i shapes processed",nofdone) + report_png("%i shapes processed",nofdone) end end - report_sbix("processing %i pdf results",nofindices) - remove(sbixfile) + report_png("processing %i pdf results",nofindices) + remove(pngfile) remove(pdffile) statistics.stoptiming() if statistics.elapsedseconds then - report_sbix("sbix conversion time %s",statistics.elapsedseconds() or "-") + report_png("png conversion time %s",statistics.elapsedseconds() or "-") end return pdfshapes - -- end end end -local function initializesbix(tfmdata,kind,value) -- hm, always value - if value and otf.sbixenabled then - local sbix = tfmdata.properties.sbix - local hash = sbix and sbix.hash - local timestamp = sbix and sbix.timestamp +-- This will change in a future version of context. More direct. + +local function initializepng(tfmdata,kind,value) -- hm, always value + if value and otf.pngenabled then + local png = tfmdata.properties.png + local hash = png and png.hash + local timestamp = png and png.timestamp if not hash then return end local pdffile = containers.read(otf.pdfcache,hash) local pdfshapes = pdffile and pdffile.pdfshapes if not pdfshapes or pdffile.timestamp ~= timestamp then - local sbixfile = containers.read(otf.sbixcache,hash) - local sbixshapes = sbixfile and sbixfile.sbixshapes - pdfshapes = sbixshapes and otfsbix.topdf(sbixshapes) or { } + local pngfile = containers.read(otf.pngcache,hash) + local pngshapes = pngfile and pngfile.pngshapes + pdfshapes = pngshapes and otfpng.topdf(pngshapes) or { } containers.write(otf.pdfcache, hash, { pdfshapes = pdfshapes, timestamp = timestamp, }) end -- - pdftovirtual(tfmdata,pdfshapes,"sbix") + pdftovirtual(tfmdata,pdfshapes,"png") end end @@ -686,8 +675,16 @@ fonts.handlers.otf.features.register { name = "sbix", description = "sbix glyphs", manipulators = { - base = initializesbix, - node = initializesbix, + base = initializepng, + node = initializepng, } } +fonts.handlers.otf.features.register { + name = "cblc", + description = "cblc glyphs", + manipulators = { + base = initializepng, + node = initializepng, + } +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-one.lua b/Master/texmf-dist/tex/context/base/mkiv/font-one.lua index a3dc7b03859..18ba5118532 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-one.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-one.lua @@ -86,14 +86,16 @@ function afm.load(filename) local name = file.removesuffix(file.basename(filename)) local data = containers.read(afm.cache,name) local attr = lfs.attributes(filename) - local size, time = attr.size or 0, attr.modification or 0 + local size = attr and attr.size or 0 + local time = attr and attr.modification or 0 -- local pfbfile = file.replacesuffix(name,"pfb") local pfbname = resolvers.findfile(pfbfile,"pfb") or "" if pfbname == "" then pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or "" end - local pfbsize, pfbtime = 0, 0 + local pfbsize = 0 + local pfbtime = 0 if pfbname ~= "" then local attr = lfs.attributes(pfbname) pfbsize = attr.size or 0 @@ -106,6 +108,7 @@ function afm.load(filename) afmenhancers.apply(data,filename) -- otfreaders.addunicodetable(data) -- only when not done yet fonts.mappings.addtounicode(data,filename) + otfreaders.stripredundant(data) -- otfreaders.extend(data) otfreaders.pack(data) data.size = size @@ -323,7 +326,8 @@ local addthem = function(rawdata,ligatures) local one = descriptions[unicodes[ligname]] if one then for _, pair in next, ligdata do - local two, three = unicodes[pair[1]], unicodes[pair[2]] + local two = unicodes[pair[1]] + local three = unicodes[pair[2]] if two and three then local ol = one.ligatures if ol then @@ -391,7 +395,7 @@ local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust h if what then for complex, simple in next, what do complex = unicodes[complex] - simple = unicodes[simple] + simple = unicodes[simple] if complex and simple then local complexdescription = descriptions[complex] if complexdescription then -- optional @@ -444,7 +448,8 @@ local function adddimensions(data) -- we need to normalize afm to otf i.e. index for unicode, description in next, data.descriptions do local bb = description.boundingbox if bb then - local ht, dp = bb[4], -bb[2] + local ht = bb[4] + local dp = -bb[2] if ht == 0 or ht < 0 then -- no need to set it and no negative heights, nil == 0 else diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-onr.lua b/Master/texmf-dist/tex/context/base/mkiv/font-onr.lua index 26a782649f4..8523d8729ab 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-onr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-onr.lua @@ -26,7 +26,7 @@ local match, lower, gsub, strip, find = string.match, string.lower, string.gsub, local char, byte, sub = string.char, string.byte, string.sub local abs = math.abs local bxor, rshift = bit32.bxor, bit32.rshift -local P, S, R, Cmt, C, Ct, Cs, Carg, Cf, Cg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg +local P, S, R, V, Cmt, C, Ct, Cs, Carg, Cf, Cg, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.V, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg, lpeg.Cc local lpegmatch, patterns = lpeg.match, lpeg.patterns local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) @@ -83,31 +83,40 @@ do end - local charstrings = P("/CharStrings") - local subroutines = P("/Subrs") - local encoding = P("/Encoding") - local dup = P("dup") - local put = P("put") - local array = P("array") - local name = P("/") * C((R("az","AZ","09")+S("-_."))^1) - local digits = R("09")^1 - local cardinal = digits / tonumber - local spaces = P(" ")^1 - local spacing = patterns.whitespace^0 + local charstrings = P("/CharStrings") + local subroutines = P("/Subrs") + local encoding = P("/Encoding") + local dup = P("dup") + local put = P("put") + local array = P("array") + local name = P("/") * C((R("az","AZ","09")+S("-_."))^1) + local digits = R("09")^1 + local cardinal = digits / tonumber + local spaces = P(" ")^1 + local spacing = patterns.whitespace^0 local routines, vector, chars, n, m local initialize = function(str,position,size) n = 0 - m = size -- % tonumber(size) + m = size return position + 1 end local setroutine = function(str,position,index,size,filename) - local forward = position + tonumber(size) + if routines[index] then + -- we have passed the end + return false + end + local forward = position + size local stream = decrypt(sub(str,position+1,forward),4330,4) routines[index] = { byte(stream,1,#stream) } - return forward + n = n + 1 + if n >= m then + -- m should be index now but can we assume ordering? + return #str + end + return forward + 1 end local setvector = function(str,position,name,size,filename) @@ -152,7 +161,7 @@ do local p_filterroutines = -- dup RD or -| NP or | (1-subroutines)^0 * subroutines * spaces * Cmt(cardinal,initialize) - * (Cmt(cardinal * spaces * cardinal * p_rd * Carg(1), setroutine) * p_np + P(1))^1 + * (Cmt(cardinal * spaces * cardinal * p_rd * Carg(1), setroutine) * p_np + (1-p_nd))^1 local p_filtershapes = -- /foo RD ND (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize) @@ -175,7 +184,33 @@ do -- if one of first 4 not 0-9A-F then binary else hex - local function loadpfbvector(filename,shapestoo) + local key = spacing * P("/") * R("az","AZ") + local str = spacing * Cs { (P("(")/"") * ((1 - P("\\(") - P("\\)") - S("()")) + V(1))^0 * (P(")")/"") } + local num = spacing * (R("09") + S("+-."))^1 / tonumber + local arr = spacing * Ct (S("[{") * (num)^0 * spacing * S("]}")) + local boo = spacing * (P("true") * Cc(true) + P("false") * Cc(false)) + local nam = spacing * P("/") * Cs(R("az","AZ")^1) + + local p_filtermetadata = ( + P("/") * Carg(1) * ( ( + C("version") * str + + C("Copyright") * str + + C("Notice") * str + + C("FullName") * str + + C("FamilyName") * str + + C("Weight") * str + + C("ItalicAngle") * num + + C("isFixedPitch") * boo + + C("UnderlinePosition") * num + + C("UnderlineThickness") * num + + C("FontName") * nam + + C("FontMatrix") * arr + + C("FontBBox") * arr + ) ) / function(t,k,v) t[lower(k)] = v end + + P(1) + )^0 * Carg(1) + + local function loadpfbvector(filename,shapestoo,streams) -- for the moment limited to encoding only local data = io.loaddata(resolvers.findfile(filename)) @@ -200,11 +235,14 @@ do binary = decrypt(binary,55665,4) local names = { } + local encoding = lpegmatch(p_filterencoding,ascii) + local metadata = lpegmatch(p_filtermetadata,ascii,1,{}) local glyphs = { } routines, vector, chars = { }, { }, { } - if shapestoo then + if shapestoo or streams then + -- io.savedata("foo.txt",binary) lpegmatch(p_filterroutines,binary,1,filename) lpegmatch(p_filtershapes,binary,1,filename) local data = { @@ -216,7 +254,8 @@ do } }, } - fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,true) + -- only cff 1 in type 1 fonts + fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,"cff",streams) else lpegmatch(p_filternames,binary,1,filename) end @@ -225,7 +264,7 @@ do routines, vector, chars = nil, nil, nil - return names, encoding, glyphs + return names, encoding, glyphs, metadata end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua b/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua index 9f99fd57f1c..32d791b48e9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-osd.lua @@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag license = "see context related readme files" } + +-- we need to check nbsphash (context only) + -- A few remarks: -- -- This code is a partial rewrite of the code that deals with devanagari. The data @@ -96,8 +99,6 @@ local otffeatures = fonts.constructors.features.otf local registerotffeature = otffeatures.register local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -152,47 +153,27 @@ replace_all_nbsp = function(head) -- delayed definition return replace_all_nbsp(head) end -local xprocesscharacters = nil +local processcharacters = nil if context then - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.characters - return xprocesscharacters(head,font) + local fontprocesses = fonts.hashes.processes + function processcharacters(head,font) + local processors = fontprocesses[font] + for i=1,#processors do + head = processors[i](head,font,0) + end + return head end else - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.nodepass -- generic - return xprocesscharacters(head,font) + function processcharacters(head,font) + local processors = fontdata[font].shared.processes + for i=1,#processors do + head = processors[i](head,font,0) + end + return head end end -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -- can be more efficient in context, just direct call -end - --- to be tested: --- --- local processcharacters = nil --- --- if context then --- local fontprocesses = fonts.hashes.processes --- function processcharacters(head,font) --- local processors = fontprocesses[font] --- for i=1,#processors do --- head = processors[i](head,font,0) --- end --- return head, true --- end --- else --- function processcharacters(head,font) --- local processors = fontdata[font].shared.processes --- for i=1,#processors do --- head = processors[i](head,font,0) --- end --- return head, true --- end --- end - -- We can assume that script are not mixed in the source but if that is the case -- we might need to have consonants etc per script and initialize a local table -- pointing to the right one. But not now. @@ -293,10 +274,6 @@ if not indicgroups and characters then characters.indicgroups = indicgroups -else - - indicgroups = table.setmetatableindex("table") - end local consonant = indicgroups.consonant @@ -422,19 +399,19 @@ local sequence_remove_joiners = { -- as it might depends on the font. Not that it's a bottleneck. local basic_shaping_forms = { - init = true, -- new - abvs = true, -- new + -- init = true, -- new + -- abvs = true, -- new akhn = true, blwf = true, - calt = true, -- new + -- calt = true, -- new cjct = true, half = true, - haln = true, -- new + -- haln = true, -- new nukt = true, pref = true, - pres = true, -- new + -- pres = true, -- new pstf = true, - psts = true, -- new + -- psts = true, -- new rkrf = true, rphf = true, vatu = true, @@ -605,9 +582,7 @@ local function initializedevanagi(tfmdata) end end end -if reph then - seqsubset[#seqsubset+1] = { kind, coverage, reph } -end + seqsubset[#seqsubset+1] = { kind, coverage, reph } end end end @@ -691,6 +666,19 @@ registerotffeature { }, } +local show_syntax_errors = false + +local function inject_syntax_error(head,current,char) + local signal = copy_node(current) + copyinjection(signal,current) + if pre_mark[char] then + setchar(signal,dotted_circle) + else + setchar(current,dotted_circle) + end + return insert_node_after(head,current,signal) +end + -- hm, this is applied to one character: local function initialize_one(font,attr) -- we need a proper hook into the dataset initializer @@ -793,10 +781,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) setprop(tempcurrent,a_state,unsetvalue) if getchar(next) == getchar(tempcurrent) then flush_list(tempcurrent) - local n = copy_node(current) - copyinjection(n,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set - setchar(current,dotted_circle) - head = insert_node_after(head, current, n) + if show_syntax_errors then + head, current = inject_syntax_error(head,current,char) + end else setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node local freenode = getnext(current) @@ -1217,7 +1204,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char = ischar(current,startfont) if char and getprop(current,a_syllabe) == startattr then - if not c and mark_above_below_post[char] and after_subscript[char] then + if not c and mark_above_below_post[char] and not after_subscript[char] then c = current end current = getnext(current) @@ -1560,10 +1547,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas setprop(current,a_state,unsetvalue) if halant[getchar(current)] then setnext(getnext(current),tmp) - local nc = copy_node(current) - copyinjection(nc,current) - setchar(current,dotted_circle) - head = insert_node_after(head,current,nc) + if show_syntax_errors then + head, current = inject_syntax_error(head,current,char) + end else setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node if changestop then @@ -2058,24 +2044,10 @@ local function analyze_next_chars_two(c,font) end end -local show_syntax_errors = false - -local function inject_syntax_error(head,current,char) - local signal = copy_node(current) - copyinjection(signal,current) - if pre_mark[char] then - setchar(signal,dotted_circle) - else - setchar(current,dotted_circle) - end - return insert_node_after(head,current,signal) -end - -- It looks like these two analyzers were written independently but they share -- a lot. Common code has been synced. local function method_one(head,font,attr) - head = tonut(head) local current = head local start = true local done = false @@ -2270,14 +2242,13 @@ local function method_one(head,font,attr) head = replace_all_nbsp(head) end - return tonode(head), done + return head, done end -- there is a good change that when we run into one with subtype < 256 that the rest is also done -- so maybe we can omit this check (it's pretty hard to get glyphs in the stream out of the blue) local function method_two(head,font,attr) - head = tonut(head) local current = head local start = true local done = false @@ -2366,7 +2337,7 @@ local function method_two(head,font,attr) head = replace_all_nbsp(head) end - return tonode(head), done + return head, done end for i=1,nofscripts do diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua index de626c120c5..76c267a8176 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ota.lua @@ -37,12 +37,10 @@ local getprev = nuts.getprev local getprev = nuts.getprev local getprop = nuts.getprop local setprop = nuts.setprop -local getfont = nuts.getfont local getsubtype = nuts.getsubtype local getchar = nuts.getchar local ischar = nuts.is_char -local traverse_id = nuts.traverse_id local end_of_math = nuts.end_of_math local nodecodes = nodes.nodecodes @@ -112,6 +110,8 @@ analyzers.useunicodemarks = false -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace +-- done can go away as can tonut + function analyzers.setstate(head,font) local useunicodemarks = analyzers.useunicodemarks local tfmdata = fontdata[font] @@ -302,9 +302,9 @@ if not classifiers then end function methods.arab(head,font,attr) - local first, last = nil, nil - local c_first, c_last = nil, nil - local current, done = head, false + local first, last, c_first, c_last + local current = head + local done = false current = tonut(current) while current do local char, id = ischar(current,font) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua index 2bad62d60f0..a774a81c2c9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otc.lua @@ -6,11 +6,10 @@ if not modules then modules = { } end modules ['font-otc'] = { license = "see context related readme files" } -local format, insert, sortedkeys, tohash = string.format, table.insert, table.sortedkeys, table.tohash -local type, next = type, next +local insert, sortedkeys, sortedhash, tohash = table.insert, table.sortedkeys, table.sortedhash, table.tohash +local type, next, tonumber = type, next, tonumber local lpegmatch = lpeg.match -local utfbyte, utflen, utfsplit = utf.byte, utf.len, utf.split -local match = string.match +local utfbyte, utflen = utf.byte, utf.len local sortedhash = table.sortedhash -- we assume that the other otf stuff is loaded already @@ -175,6 +174,10 @@ local function addfeature(data,feature,specifications) return end + local p = lpeg.P("P") + * (lpeg.patterns.hexdigit^1/function(s) return tonumber(s,16) end) + * lpeg.P(-1) + local function tounicode(code) if not code then return @@ -184,6 +187,7 @@ local function addfeature(data,feature,specifications) end local u = unicodes[code] if u then + -- unicodes[code] = u return u end if utflen(code) == 1 then @@ -192,10 +196,19 @@ local function addfeature(data,feature,specifications) return u end end + local u = lpegmatch(p,code) + if u then + -- unicodes[code] = u + return u + end if not aglunicodes then aglunicodes = fonts.encodings.agl.unicodes -- delayed end - return aglunicodes[code] + local u = aglunicodes[code] + if u then + -- unicodes[code] = u + return u + end end local coverup = otf.coverup @@ -265,7 +278,8 @@ local function addfeature(data,feature,specifications) if not nocheck and not description then skip = skip + 1 elseif type(replacement) == "table" then - local r, n = { }, 0 + local r = { } + local n = 0 for i=1,#replacement do local u = tounicode(replacement[i]) if nocheck or descriptions[u] then @@ -467,6 +481,8 @@ local function addfeature(data,feature,specifications) if not subtype then subtype = lookup.type end + elseif v == 0 then + lookups[k] = { { type = "gsub_remove" } } else lookups[k] = false -- { false } -- new end @@ -813,177 +829,6 @@ otf.enhancers.enhance = enhance otf.enhancers.register("check extra features",enhance) --- tlig -- - -local tlig = { -- we need numbers for some fonts so ... - -- endash = "hyphen hyphen", - -- emdash = "hyphen hyphen hyphen", - [0x2013] = { 0x002D, 0x002D }, - [0x2014] = { 0x002D, 0x002D, 0x002D }, - -- quotedblleft = "quoteleft quoteleft", - -- quotedblright = "quoteright quoteright", - -- quotedblleft = "grave grave", - -- quotedblright = "quotesingle quotesingle", - -- quotedblbase = "comma comma", -} - -local tlig_specification = { - type = "ligature", - features = everywhere, - data = tlig, - order = { "tlig" }, - flags = noflags, - prepend = true, -} - -otf.addfeature("tlig",tlig_specification) - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'tlig', - description = 'tex ligatures', -} - --- trep - -local trep = { - -- [0x0022] = 0x201D, - [0x0027] = 0x2019, - -- [0x0060] = 0x2018, -} - -local trep_specification = { - type = "substitution", - features = everywhere, - data = trep, - order = { "trep" }, - flags = noflags, - prepend = true, -} - -otf.addfeature("trep",trep_specification) - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'trep', - description = 'tex replacements', -} - --- -- tcom (obsolete, was already not set for a while) - --- if characters.combined then --- --- local tcom = { } --- --- local function initialize() --- characters.initialize() --- for first, seconds in next, characters.combined do --- for second, combination in next, seconds do --- tcom[combination] = { first, second } --- end --- end --- -- return false --- end --- --- local tcom_specification = { --- type = "ligature", --- features = everywhere, --- data = tcom, --- order = { "tcom" }, --- flags = noflags, --- initialize = initialize, --- } --- --- otf.addfeature("tcom",tcom_specification) --- --- registerotffeature { --- name = 'tcom', --- description = 'tex combinations', --- } --- --- end - --- anum - -local anum_arabic = { - [0x0030] = 0x0660, - [0x0031] = 0x0661, - [0x0032] = 0x0662, - [0x0033] = 0x0663, - [0x0034] = 0x0664, - [0x0035] = 0x0665, - [0x0036] = 0x0666, - [0x0037] = 0x0667, - [0x0038] = 0x0668, - [0x0039] = 0x0669, -} - -local anum_persian = { - [0x0030] = 0x06F0, - [0x0031] = 0x06F1, - [0x0032] = 0x06F2, - [0x0033] = 0x06F3, - [0x0034] = 0x06F4, - [0x0035] = 0x06F5, - [0x0036] = 0x06F6, - [0x0037] = 0x06F7, - [0x0038] = 0x06F8, - [0x0039] = 0x06F9, -} - -local function valid(data) - local features = data.resources.features - if features then - for k, v in next, features do - for k, v in next, v do - if v.arab then - return true - end - end - end - end -end - -local anum_specification = { - { - type = "substitution", - features = { arab = { urd = true, dflt = true } }, - order = { "anum" }, - data = anum_arabic, - flags = noflags, -- { }, - valid = valid, - }, - { - type = "substitution", - features = { arab = { urd = true } }, - order = { "anum" }, - data = anum_persian, - flags = noflags, -- { }, - valid = valid, - }, -} - -otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature - -registerotffeature { - -- this makes it a known feature (in tables) - name = 'anum', - description = 'arabic digits', -} - --- maybe: - --- fonts.handlers.otf.addfeature("hangulfix",{ --- type = "substitution", --- features = { ["hang"] = { ["*"] = true } }, --- data = { --- [0x1160] = 0x119E, --- }, --- order = { "hangulfix" }, --- flags = { }, --- prepend = true, --- }) - -- fonts.handlers.otf.features.register { -- name = 'hangulfix', -- description = 'fixes for hangul', @@ -1028,126 +873,3 @@ registerotffeature { -- a = { b = -500 }, -- } -- } - --- This is a quick and dirty hack. - -local lookups = { } -local protect = { } -local revert = { } -local zwjchar = 0x200C -local zwj = { zwjchar } - -otf.addfeature { - name = "blockligatures", - type = "chainsubstitution", - nocheck = true, -- because there is no 0x200C in the font - prepend = true, -- make sure we do it early - future = true, -- avoid nilling due to no steps yet - lookups = { - { - type = "multiple", - data = lookups, - }, - }, - data = { - rules = protect, - } -} - -otf.addfeature { - name = "blockligatures", - type = "chainsubstitution", - nocheck = true, -- because there is no 0x200C in the font - append = true, -- this is done late - overload = false, -- we don't want to overload the previous definition - lookups = { - { - type = "ligature", - data = lookups, - }, - }, - data = { - rules = revert, - } -} - -registerotffeature { - name = 'blockligatures', - description = 'block certain ligatures', -} - -local settings_to_array = utilities.parsers and utilities.parsers.settings_to_array - or function(s) return string.split(s,",") end -- for generic - -local splitter = lpeg.splitat(":") - -local function blockligatures(str) - - local t = settings_to_array(str) - - for i=1,#t do - local ti = t[i] - local before, current, after = lpegmatch(splitter,ti) - if current and after then -- before is returned when no match - -- experimental joke - if before then - before = utfsplit(before) - for i=1,#before do - before[i] = { before[i] } - end - end - if current then - current = utfsplit(current) - end - if after then - after = utfsplit(after) - for i=1,#after do - after[i] = { after[i] } - end - end - else - before = nil - current = utfsplit(ti) - after = nil - end - if #current > 1 then - local one = current[1] - local two = current[2] - lookups[one] = { one, zwjchar } - local one = { one } - local two = { two } - local new = #protect + 1 - protect[new] = { - before = before, - current = { one, two }, - after = after, - lookups = { 1 }, -- not shared ! - } - revert[new] = { - -- before = before, - current = { one, zwj }, - -- after = { two, unpack(after) }, - after = { two }, - lookups = { 1 }, -- not shared ! - } - end - end -end - --- blockligatures("\0\0") - -otf.helpers.blockligatures = blockligatures - --- blockligatures("fi,ff") --- blockligatures("fl") --- blockligatures("u:fl:age") - -if context then - - interfaces.implement { - name = "blockligatures", - arguments = "string", - actions = blockligatures, - } - -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua index 9037939df10..bb30389357c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otj.lua @@ -97,8 +97,11 @@ local setlink = nuts.setlink local setwidth = nuts.setwidth local getwidth = nuts.getwidth -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglue = nuts.traversers.glue + local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after @@ -128,6 +131,10 @@ do if not fontkern then -- generic return n end +end end + +do if not italickern then -- generic + local thekern = nuts.new("kern",3) -- italiccorrection local setkern = nuts.setkern local copy_node = nuts.copy_node @@ -298,10 +305,10 @@ end -- kind: 0=single 1=first of pair, 2=second of pair function injections.setposition(kind,current,factor,rlmode,spec,injection) - local x = factor*spec[1] - local y = factor*spec[2] - local w = factor*spec[3] - local h = factor*spec[4] + local x = factor * (spec[1] or 0) + local y = factor * (spec[2] or 0) + local w = factor * (spec[3] or 0) + local h = factor * (spec[4] or 0) if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay? local yoffset = y - h local leftkern = x -- both kerns are set in a pair kern compared @@ -449,7 +456,8 @@ function injections.setmove(current,factor,rlmode,x,injection) end function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor - local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) + local dx = factor*(ba[1]-ma[1]) + local dy = factor*(ba[2]-ma[2]) nofregisteredmarks = nofregisteredmarks + 1 if rlmode >= 0 then dx = tfmbase.width - dx -- see later commented ox @@ -462,15 +470,18 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmar if i.markmark then -- out of order mkmk: yes or no or option else - if dx ~= 0 then - i.markx = dx - end - if y ~= 0 then - i.marky = dy - end - if rlmode then - i.markdir = rlmode - end + -- if dx ~= 0 then + -- i.markx = dx + -- end + -- if y ~= 0 then + -- i.marky = dy + -- end + -- if rlmode then + -- i.markdir = rlmode + -- end + i.markx = dx + i.marky = dy + i.markdir = rlmode or 0 i.markbase = nofregisteredmarks i.markbasenode = base i.markmark = mkmk @@ -558,7 +569,7 @@ end local function showsub(n,what,where) report_injections("begin subrun: %s",where) - for n in traverse_char(n) do + for n in nextchar, n do showchar(n,where) show(n,what,where," ") end @@ -628,7 +639,6 @@ end -- +D-replace +D-replace local function inject_kerns_only(head,where) - head = tonut(head) if trace_injections then trace(head,"kerns") end @@ -684,7 +694,8 @@ local function inject_kerns_only(head,where) -- glyph|disc|glyph (special case) local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern + replace = fontkern(leftkern) + done = true end end end @@ -704,7 +715,7 @@ local function inject_kerns_only(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -720,7 +731,7 @@ local function inject_kerns_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -736,7 +747,7 @@ local function inject_kerns_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -771,11 +782,10 @@ local function inject_kerns_only(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end local function inject_positions_only(head,where) - head = tonut(head) if trace_injections then trace(head,"positions") end @@ -826,7 +836,9 @@ local function inject_positions_only(head,where) if replace then -- error, we expect an empty one else - setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern +--KE setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern + replace = fontkern(rightkern) -- maybe also leftkern --KE + done = true --KE end end end @@ -859,7 +871,8 @@ local function inject_positions_only(head,where) -- new .. okay? local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern + replace = fontkern(leftkern) + done = true end end end @@ -878,7 +891,7 @@ local function inject_positions_only(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -903,7 +916,7 @@ local function inject_positions_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -928,7 +941,7 @@ local function inject_positions_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -1002,7 +1015,7 @@ local function inject_positions_only(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end local function showoffset(n,flag) @@ -1013,7 +1026,6 @@ local function showoffset(n,flag) end local function inject_everything(head,where) - head = tonut(head) if trace_injections then trace(head,"everything") end @@ -1276,7 +1288,8 @@ local function inject_everything(head,where) if replace then -- error, we expect an empty one else - setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern + replace = fontkern(rightkern) + done = true end end end @@ -1309,7 +1322,8 @@ local function inject_everything(head,where) if i then local leftkern = i.leftkern if leftkern and leftkern ~= 0 then - setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern + replace = fontkern(leftkern) + done = true end end end @@ -1344,7 +1358,7 @@ local function inject_everything(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -1375,7 +1389,7 @@ local function inject_everything(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -1406,7 +1420,7 @@ local function inject_everything(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -1514,7 +1528,7 @@ local function inject_everything(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end -- space triggers @@ -1603,7 +1617,7 @@ end local function injectspaces(head) if not triggers then - return head, false + return head end local lastfont = nil local spacekerns = nil @@ -1613,7 +1627,6 @@ local function injectspaces(head) local threshold = 0 local leftkern = false local rightkern = false - local nuthead = tonut(head) local function updatefont(font,trig) leftkerns = trig.left @@ -1623,7 +1636,7 @@ local function injectspaces(head) factor = getthreshold(font) end - for n in traverse_id(glue_code,nuthead) do + for n in nextglue, head do local prev, next = getspaceboth(n) local prevchar = prev and ischar(prev) local nextchar = next and ischar(next) @@ -1661,12 +1674,8 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar) end - local h = insert_node_before(nuthead,n,italickern(lnew)) - if h == nuthead then - head = tonode(h) - nuthead = h - end - insert_node_after(nuthead,n,italickern(rnew)) + head = insert_node_before(head,n,italickern(lnew)) + insert_node_after(head,n,italickern(rnew)) else local new = old + (leftkern + rightkern) * factor if trace_spaces then @@ -1681,7 +1690,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",prevchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) -- tricky with traverse but ok + insert_node_after(head,n,italickern(new)) -- tricky with traverse but ok else local new = old + leftkern * factor if trace_spaces then @@ -1700,7 +1709,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",nextchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) + insert_node_after(head,n,italickern(new)) else local new = old + rightkern * factor if trace_spaces then @@ -1714,7 +1723,8 @@ local function injectspaces(head) end triggers = false - return head, true + + return head end -- @@ -1740,6 +1750,6 @@ function injections.handler(head,where) end return inject_kerns_only(head,where) else - return head, false + return head end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua index a71e3ad98ca..df83dc96825 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otl.lua @@ -52,14 +52,14 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.103 -- 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.sbixcache = containers.define("fonts", "sbix", otf.version, true) -otf.pdfcache = containers.define("fonts", "pdf", otf.version, true) +otf.version = 3.107 -- 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) +otf.pdfcache = containers.define("fonts", "pdf", otf.version, true) otf.svgenabled = false -otf.sbixenabled = false +otf.pngenabled = false local otfreaders = otf.readers @@ -152,17 +152,17 @@ function otf.load(filename,sub,instance) report_otf("forced reload of %a due to hard coded flag",filename) reload = true end - if reload then + if reload then report_otf("loading %a, hash %a",filename,hash) -- - starttiming(otfreaders) + starttiming(otfreaders,true) data = otfreaders.loadfont(filename,sub or 1,instance) -- we can pass the number instead (if it comes from a name search) if data then -- todo: make this a plugin - local used = checkmemory() - local resources = data.resources - local svgshapes = resources.svgshapes - local sbixshapes = resources.sbixshapes + local used = checkmemory() + local resources = data.resources + local svgshapes = resources.svgshapes + local pngshapes = resources.pngshapes if cleanup == 0 then checkmemory(used,threshold,tracememory) end @@ -186,16 +186,16 @@ function otf.load(filename,sub,instance) checkmemory(used,threshold,tracememory) end end - if sbixshapes then - resources.sbixshapes = nil - if otf.sbixenabled then + if pngshapes then + resources.pngshapes = nil + if otf.pngenabled then local timestamp = os.date() -- work in progress ... a bit boring to do - containers.write(otf.sbixcache,hash, { - sbixshapes = sbixshapes, - timestamp = timestamp, + containers.write(otf.pngcache,hash, { + pngshapes = pngshapes, + timestamp = timestamp, }) - data.properties.sbix = { + data.properties.png = { hash = hash, timestamp = timestamp, } @@ -242,6 +242,7 @@ function otf.load(filename,sub,instance) checkmemory(used,threshold,tracememory) end else + stoptiming(otfreaders) data = nil report_otf("loading failed due to read error") end @@ -405,6 +406,7 @@ local function copytotfm(data,cache_id) local fontname = metadata.fontname local fullname = metadata.fullname or fontname local psname = fontname or fullname + local subfont = metadata.subfontindex local units = metadata.units or 1000 -- if units == 0 then -- catch bugs in fonts @@ -499,6 +501,7 @@ local function copytotfm(data,cache_id) properties.fullname = fullname properties.psname = psname properties.name = filename or fullname + properties.subfont = subfont -- -- properties.name = specification.name -- properties.sub = specification.sub diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua index 4b986bd3b66..6f6d89d434a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-oto.lua @@ -49,7 +49,9 @@ local function gref(descriptions,n) return f_unicode(n) end elseif n then - local num, nam, j = { }, { }, 0 + local num = { } + local nam = { } + local j = 0 for i=1,#n do local ni = n[i] if tonumber(ni) then -- first is likely a key @@ -121,8 +123,8 @@ local basehash, basehashes, applied = { }, 1, { } local function registerbasehash(tfmdata) local properties = tfmdata.properties - local hash = concat(applied," ") - local base = basehash[hash] + local hash = concat(applied," ") + local base = basehash[hash] if not base then basehashes = basehashes + 1 base = basehashes @@ -310,13 +312,16 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis for i=1,nofligatures do local ligature = ligatures[i] - local unicode, tree = ligature[1], ligature[2] + local unicode = ligature[1] + local tree = ligature[2] make_1(present,tree,"ctx_"..unicode) end for i=1,nofligatures do - local ligature = ligatures[i] - local unicode, tree, lookupname = ligature[1], ligature[2], ligature[3] + local ligature = ligatures[i] + local unicode = ligature[1] + local tree = ligature[2] + local lookupname = ligature[3] make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence) end @@ -415,36 +420,42 @@ local function checkmathreplacements(tfmdata,fullname,fixitalics) for unicode, replacement in next, changed do local u = characters[unicode] local r = characters[replacement] - local n = u.next - local v = u.vert_variants - local h = u.horiz_variants - if fixitalics then - -- quite some warnings on stix ... - local ui = u.italic - if ui and not r.italic then + if u and r then + local n = u.next + local v = u.vert_variants + local h = u.horiz_variants + if fixitalics then + -- quite some warnings on stix ... + local ui = u.italic + if ui and not r.italic then + if trace_preparing then + report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + end + r.italic = ui -- print(ui,ri) + end + end + if n and not r.next then if trace_preparing then - report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement) + report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) end - r.italic = ui -- print(ui,ri) + r.next = n end - end - if n and not r.next then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement) + if v and not r.vert_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + end + r.vert_variants = v end - r.next = n - end - if v and not r.vert_variants then - if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement) + if h and not r.horiz_variants then + if trace_preparing then + report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + end + r.horiz_variants = h end - r.vert_variants = v - end - if h and not r.horiz_variants then + else if trace_preparing then - report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement) + report_prepare("error replacing %C by %U",unicode,replacement) end - r.horiz_variants = h end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua index 5bac75052ac..c7ff6b72689 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['font-otr'] = { -- are just a unicode string but it doesn't save that much. It will be an option -- some day. --- Optimizing the widths wil be done anyway as it save quite some on a cjk font +-- Optimizing the widths will be done anyway as it save quite some on a cjk font -- and the existing (old) code if okay. -- todo: more messages (only if really needed) @@ -67,6 +67,7 @@ if not modules then modules = { } end modules ['font-otr'] = { local next, type, tonumber = next, type, tonumber local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub +local fullstrip = string.fullstrip local floor, round = math.floor, math.round local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt local lpegmatch = lpeg.match @@ -121,11 +122,47 @@ local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed num local readfword = readshort -- 16-bit signed integer that describes a quantity in FUnits local readufword = readushort -- 16-bit unsigned integer that describes a quantity in FUnits local readoffset = readushort +local readcardinaltable = streamreader.readcardinaltable +local readintegertable = streamreader.readintegertable function streamreader.readtag(f) return lower(stripstring(readstring(f,4))) end +local short = 2 +local ushort = 2 +local ulong = 4 + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + openfile = streamreader.open + closefile = streamreader.close + setposition = streamreader.setposition + skipshort = streamreader.skipshort + readbytes = streamreader.readbytes + readstring = streamreader.readstring + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readuint = streamreader.readcardinal3 + readulong = streamreader.readcardinal4 + readshort = streamreader.readinteger2 + readlong = streamreader.readinteger4 + readfixed = streamreader.readfixed4 + read2dot14 = streamreader.read2dot14 + readfword = readshort + readufword = readushort + readoffset = readushort + readcardinaltable = streamreader.readcardinaltable + readintegertable = streamreader.readintegertable + + function streamreader.readtag(f) + return lower(stripstring(readstring(f,4))) + end + +end) + -- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a -- signed 64-bit integer @@ -704,20 +741,30 @@ readers.helpers = helpers local function gotodatatable(f,fontdata,tag,criterium) if criterium and f then - local datatable = fontdata.tables[tag] - if datatable then - local tableoffset = datatable.offset - setposition(f,tableoffset) - return tableoffset + local tables = fontdata.tables + if tables then + local datatable = tables[tag] + if datatable then + local tableoffset = datatable.offset + setposition(f,tableoffset) + return tableoffset + end + else + report("no tables") end end end local function reportskippedtable(f,fontdata,tag,criterium) if criterium and f then - local datatable = fontdata.tables[tag] - if datatable then - report("loading of table %a skipped",tag) + local tables = fontdata.tables + if tables then + local datatable = tables[tag] + if datatable then + report("loading of table %a skipped",tag) + end + else + report("no tables") end end end @@ -749,6 +796,16 @@ local platformnames = { compatiblefullname = true, } +local platformextras = { + uniqueid = true, + version = true, + copyright = true, + license = true, + licenseurl = true, + manufacturer = true, + vendorurl = true, +} + function readers.name(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"name",true) if tableoffset then @@ -819,6 +876,18 @@ function readers.name(f,fontdata,specification) -- and extend when we run into it (todo: proper reverse hash) .. we're only -- interested in english anyway -- + local function decoded(platform,encoding,content) + local decoder = decoders[platform] + if decoder then + decoder = decoder[encoding] + end + if decoder then + return decoder(content) + else + return content + end + end + -- local function filter(platform,e,l) local namelist = namelists[platform] for i=1,#namelist do @@ -830,14 +899,7 @@ function readers.name(f,fontdata,specification) local language = name.language if (not e or encoding == e) and (not l or language == l) then setposition(f,name.offset) - local content = readstring(f,name.length) - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end + local content = decoded(platform,encoding,readstring(f,name.length)) if nametag then names[nametag] = { content = content, @@ -864,23 +926,16 @@ function readers.name(f,fontdata,specification) fontdata.extras = extras -- if specification.platformnames then - local collected = { } + local collected = { } + local platformextras = specification.platformextras and platformextras for platform, namelist in next, namelists do local filtered = false for i=1,#namelist do local entry = namelist[i] local name = entry.name - if platformnames[name] then + if platformnames[name] or (platformextras and platformextras[name]) then setposition(f,entry.offset) - local content = readstring(f,entry.length) - local encoding = entry.encoding - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end + local content = decoded(platform,entry.encoding,readstring(f,entry.length)) if filtered then filtered[name] = content else @@ -923,7 +978,7 @@ readers["os/2"] = function(f,fontdata) local version = readushort(f) local windowsmetrics = { version = version, - averagewidth = readshort(f), + averagewidth = readshort(f), -- ushort? weightclass = readushort(f), widthclass = readushort(f), fstype = readushort(f), @@ -953,7 +1008,7 @@ readers["os/2"] = function(f,fontdata) if version >= 1 then windowsmetrics.codepageranges = { readulong(f), readulong(f) } end - if version >= 3 then + if version >= 2 then windowsmetrics.xheight = readshort(f) windowsmetrics.capheight = readshort(f) windowsmetrics.defaultchar = readushort(f) @@ -980,24 +1035,28 @@ end readers.head = function(f,fontdata) local tableoffset = gotodatatable(f,fontdata,"head",true) if tableoffset then + local version = readulong(f) + local fontversion = readulong(f) local fontheader = { - version = readfixed(f), - revision = readfixed(f), - checksum = readulong(f), - magic = readulong(f), - flags = readushort(f), - units = readushort(f), - created = readlongdatetime(f), - modified = readlongdatetime(f), - xmin = readshort(f), - ymin = readshort(f), - xmax = readshort(f), - ymax = readshort(f), - macstyle = readushort(f), - smallpixels = readushort(f), - directionhint = readshort(f), - indextolocformat = readshort(f), - glyphformat = readshort(f), + version = version, + fontversion = number.to16dot16(fontversion), + fontversionnumber = fontversion, + -- checksum = readulong(f), + checksum = readushort(f) * 0x10000 + readushort(f), + magic = readulong(f), + flags = readushort(f), + units = readushort(f), + created = readlongdatetime(f), + modified = readlongdatetime(f), + xmin = readshort(f), + ymin = readshort(f), + xmax = readshort(f), + ymax = readshort(f), + macstyle = readushort(f), + smallpixels = readushort(f), + directionhint = readshort(f), + indextolocformat = readshort(f), + glyphformat = readshort(f), } fontdata.fontheader = fontheader else @@ -1013,7 +1072,7 @@ readers.hhea = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"hhea",specification.details) if tableoffset then fontdata.horizontalheader = { - version = readfixed(f), -- two ushorts: major minor + version = readulong(f), ascender = readfword(f), descender = readfword(f), linegap = readfword(f), @@ -1042,7 +1101,7 @@ readers.vhea = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"vhea",specification.details) if tableoffset then fontdata.verticalheader = { - version = readfixed(f), + version = readulong(f), ascender = readfword(f), descender = readfword(f), linegap = readfword(f), @@ -1075,15 +1134,15 @@ end readers.maxp = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"maxp",specification.details) if tableoffset then - local version = readfixed(f) + local version = readulong(f) local nofglyphs = readushort(f) fontdata.nofglyphs = nofglyphs - if version == 0.5 then + if version == 0x00005000 then fontdata.maximumprofile = { version = version, nofglyphs = nofglyphs, } - elseif version == 1.0 then + elseif version == 0x00010000 then fontdata.maximumprofile = { version = version, nofglyphs = nofglyphs, @@ -1124,15 +1183,14 @@ readers.hmtx = function(f,fontdata,specification) local leftsidebearing = 0 for i=0,nofmetrics-1 do local glyph = glyphs[i] - width = readshort(f) + width = readshort(f) -- readushort leftsidebearing = readshort(f) if width ~= 0 then glyph.width = width end --- for now --- if leftsidebearing ~= 0 then --- glyph.lsb = leftsidebearing --- end + -- if leftsidebearing ~= 0 then + -- glyph.lsb = leftsidebearing + -- end end -- The next can happen in for instance a monospace font or in a cjk font -- with fixed widths. @@ -1145,7 +1203,6 @@ readers.hmtx = function(f,fontdata,specification) -- glyph.lsb = leftsidebearing -- end end - -- hm, there can be a lsb here end end @@ -1195,7 +1252,7 @@ end readers.post = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"post",true) if tableoffset then - local version = readfixed(f) + local version = readulong(f) fontdata.postscript = { version = version, italicangle = round(1000*readfixed(f))/1000, @@ -1209,12 +1266,12 @@ readers.post = function(f,fontdata,specification) } if not specification.glyphs then -- enough done - elseif version == 1.0 then + elseif version == 0x00010000 then -- mac encoding (258 glyphs) for index=0,#standardromanencoding do glyphs[index].name = standardromanencoding[index] end - elseif version == 2.0 then + elseif version == 0x00020000 then local glyphs = fontdata.glyphs local nofglyphs = readushort(f) local indices = { } @@ -1245,10 +1302,6 @@ readers.post = function(f,fontdata,specification) end end end - elseif version == 2.5 then - -- depricated, will be done when needed - elseif version == 3.0 then - -- no ps name information end else fontdata.postscript = { } @@ -1321,34 +1374,18 @@ formatreaders[4] = function(f,fontdata,offset) -- skipshort(f,3) -- searchrange entryselector rangeshift -- - local endchars = { } - local startchars = { } - local deltas = { } - local offsets = { } - local indices = { } local mapping = fontdata.mapping local glyphs = fontdata.glyphs local duplicates = fontdata.duplicates local nofdone = 0 - -- - for i=1,nofsegments do - endchars[i] = readushort(f) - end - local reserved = readushort(f) -- 0 - for i=1,nofsegments do - startchars[i] = readushort(f) - end - for i=1,nofsegments do - deltas[i] = readshort(f) - end - for i=1,nofsegments do - offsets[i] = readushort(f) - end + local endchars = readcardinaltable(f,nofsegments,ushort) + local reserved = readushort(f) -- 0 + local startchars = readcardinaltable(f,nofsegments,ushort) + local deltas = readcardinaltable(f,nofsegments,ushort) + local offsets = readcardinaltable(f,nofsegments,ushort) -- format length language nofsegments searchrange entryselector rangeshift 4-tables - local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2 - for i=1,size-1 do - indices[i] = readushort(f) - end + local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2 + local indices = readcardinaltable(f,size-1,ushort) -- for segment=1,nofsegments do local startchar = startchars[segment] @@ -1927,14 +1964,16 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,inst designsize = fontdata.designsize, minsize = fontdata.minsize, maxsize = fontdata.maxsize, + boundingbox = fontheader and { fontheader.xmin or 0, fontheader.ymin or 0, fontheader.xmax or 0, fontheader.ymax or 0 } or nil, monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced", averagewidth = metrics.averagewidth, - xheight = metrics.xheight, - capheight = metrics.capheight, -- not always present and probably crap + xheight = metrics.xheight, -- can be missing + capheight = metrics.capheight or fontdata.maxy, -- can be missing ascender = metrics.typoascender, descender = metrics.typodescender, platformnames = platformnames or nil, instancenames = instancenames or nil, + tableoffsets = fontdata.tableoffsets, } if metricstoo then local keys = { @@ -1996,7 +2035,8 @@ local function loadtables(f,specification,offset) } for i=1,fontdata.noftables do local tag = lower(stripstring(readstring(f,4))) - local checksum = readulong(f) -- not used + -- local checksum = readulong(f) -- not used + local checksum = readushort(f) * 0x10000 + readushort(f) local offset = readulong(f) local length = readulong(f) if offset + length > filesize then @@ -2008,13 +2048,14 @@ local function loadtables(f,specification,offset) length = length, } end +-- inspect(tables) fontdata.foundtables = sortedkeys(tables) if tables.cff or tables.cff2 then fontdata.format = "opentype" else fontdata.format = "truetype" end - return fontdata + return fontdata, tables end local function prepareglyps(fontdata) @@ -2043,7 +2084,7 @@ local variablefonts_supported = (context and true) or (logs and logs.application local function readdata(f,offset,specification) - local fontdata = loadtables(f,specification,offset) + local fontdata, tables = loadtables(f,specification,offset) if specification.glyphs then prepareglyps(fontdata) @@ -2182,10 +2223,20 @@ local function readdata(f,offset,specification) readtable("math",f,fontdata,specification) fontdata.locations = nil - fontdata.tables = nil fontdata.cidmaps = nil fontdata.dictionaries = nil -- fontdata.cff = nil + + if specification.tableoffsets then + fontdata.tableoffsets = tables + setmetatableindex(tables, { + version = fontdata.version, + noftables = fontdata.noftables, + searchrange = fontdata.searchrange, + entryselector = fontdata.entryselector, + rangeshift = fontdata.rangeshift, + }) + end return fontdata end @@ -2209,12 +2260,9 @@ local function loadfontdata(specification) fontdata = readdata(f,0,specification) elseif version == "ttcf" then local subfont = tonumber(specification.subfont) - local offsets = { } local ttcversion = readulong(f) local nofsubfonts = readulong(f) - for i=1,nofsubfonts do - offsets[i] = readulong(f) - end + local offsets = readcardinaltable(f,nofsubfonts,ulong) if subfont then -- a number of not if subfont >= 1 and subfont <= nofsubfonts then fontdata = readdata(f,offsets[subfont],specification) @@ -2296,12 +2344,13 @@ local function loadfont(specification,n,instance) specification.instance = specification.instance or instance end local function message(str) - report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback()) + report("fatal error in file %a: %s\n%s",specification.filename,str,debug and debug.traceback()) end local ok, result = xpcall(loadfontdata,message,specification) if ok then return result end +-- return loadfontdata(specification) end -- we need even less, but we can have a 'detail' variant @@ -2323,13 +2372,26 @@ function readers.loadshapes(filename,n,instance,streams) v.math = nil -- v.name = nil end + local names = fontdata.names + if names then + for k, v in next, names do + names[k] = fullstrip(v.content) + end + end end return fontdata and { - -- version = 0.123 -- todo - filename = filename, - format = fontdata.format, - glyphs = fontdata.glyphs, - units = fontdata.fontheader.units, + -- version = 0.123 -- todo + filename = filename, + format = fontdata.format, + glyphs = fontdata.glyphs, + units = fontdata.fontheader.units, + cffinfo = fontdata.cffinfo, + fontheader = fontdata.fontheader, + horizontalheader = fontdata.horizontalheader, + verticalheader = fontdata.verticalheader, + maximumprofile = fontdata.maximumprofile, + names = fontdata.names, + postscript = fontdata.postscript, } or { filename = filename, format = "unknown", @@ -2385,7 +2447,7 @@ function readers.loadfont(filename,n,instance) mathconstants = fontdata.mathconstants, colorpalettes = fontdata.colorpalettes, svgshapes = fontdata.svgshapes, - sbixshapes = fontdata.sbixshapes, + pngshapes = fontdata.pngshapes, variabledata = fontdata.variabledata, foundtables = fontdata.foundtables, }, @@ -2400,10 +2462,12 @@ function readers.getinfo(filename,specification) -- string, nil|number|table local platformnames = false local rawfamilynames = false local instancenames = true + local tableoffsets = false if type(specification) == "table" then subfont = tonumber(specification.subfont) platformnames = specification.platformnames rawfamilynames = specification.rawfamilynames + tableoffsets = specification.tableoffsets else subfont = tonumber(specification) end @@ -2412,6 +2476,7 @@ function readers.getinfo(filename,specification) -- string, nil|number|table details = true, platformnames = platformnames, instancenames = true, + tableoffsets = tableoffsets, -- rawfamilynames = rawfamilynames, } if fontdata then diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua index 25083dfcef8..563094fc17b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ots.lua @@ -82,7 +82,7 @@ mechanisms. Both put some constraints on the code here.

-- Todo: check if we copy attributes to disc nodes if needed. -- -- Todo: it would be nice if we could get rid of components. In other places we can use --- the unicode properties. +-- the unicode properties. We can just keep a lua table. -- -- Remark: We do some disc juggling where we need to keep in mind that the pre, post and -- replace fields can have prev pointers to a nesting node ... I wonder if that is still @@ -176,8 +176,6 @@ registertracker("otf.sample", "otf.steps","otf.substitutions","otf.positi registertracker("otf.sample.silent", "otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing") local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getfield = nuts.getfield local getnext = nuts.getnext @@ -191,7 +189,6 @@ local getattr = nuts.getattr local setattr = nuts.setattr local getprop = nuts.getprop local setprop = nuts.setprop -local getfont = nuts.getfont local getsubtype = nuts.getsubtype local setsubtype = nuts.setsubtype local getchar = nuts.getchar @@ -201,10 +198,10 @@ local setdisc = nuts.setdisc local setlink = nuts.setlink local getcomponents = nuts.getcomponents -- the original one, not yet node-aux local setcomponents = nuts.setcomponents -- the original one, not yet node-aux -local getdir = nuts.getdir local getwidth = nuts.getwidth local ischar = nuts.is_char +local isglyph = nuts.isglyph local usesfont = nuts.uses_font local insert_node_after = nuts.insert_after @@ -215,17 +212,12 @@ local find_node_tail = nuts.tail local flush_node_list = nuts.flush_list local flush_node = nuts.flush_node local end_of_math = nuts.end_of_math -local traverse_nodes = nuts.traverse ------ traverse_id = nuts.traverse_id -local set_components = nuts.set_components -local take_components = nuts.take_components -local count_components = nuts.count_components -local copy_no_components = nuts.copy_no_components -local copy_only_glyphs = nuts.copy_only_glyphs local setmetatable = setmetatable local setmetatableindex = table.setmetatableindex +local nextnode = nuts.traversers.node + ----- zwnj = 0x200C ----- zwj = 0x200D @@ -240,8 +232,8 @@ local math_code = nodecodes.math local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local discretionary_code = disccodes.discretionary -local ligature_code = glyphcodes.ligature +local discretionarydisc_code = disccodes.discretionary +local ligatureglyph_code = glyphcodes.ligature local a_state = attributes.private('state') local a_noligature = attributes.private("noligature") @@ -458,26 +450,28 @@ end -- start is a mark and we need to keep that one -local take_components = getcomponents -- we overload here (for now) -local set_components = setcomponents -- we overload here (for now) ------ get_components = getcomponents -- we overload here (for now) +local copy_no_components = nuts.copy_no_components +local copy_only_glyphs = nuts.copy_only_glyphs + +local set_components = setcomponents +local take_components = getcomponents local function count_components(start,marks) - if getid(start) ~= glyph_code then - return 0 - elseif getsubtype(start) == ligature_code then - local i = 0 - local components = getcomponents(start) - while components do - i = i + count_components(components,marks) - components = getnext(components) + local char = isglyph(start) + if char then + if getsubtype(start) == ligatureglyph_code then + local i = 0 + local components = getcomponents(start) + while components do + i = i + count_components(components,marks) + components = getnext(components) + end + return i + elseif not marks[char] then + return 1 end - return i - elseif not marks[getchar(start)] then - return 1 - else - return 0 end + return 0 end local function markstoligature(head,start,stop,char) @@ -494,7 +488,7 @@ local function markstoligature(head,start,stop,char) end resetinjection(base) setchar(base,char) - setsubtype(base,ligature_code) + setsubtype(base,ligatureglyph_code) set_components(base,start) setlink(prev,base,next) return head, base @@ -530,7 +524,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou end resetinjection(base) setchar(base,char) - setsubtype(base,ligature_code) + setsubtype(base,ligatureglyph_code) set_components(base,comp) setlink(prev,base,next) if not discfound then @@ -612,7 +606,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou set_components(base,copied) replace = base if forcediscretionaries then - setdisc(discfound,pre,post,replace,discretionary_code) + setdisc(discfound,pre,post,replace,discretionarydisc_code) else setdisc(discfound,pre,post,replace) end @@ -623,7 +617,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou return head, base end -local function multiple_glyphs(head,start,multiple,skiphash,what) -- what to do with skiphash matches here +local function multiple_glyphs(head,start,multiple,skiphash,what,stop) -- what to do with skiphash matches here local nofmultiples = #multiple if nofmultiples > 0 then resetinjection(start) @@ -784,23 +778,17 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip -- ok, goto next lookup end end - else -- is the check for disc still valid here ? and why only replace then + else local discfound = false - local lastdisc = nil local hasmarks = marks[startchar] while current do local char, id = ischar(current,currentfont) if char then if skiphash and skiphash[char] then current = getnext(current) - -- if stop then stop = current end -- ? - else -- ligature is a tree - local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font + else + local lg = ligature[char] if lg then - if not discfound and lastdisc then - discfound = lastdisc - lastdisc = nil - end if marks[char] then hasmarks = true end @@ -815,58 +803,89 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip -- kind of weird break elseif id == disc_code then - -- - -- Kai: see chainprocs, we probably could do the same here or was there a reason - -- why we kept the replace check here. - -- - -- if not discfound then - -- discfound = current - -- end - -- if current == stop then - -- break -- okay? or before the disc - -- else - -- current = getnext(current) - -- end - -- - local replace = getfield(current,"replace") -- hm: pre and post - if replace then - -- of{f-}{}{f}e o{f-}{}{f}fe o{-}{}{ff}e (oe and ff ligature) - -- we can end up here when we have a start run .. testruns start at a disc but - -- so here we have the other case: char + disc - while replace do - local char, id = ischar(replace,currentfont) - if char then - local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font - if lg then - if marks[char] then - hasmarks = true -- very unlikely - end - ligature = lg - replace = getnext(replace) - else - return head, start, false, false - end - else - return head, start, false, false - end - end - stop = current - end - lastdisc = current - current = getnext(current) + discfound = current + break else break end end + -- of{f-}{}{f}e o{f-}{}{f}fe o{-}{}{ff}e (oe and ff ligature) + -- we can end up here when we have a start run .. testruns start at a disc but + -- so here we have the other case: char + disc + if discfound then + -- don't assume marks in a disc and we don't run over a disc (for now) + local pre, post, replace = getdisc(discfound) + local match + if replace then + local char = ischar(replace,currentfont) + if char 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 + 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 + match = true + end + end + if match then + -- we force a restart + local ishead = head == start + local prev = getprev(start) + if stop then + setnext(stop) + local tail = getprev(stop) + local copy = copy_node_list(start) + local liat = find_node_tail(copy) + if pre then + setlink(liat,pre) + end + if replace then + setlink(tail,replace) + end + pre = copy + replace = start + else + setnext(start) + local copy = copy_node(start) + if pre then + setlink(copy,pre) + end + if replace then + setlink(start,replace) + end + pre = copy + replace = start + end + setdisc(discfound,pre,post,replace) + if prev then + setlink(prev,discfound) + else + setprev(discfound) + head = discfound + end + start = discfound + return head, start, true, true + end + end local lig = ligature.ligature if lig 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,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)) else - head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) + -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) + head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) end else -- weird but happens (in some arabic font) @@ -876,12 +895,12 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) end end - return head, start, true, discfound + return head, start, true, false else -- weird but happens, pseudo ligatures ... just the components end end - return head, start, false, discfound + return head, start, false, false end function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection) @@ -920,7 +939,8 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,st end local format = step.format if format == "pair" then - local a, b = krn[1], krn[2] + local a = krn[1] + local b = krn[2] if a == true then -- zero elseif a then -- #a > 0 @@ -1270,6 +1290,14 @@ local function getmapping(dataset,sequence,currentlookup) end end +function chainprocs.gsub_remove(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex) + if trace_chains then + logprocess("%s: removing character %s",cref(dataset,sequence,chainindex),gref(getchar(start))) + end + head, start = remove_node(head,start,true) + return head, getprev(start), true +end + function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex) local mapping = currentlookup.mapping if mapping == nil then @@ -1380,7 +1408,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup if trace_multiples then logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement)) end - return multiple_glyphs(head,start,replacement,skiphash,dataset[1]) + return multiple_glyphs(head,start,replacement,skiphash,dataset[1],stop) end end return head, start, false @@ -1532,7 +1560,8 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm end local format = currentlookup.format if format == "pair" then - local a, b = krn[1], krn[2] + local a = krn[1] + local b = krn[2] if a == true then -- zero elseif a then @@ -1986,6 +2015,9 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck) logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind) end end + else + -- we skip but we could also delete as option .. what does an empty lookup actually mean + -- in opentype ... anyway, we could map it onto gsub_remove if needed end i = i + 1 if i > size or not start then @@ -2625,7 +2657,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s end end else - notmatchreplace[prev] = true -- new, for Kai to check + -- notmatchreplace[prev] = true -- not according to Kai end end prev = getprev(prev) @@ -2754,7 +2786,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s end end else - notmatchreplace[current] = true -- new, for Kai to check + -- notmatchreplace[current] = true -- not according to Kai end current = getnext(current) elseif id == glue_code then @@ -2802,6 +2834,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s notmatchpre = { } notmatchpost = { } notmatchreplace = { } + -- notmatchpre = { a = 1, b = 1 } notmatchpre .a = nil notmatchpre .b = nil + -- notmatchpost = { a = 1, b = 1 } notmatchpost .a = nil notmatchpost .b = nil + -- notmatchreplace = { a = 1, b = 1 } notmatchreplace.a = nil notmatchreplace.b = nil end return head, start, done end @@ -3159,7 +3194,7 @@ local function testrun(disc,t_run,c_run,...) local d = d_replace > d_post and d_replace or d_post local head = getnext(disc) -- is: next local tail = head - for i=1,d do + for i=2,d do -- must start at 2 according to Kai local nx = getnext(tail) local id = getid(nx) if id == disc_code then @@ -3419,7 +3454,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase a = getattr(sub,0) end if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos + for n in nextnode, sub do -- only gpos if n == last then break end @@ -3584,7 +3619,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase a = getattr(sub,0) end if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos + for n in nextnode, sub do -- only gpos if n == last then break end @@ -3606,129 +3641,57 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase end end --- to be checked, nowadays we probably can assume properly matched directions --- so maybe we no longer need a stack - --- local function txtdirstate(start,stack,top,rlparmode) --- local dir = getdir(start) --- local new = 1 --- if dir == "+TRT" then --- top = top + 1 --- stack[top] = dir --- new = -1 --- elseif dir == "+TLT" then --- top = top + 1 --- stack[top] = dir --- elseif dir == "-TRT" or dir == "-TLT" then --- if top == 1 then --- top = 0 --- new = rlparmode --- else --- top = top - 1 --- if stack[top] == "+TRT" then --- new = -1 --- end --- end --- else --- new = rlparmode --- end --- return getnext(start), top, new --- end --- --- local function pardirstate(start) --- local dir = getdir(start) --- local new = 0 --- if dir == "TLT" then --- new = 1 --- elseif dir == "TRT" then --- new = -1 --- end --- return getnext(start), new, new --- end +local txtdirstate, pardirstate do -- this might change (no need for nxt in pardirstate) -local function txtdirstate(start,stack,top,rlparmode) - local nxt = getnext(start) - local dir = getdir(start) - if dir == "+TRT" then - top = top + 1 - stack[top] = dir - return nxt, top, -1 - elseif dir == "+TLT" then - top = top + 1 - stack[top] = dir - return nxt, top, 1 - elseif dir == "-TRT" or dir == "-TLT" then - if top == 1 then - return nxt, 0, rlparmode - else - top = top - 1 - if stack[top] == "+TRT" then - return nxt, top, -1 + local getdirection = nuts.getdirection + local lefttoright = 0 + local righttoleft = 1 + + txtdirstate = function(start,stack,top,rlparmode) + local dir, pop = getdirection(start) + if pop then + if top == 1 then + return 0, rlparmode else - return nxt, top, 1 + top = top - 1 + if stack[top] == righttoleft then + return top, -1 + else + return top, 1 + end end + elseif dir == lefttoright then + top = top + 1 + stack[top] = lefttoright + return top, 1 + elseif dir == righttoleft then + top = top + 1 + stack[top] = righttoleft + return top, -1 + else + return top, rlparmode end - else - return nxt, top, rlparmode end -end -local function pardirstate(start) - local nxt = getnext(start) - local dir = getdir(start) - if dir == "TLT" then - return nxt, 1, 1 - elseif dir == "TRT" then - return nxt, -1, -1 - else - return nxt, 0, 0 + pardirstate = function(start) + local dir = getdirection(start) + if dir == lefttoright then + return 1, 1 + elseif dir == righttoleft then + return -1, -1 + -- for old times sake we we handle strings too + elseif dir == "TLT" then + return 1, 1 + elseif dir == "TRT" then + return -1, -1 + else + return 0, 0 + end end + end --- -- this will become: --- --- local getdirection = nuts.getdirection --- --- local function txtdirstate1(start,stack,top,rlparmode) --- local nxt = getnext(start) --- local dir, sub = getdirection(start) --- if sub then --- if top == 1 then --- return nxt, 0, rlparmode --- elseif dir < 2 then --- top = top - 1 --- if stack[top] == 1 then --- return nxt, top, -1 --- else --- return nxt, top, 1 --- end --- else --- return nxt, top, rlparmode --- end --- elseif dir == 1 then --- top = top + 1 --- stack[top] = 1 --- return nxt, top, -1 --- elseif dir == 0 then --- top = top + 1 --- stack[top] = 0 --- return nxt, top, 1 --- else --- return nxt, top, rlparmode --- end --- end --- --- local function pardirstate1(start) --- local nxt = getnext(start) --- local dir = getdirection(start) --- if dir == 0 then --- return nxt, 1, 1 --- elseif dir == 1 then --- return nxt, -1, -1 --- else --- return nxt, 0, 0 --- end --- end +-- These are non public helpers that can change without notice! otf.helpers = otf.helpers or { } otf.helpers.txtdirstate = txtdirstate @@ -3832,20 +3795,23 @@ do -- attr = false -- end - local head = tonut(head) - if trace_steps then checkstep(head) end - local initialrl = direction == "TRT" and -1 or 0 - -- local initialrl = (direction == 1 or direction == "TRT") and -1 or 0 + local initialrl = 0 - local done = false - -- local datasets = otf.dataset(tfmdata,font,attr) + if getid(head) == localpar_code and getsubtype(head) == 0 then + initialrl = pardirstate(head) + elseif direction == 1 or direction == "TRT" then + initialrl = -1 + end + + -- local done = false local datasets = otfdataset(tfmdata,font,attr) - local dirstack = { } -- could move outside function but we can have local runs + local dirstack = { nil } -- could move outside function but we can have local runs sweephead = { } + -- sweephead = { a = 1, b = 1 } sweephead.a = nil sweephead.b = nil -- Keeping track of the headnode is needed for devanagari. (I generalized it a bit -- so that multiple cases are also covered.) We could prepend a temp node. @@ -3872,9 +3838,9 @@ do -- are not frozen as we might extend or change this. Is this used at all apart from some -- experiments? local h, ok = handler(head,dataset,sequence,initialrl,font,attr) -- less arguments now - if ok then - done = true - end + -- if ok then + -- done = true + -- end if h and h ~= head then head = h end @@ -3907,7 +3873,7 @@ do local ok head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) if ok then - done = true + -- done = true break end end @@ -3948,12 +3914,14 @@ do a = true end if a then - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if ok then - done = true - end - if start then + local ok, df + head, start, ok, df = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) + -- if ok then + -- done = true + -- end + if df then +-- print("restart 1",typ) + elseif start then start = getnext(start) end else @@ -3976,18 +3944,20 @@ do else start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done = true - end + -- if ok then + -- done = true + -- end else start = getnext(start) end elseif id == math_code then start = getnext(end_of_math(start)) elseif id == dir_code then - start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) - elseif id == localpar_code then - start, rlparmode, rlmode = pardirstate(start) + topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) + start = getnext(start) + -- elseif id == localpar_code then + -- rlparmode, rlmode = pardirstate(start) + -- start = getnext(start) else start = getnext(start) end @@ -4011,6 +3981,7 @@ do a = true end if a then + local ok, df for i=m[1],m[2] do local step = steps[i] -- for i=1,#m do @@ -4019,10 +3990,12 @@ do local lookupmatch = lookupcache[char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable - local ok - head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if ok then - done = true +-- local ok, df + head, start, ok, df = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) + if df then + break + elseif ok then + -- done = true break elseif not start then -- don't ask why ... shouldn't happen @@ -4030,7 +4003,9 @@ do end end end - if start then + if df then +-- print("restart 2",typ) + elseif start then start = getnext(start) end else @@ -4053,18 +4028,20 @@ do else start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done = true - end + -- if ok then + -- done = true + -- end else start = getnext(start) end elseif id == math_code then start = getnext(end_of_math(start)) elseif id == dir_code then - start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) - elseif id == localpar_code then - start, rlparmode, rlmode = pardirstate(start) + topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) + start = getnext(start) + -- elseif id == localpar_code then + -- rlparmode, rlmode = pardirstate(start) + -- start = getnext(start) else start = getnext(start) end @@ -4079,12 +4056,12 @@ do end nesting = nesting - 1 - head = tonode(head) - return head, done + -- return head, done + return head end - -- This is not an official helpoer and used for tracing experiments. It can be changed as I like + -- This is not an official helper and used for tracing experiments. It can be changed as I like -- at any moment. At some point it might be used in a module that can help font development. function otf.datasetpositionprocessor(head,font,direction,dataset) @@ -4118,12 +4095,10 @@ do local steps = sequence.steps local nofsteps = sequence.nofsteps - local head = tonut(head) local done = false - local dirstack = { } -- could move outside function but we can have local runs + local dirstack = { nil } -- could move outside function but we can have local runs (maybe a few more nils) local start = head - local initialrl = direction == "TRT" and -1 or 0 - -- local initialrl = (direction == 1 or direction == "TRT") and -1 or 0 + local initialrl = (direction == 1 or direction == "TRT") and -1 or 0 local rlmode = initialrl local rlparmode = initialrl local topstack = 0 @@ -4173,15 +4148,17 @@ do elseif id == math_code then start = getnext(end_of_math(start)) elseif id == dir_code then - start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) - elseif id == localpar_code then - start, rlparmode, rlmode = pardirstate(start) + topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) + start = getnext(start) + -- elseif id == localpar_code then + -- rlparmode, rlmode = pardirstate(start) + -- start = getnext(start) else start = getnext(start) end end - return tonode(head) -- , matches + return head end -- end of experiment @@ -4193,9 +4170,26 @@ end local plugins = { } otf.plugins = plugins +local report = logs.reporter("fonts") + function otf.registerplugin(name,f) if type(name) == "string" and type(f) == "function" then plugins[name] = { name, f } + report() + report("plugin %a has been loaded, please be aware of possible side effects",name) + report() + if logs.pushtarget then + logs.pushtarget("log") + end + report("Plugins are not officially supported unless stated otherwise. This is because") + report("they bypass the regular font handling and therefore some features in ConTeXt") + report("(especially those related to fonts) might not work as expected or might not work") + report("at all. Some plugins are for testing and development only and might change") + report("whenever we feel the need for it.") + report() + if logs.poptarget then + logs.poptarget() + end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua index 59d92f40d84..10420f6eeb1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ott.lua @@ -8,7 +8,8 @@ if not modules then modules = { } end modules ["font-ott"] = { } local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset -local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match +local gsub, lower, format, match, gmatch, find = string.gsub, string.lower, string.format, string.match, string.gmatch, string.find +local sequenced = table.sequenced local is_boolean = string.is_boolean local setmetatableindex = table.setmetatableindex @@ -389,6 +390,7 @@ local languages = allocate { ["kiu" ] = "kirmanjki", ["kjd" ] = "southern kiwai", ["kjp" ] = "eastern pwo karen", + ["kjz" ] = "bumthangkha", ["kkn" ] = "kokni", ["klm" ] = "kalmyk", ["kmb" ] = "kamba", @@ -477,6 +479,7 @@ local languages = allocate { ["mdr" ] = "mandar", ["men" ] = "me'en", ["mer" ] = "meru", + ["mfa" ] = "pattani malay", ["mfe" ] = "morisyen", ["min" ] = "minangkabau", ["miz" ] = "mizo", @@ -674,6 +677,7 @@ local languages = allocate { ["tpi" ] = "tok pisin", ["trk" ] = "turkish", ["tsg" ] = "tsonga", + ["tsj" ] = "tshangla", ["tua" ] = "turoyo aramaic", ["tul" ] = "tulu", ["tuv" ] = "tuvin", @@ -704,6 +708,7 @@ local languages = allocate { ["xbd" ] = "lü", ["xhs" ] = "xhosa", ["xjb" ] = "minjangbal", + ["xkf" ] = "khengkha", ["xog" ] = "soga", ["xpe" ] = "kpelle (liberia)", ["yak" ] = "sakha", @@ -987,9 +992,13 @@ setmetatableindex(languages, function(t,k) return "dflt" end) -setmetatablenewindex(languages, "ignore") -setmetatablenewindex(baselines, "ignore") -setmetatablenewindex(baselines, "ignore") +if setmetatablenewindex then + + setmetatablenewindex(languages, "ignore") + setmetatablenewindex(scripts, "ignore") + setmetatablenewindex(baselines, "ignore") + +end local function resolve(t,k) if k then @@ -1029,7 +1038,11 @@ local function assign(t,k,v) end end -setmetatablenewindex(features, assign) +if setmetatablenewindex then + + setmetatablenewindex(features, assign) + +end local checkers = { rand = function(v) @@ -1085,7 +1098,7 @@ storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.sta local normalizedaxis = otf.readers.helpers.normalizedaxis or function(s) return s end -function otffeatures.normalize(features) +function otffeatures.normalize(features,wrap) -- wrap is for context if features then local h = { } for key, value in next, features do @@ -1098,9 +1111,9 @@ function otffeatures.normalize(features) h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds elseif k == "axis" then h[k] = normalizedaxis(value) -if not callbacks.supported.glyph_stream_provider then - h.variableshapes = true -- for the moment -end + if not callbacks.supported.glyph_stream_provider then + h.variableshapes = true -- for the moment + end else local uk = usedfeatures[key] local uv = uk[value] @@ -1113,10 +1126,27 @@ end elseif type(value) == "string" then local b = is_boolean(value) if type(b) == "nil" then - uv = lower(value) + -- we do this elsewhere + -- + -- if find(value,"=") then + -- local t = { } + -- for k, v in gmatch(value,"([^%s,=]+)%s*=%s*([^%s,=]+)") do + -- t[k] = tonumber(v) or v + -- end + -- if next(t) then + -- value = sequenced(t,",") + -- end + -- end + if wrap and find(value,",") then + uv = "{"..lower(value).."}" + else + uv = lower(value) + end else uv = b end + elseif type(value) == "table" then + uv = sequenced(t,",") else uv = value end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua b/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua index 79ac76abee3..d1faadbf712 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-oup.lua @@ -11,27 +11,34 @@ local P, R, S = lpeg.P, lpeg.R, lpeg.S local lpegmatch = lpeg.match local insert, remove, copy, unpack = table.insert, table.remove, table.copy, table.unpack -local formatters = string.formatters -local sortedkeys = table.sortedkeys -local sortedhash = table.sortedhash -local tohash = table.tohash -local setmetatableindex = table.setmetatableindex - -local report = logs.reporter("otf reader") - -local trace_markwidth = false trackers.register("otf.markwidth",function(v) trace_markwidth = v end) - -local readers = fonts.handlers.otf.readers -local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF - -local f_private = formatters["P%05X"] -local f_unicode = formatters["U%05X"] -local f_index = formatters["I%05X"] -local f_character_y = formatters["%C"] -local f_character_n = formatters["[ %C ]"] - -local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway -local check_soft_hyphen = true -- can become an option (pseudo feature) / needed for tagging +local formatters = string.formatters +local sortedkeys = table.sortedkeys +local sortedhash = table.sortedhash +local tohash = table.tohash +local setmetatableindex = table.setmetatableindex + +local report_error = logs.reporter("otf reader","error") +local report_markwidth = logs.reporter("otf reader","markwidth") +local report_cleanup = logs.reporter("otf reader","cleanup") +local report_optimizations = logs.reporter("otf reader","merges") +local report_unicodes = logs.reporter("otf reader","unicodes") + +local trace_markwidth = false trackers.register("otf.markwidth", function(v) trace_markwidth = v end) +local trace_cleanup = false trackers.register("otf.cleanups", function(v) trace_cleanups = v end) +local trace_optimizations = false trackers.register("otf.optimizations", function(v) trace_optimizations = v end) +local trace_unicodes = false trackers.register("otf.unicodes", function(v) trace_unicodes = v end) + +local readers = fonts.handlers.otf.readers +local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF + +local f_private = formatters["P%05X"] +local f_unicode = formatters["U%05X"] +local f_index = formatters["I%05X"] +local f_character_y = formatters["%C"] +local f_character_n = formatters["[ %C ]"] + +local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway +local check_soft_hyphen = true -- can become an option (pseudo feature) / needed for tagging directives.register("otf.checksofthyphen",function(v) check_soft_hyphen = v @@ -67,6 +74,8 @@ local function unifyresources(fontdata,indices) return end -- + local nofindices = #indices + -- local variants = fontdata.resources.variants if variants then for selector, unicodes in next, variants do @@ -83,8 +92,8 @@ local function unifyresources(fontdata,indices) local u = indices[k] if u then newmarks[u] = v - else - report("discarding mark %i",k) + elseif trace_optimizations then + report_optimizations("discarding mark %i",k) end end return newmarks @@ -123,7 +132,12 @@ local function unifyresources(fontdata,indices) if not done[c] then local t = { } for k, v in next, c do - t[indices[k]] = v + local ug = indices[k] + if ug then + t[ug] = v + else + report_error("case %i, bad index in unifying %s: %s of %s",1,"coverage",k,nofindices) + end end cover[i] = t done[c] = d @@ -131,11 +145,16 @@ local function unifyresources(fontdata,indices) end end -- - local function recursed(c) -- ligs are not packed + local function recursed(c,kind) -- ligs are not packed local t = { } for g, d in next, c do if type(d) == "table" then - t[indices[g]] = recursed(d) + local ug = indices[g] + if ug then + t[ug] = recursed(d,kind) + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g,nofindices) + end else t[g] = indices[d] -- ligature end @@ -167,19 +186,31 @@ local function unifyresources(fontdata,indices) if duplicates then for g1, d1 in next, c do local ug1 = indices[g1] - local ud1 = indices[d1] - t1[ug1] = ud1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = ud1 + if ug1 then + local ud1 = indices[d1] + if ud1 then + t1[ug1] = ud1 + local dg1 = duplicates[ug1] + if dg1 then + for u in next, dg1 do + t1[u] = ud1 + end + end + else + report_error("case %i, bad index in unifying %s: %s of %s",3,kind,d1,nofindices) end + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices) end end else for g1, d1 in next, c do - t1[indices[g1]] = indices[d1] + local ug1 = indices[g1] + if ug1 then + t1[ug1] = indices[d1] + else + report_error("fuzzy case %i in unifying %s: %i",2,kind,g1) + end end end done[c] = t1 @@ -193,15 +224,25 @@ local function unifyresources(fontdata,indices) if not t1 then t1 = { } for g1, d1 in next, c do - local t2 = done[d1] - if not t2 then - t2 = { } - for g2, d2 in next, d1 do - t2[indices[g2]] = d2 + local ug1 = indices[g1] + if ug1 then + local t2 = done[d1] + if not t2 then + t2 = { } + for g2, d2 in next, d1 do + local ug2 = indices[g2] + if ug2 then + t2[ug2] = d2 + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g2,nofindices,nofindices) + end + end + done[d1] = t2 end - done[d1] = t2 + t1[ug1] = t2 + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices) end - t1[indices[g1]] = t2 end done[c] = t1 end @@ -210,7 +251,7 @@ local function unifyresources(fontdata,indices) elseif kind == "gsub_ligature" then local c = step.coverage if c then - step.coverage = recursed(c) + step.coverage = recursed(c,kind) end elseif kind == "gsub_alternate" or kind == "gsub_multiple" then local c = step.coverage @@ -221,22 +262,37 @@ local function unifyresources(fontdata,indices) if duplicates then for g1, d1 in next, c do for i=1,#d1 do - d1[i] = indices[d1[i]] + local d1i = d1[i] + local d1u = indices[d1i] + if d1u then + d1[i] = d1u + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,i,d1i,nofindices) + end end local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = copy(d1) + if ug1 then + t1[ug1] = d1 + local dg1 = duplicates[ug1] + if dg1 then + for u in next, dg1 do + t1[u] = copy(d1) + end end + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices) end end else for g1, d1 in next, c do for i=1,#d1 do - d1[i] = indices[d1[i]] + local d1i = d1[i] + local d1u = indices[d1i] + if d1u then + d1[i] = d1u + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,d1i,nofindices) + end end t1[indices[g1]] = d1 end @@ -245,6 +301,41 @@ local function unifyresources(fontdata,indices) end step.coverage = t1 end + elseif kind == "gpos_single" then + local c = step.coverage + if c then + local t1 = done[c] + if not t1 then + t1 = { } + if duplicates then + for g1, d1 in next, c do + local ug1 = indices[g1] + if ug1 then + t1[ug1] = d1 + local dg1 = duplicates[ug1] + if dg1 then + for u in next, dg1 do + t1[u] = d1 + end + end + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices) + end + end + else + for g1, d1 in next, c do + local ug1 = indices[g1] + if ug1 then + t1[ug1] = d1 + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices) + end + end + end + done[c] = t1 + end + step.coverage = t1 + end elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then local c = step.coverage if c then @@ -252,7 +343,12 @@ local function unifyresources(fontdata,indices) if not t1 then t1 = { } for g1, d1 in next, c do - t1[indices[g1]] = d1 + local ug1 = indices[g1] + if ug1 then + t1[ug1] = d1 + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices) + end end done[c] = t1 end @@ -267,7 +363,12 @@ local function unifyresources(fontdata,indices) if not t2 then t2 = { } for g2, d2 in next, d1 do - t2[indices[g2]] = d2 + local ug2 = indices[g2] + if ug2 then + t2[ug2] = d2 + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g2,nofindices) + end end done[d1] = t2 end @@ -276,7 +377,7 @@ local function unifyresources(fontdata,indices) done[c] = c end end - elseif kind == "gpos_single" then + elseif kind == "gpos_cursive" then local c = step.coverage if c then local t1 = done[c] @@ -285,47 +386,29 @@ local function unifyresources(fontdata,indices) if duplicates then for g1, d1 in next, c do local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - for u in next, dg1 do - t1[u] = d1 + if ug1 then + t1[ug1] = d1 + -- + local dg1 = duplicates[ug1] + if dg1 then + -- probably needs a bit more + for u in next, dg1 do + t1[u] = copy(d1) + end end + else + report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices) end end else - for g1, d1 in next, c do - t1[indices[g1]] = d1 - end - end - done[c] = t1 - end - step.coverage = t1 - end - elseif kind == "gpos_cursive" then - local c = step.coverage - if c then - local t1 = done[c] - if not t1 then - t1 = { } - if duplicates then for g1, d1 in next, c do local ug1 = indices[g1] - t1[ug1] = d1 - -- - local dg1 = duplicates[ug1] - if dg1 then - -- probably needs a bit more - for u in next, dg1 do - t1[u] = copy(d1) - end + if ug1 then + t1[ug1] = d1 + else + report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices) end end - else - for g1, d1 in next, c do - t1[indices[g1]] = d1 - end end done[c] = t1 end @@ -376,9 +459,13 @@ local function copyduplicates(fontdata) if not ds or ds.width == 0 then if ds then descriptions[0xAD] = nil - report("patching soft hyphen") + if trace_unicodes then + report_unicodes("patching soft hyphen") + end else - report("adding soft hyphen") + if trace_unicodes then + report_unicodes("adding soft hyphen") + end end if not duplicates then duplicates = { } @@ -414,10 +501,12 @@ local function copyduplicates(fontdata) end n = n + 1 end - if n <= m then - report("duplicates: %i : % t",n,t) - else - report("duplicates: %i : % t ...",n,t) + if trace_unicodes then + if n <= m then + report_unicodes("%i : % t",n,t) + else + report_unicodes("%i : % t ...",n,t) + end end else -- what a mess @@ -457,7 +546,6 @@ local function checklookups(fontdata,missing,nofmissing) end end end - local function collectthem(sequences) if not sequences then return @@ -549,7 +637,9 @@ local function checklookups(fontdata,missing,nofmissing) end end if nofmissing <= 0 then - report("all done in %s loops",loops) + if trace_unicodes then + report_unicodes("all missings done in %s loops",loops) + end return elseif old == nofmissing then break @@ -601,7 +691,9 @@ local function checklookups(fontdata,missing,nofmissing) recursed(ligatures[i]) end if nofmissing <= 0 then - report("all done in %s loops",loops) + if trace_unicodes then + report_unicodes("all missings done in %s loops",loops) + end return elseif old == nofmissing then break @@ -611,7 +703,7 @@ local function checklookups(fontdata,missing,nofmissing) n = 0 end - if nofmissing > 0 then + if trace_unicodes and nofmissing > 0 then local done = { } for i, r in next, missing do if r then @@ -623,7 +715,7 @@ local function checklookups(fontdata,missing,nofmissing) end end if next(done) then - report("not unicoded: % t",sortedkeys(done)) + report_unicodes("not unicoded: % t",sortedkeys(done)) end end end @@ -648,6 +740,10 @@ local function unifymissing(fontdata) resources.unicodes = nil end +local firstprivate = fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000 +local puafirst = 0xE000 +local pualast = 0xF8FF + local function unifyglyphs(fontdata,usenames) local private = fontdata.private or privateoffset local glyphs = fontdata.glyphs @@ -671,44 +767,107 @@ local function unifyglyphs(fontdata,usenames) indices[0] = zerocode end -- - for index=1,#glyphs do - local glyph = glyphs[index] - local unicode = glyph.unicode -- this is the primary one - if not unicode then - -- report("assigning private unicode %U to glyph indexed %05X (%s)",private,index,"unset") - unicode = private - -- glyph.unicode = -1 - if names then + if names then + -- seldom uses, we don't issue message ... this branch might even go away + for index=1,#glyphs do + local glyph = glyphs[index] + local unicode = glyph.unicode -- this is the primary one + if not unicode then + unicode = private local name = glyph.name or f_private(unicode) indices[index] = name names[name] = unicode - else - indices[index] = unicode - end - private = private + 1 - elseif descriptions[unicode] then - -- real weird - report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode) - unicode = private - -- glyph.unicode = -1 - if names then + private = private + 1 + elseif unicode >= firstprivate then + unicode = private local name = glyph.name or f_private(unicode) indices[index] = name names[name] = unicode + private = private + 1 + elseif unicode >= puafirst and unicode <= pualast then + local name = glyph.name or f_private(unicode) + indices[index] = name + names[name] = unicode + elseif descriptions[unicode] then + unicode = private + local name = glyph.name or f_private(unicode) + indices[index] = name + names[name] = unicode + private = private + 1 else - indices[index] = unicode - end - private = private + 1 - else - if names then local name = glyph.name or f_unicode(unicode) indices[index] = name names[name] = unicode + end + descriptions[unicode] = glyph + end + elseif trace_unicodes then + for index=1,#glyphs do + local glyph = glyphs[index] + local unicode = glyph.unicode -- this is the primary one + if not unicode then + unicode = private + indices[index] = unicode + private = private + 1 + elseif unicode >= firstprivate then + local name = glyph.name + if name then + report_unicodes("moving glyph %a indexed %05X from private %U to %U ",name,index,unicode,private) + else + report_unicodes("moving glyph indexed %05X from private %U to %U ",index,unicode,private) + end + unicode = private + indices[index] = unicode + private = private + 1 + elseif unicode >= puafirst and unicode <= pualast then + local name = glyph.name + if name then + report_unicodes("keeping private unicode %U for glyph %a indexed %05X",unicode,name,index) + else + report_unicodes("keeping private unicode %U for glyph indexed %05X",unicode,index) + end + indices[index] = unicode + elseif descriptions[unicode] then + local name = glyph.name + if name then + report_unicodes("assigning duplicate unicode %U to %U for glyph %a indexed %05X ",unicode,private,name,index) + else + report_unicodes("assigning duplicate unicode %U to %U for glyph indexed %05X ",unicode,private,index) + end + unicode = private + indices[index] = unicode + private = private + 1 else indices[index] = unicode end + descriptions[unicode] = glyph + end + else + for index=1,#glyphs do + local glyph = glyphs[index] + local unicode = glyph.unicode -- this is the primary one + if not unicode then + unicode = private + indices[index] = unicode + private = private + 1 + elseif unicode >= firstprivate then + local name = glyph.name + unicode = private + indices[index] = unicode + private = private + 1 + elseif unicode >= puafirst and unicode <= pualast then + local name = glyph.name + indices[index] = unicode + elseif descriptions[unicode] then + local name = glyph.name + unicode = private + indices[index] = unicode + private = private + 1 + else + indices[index] = unicode + end + descriptions[unicode] = glyph end - descriptions[unicode] = glyph end -- for index=1,#glyphs do @@ -757,37 +916,93 @@ local function unifyglyphs(fontdata,usenames) return indices, names end -local p_bogusname = ( - (P("uni") + P("UNI") + P("Uni") + P("U") + P("u")) * S("Xx")^0 * R("09","AF")^1 - + (P("identity") + P("Identity") + P("IDENTITY")) * R("09","AF")^1 - + (P("index") + P("Index") + P("INDEX")) * R("09")^1 -) * P(-1) +local p_crappyname do + + local p_hex = R("af","AF","09") + local p_digit = R("09") + local p_done = S("._-")^0 + P(-1) + local p_alpha = R("az","AZ") + local p_ALPHA = R("AZ") + + p_crappyname = ( + -- (P("uni") + P("UNI") + P("Uni") + P("U") + P("u")) + lpeg.utfchartabletopattern({ "uni", "u" },true) + * S("Xx_")^0 + * p_hex^1 + -- + (P("identity") + P("Identity") + P("IDENTITY") + P("glyph") + P("jamo")) + + lpeg.utfchartabletopattern({ "identity", "glyph", "jamo" },true) + * p_hex^1 + -- + (P("index") + P("Index") + P("INDEX")+ P("afii")) + + lpeg.utfchartabletopattern({ "index", "afii" }, true) + * p_digit^1 + -- also happens l + + p_digit + * p_hex^3 + + p_alpha + * p_digit^1 + -- sort of special + + P("aj") + * p_digit^1 + + P("eh_") + * (p_digit^1 + p_ALPHA * p_digit^1) + + (1-P("_"))^1 + * P("_uni") + * p_hex^1 + + P("_") + * P(1)^1 + ) * p_done + +end + +-- In context we only keep glyph names because of tracing and access by name +-- so weird names make no sense. + +local forcekeep = false -- only for testing something + +directives.register("otf.keepnames",function(v) + report_cleanup("keeping weird glyph names, expect larger files and more memory usage") + forcekeep = v +end) local function stripredundant(fontdata) local descriptions = fontdata.descriptions if descriptions then local n = 0 local c = 0 - for unicode, d in next, descriptions do - local name = d.name - if name and lpegmatch(p_bogusname,name) then - d.name = nil - n = n + 1 + -- in context we always strip + if (not context and fonts.privateoffsets.keepnames) or forcekeep then + for unicode, d in next, descriptions do + if d.class == "base" then + d.class = nil + c = c + 1 + end end - if d.class == "base" then - d.class = nil - c = c + 1 + else + for unicode, d in next, descriptions do + local name = d.name + if name and lpegmatch(p_crappyname,name) then + d.name = nil + n = n + 1 + end + if d.class == "base" then + d.class = nil + c = c + 1 + end end end - if n > 0 then - report("%s bogus names removed (verbose unicode)",n) - end - if c > 0 then - report("%s base class tags removed (default is base)",c) + if trace_cleanup then + if n > 0 then + report_cleanup("%s bogus names removed (verbose unicode)",n) + end + if c > 0 then + report_cleanup("%s base class tags removed (default is base)",c) + end end end end +readers.stripredundant = stripredundant + function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing local resources = fontdata.resources if resources then @@ -813,9 +1028,9 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n end for i=1,#steps do -- we actually had/have this in base mode - local coverage = steps[i].coverage - if coverage then - for k, v in next, coverage do + local c = steps[i].coverage + if c then + for k, v in next, c do traverse(k,k,v) end end @@ -1251,7 +1466,9 @@ function readers.pack(data) end return false elseif nt >= threshold then - local one, two, rest = 0, 0, 0 + local one = 0 + local two = 0 + local rest = 0 if pass == 1 then for k,v in next, c do if v == 1 then @@ -2125,17 +2342,24 @@ local function mergesteps_1(lookup,strict) local f = first.format for i=2,nofsteps do if steps[i].format ~= f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) + end return 0 end end end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + end local target = first.coverage for i=2,nofsteps do - for k, v in next, steps[i].coverage do - if not target[k] then - target[k] = v + local c = steps[i].coverage + if c then + for k, v in next, c do + if not target[k] then + target[k] = v + end end end end @@ -2156,24 +2380,31 @@ local function mergesteps_2(lookup) -- pairs local f = first.format for i=2,nofsteps do if steps[i].format ~= f then - report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name) + end return 0 end end end - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + end local target = first.coverage for i=2,nofsteps do - for k, v in next, steps[i].coverage do - local tk = target[k] - if tk then - for kk, vv in next, v do - if tk[kk] == nil then - tk[kk] = vv + local c = steps[i].coverage + if c then + for k, v in next, c do + local tk = target[k] + if tk then + for kk, vv in next, v do + if tk[kk] == nil then + tk[kk] = vv + end end + else + target[k] = v end - else - target[k] = v end end end @@ -2189,17 +2420,24 @@ end local function mergesteps_3(lookup,strict) -- marks local steps = lookup.steps local nofsteps = lookup.nofsteps - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + end -- check first local coverage = { } for i=1,nofsteps do - for k, v in next, steps[i].coverage do - local tk = coverage[k] -- { class, { x, y } } - if tk then - report("quitting merge due to multiple checks") - return nofsteps - else - coverage[k] = v + local c = steps[i].coverage + if c then + for k, v in next, c do + local tk = coverage[k] -- { class, { x, y } } + if tk then + if trace_optimizations then + report_optimizations("quitting merge due to multiple checks") + end + return nofsteps + else + coverage[k] = v + end end end end @@ -2245,15 +2483,20 @@ local function mergesteps_4(lookup) -- ligatures local steps = lookup.steps local nofsteps = lookup.nofsteps local first = steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + end local target = first.coverage for i=2,nofsteps do - for k, v in next, steps[i].coverage do - local tk = target[k] - if tk then - nested(v,tk) - else - target[k] = v + local c = steps[i].coverage + if c then + for k, v in next, c do + local tk = target[k] + if tk then + nested(v,tk) + else + target[k] = v + end end end end @@ -2270,7 +2513,9 @@ local function mergesteps_5(lookup) -- cursive local steps = lookup.steps local nofsteps = lookup.nofsteps local first = steps[1] - report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name) + end local target = first.coverage local hash = nil for k, v in next, target do @@ -2278,18 +2523,21 @@ local function mergesteps_5(lookup) -- cursive break end for i=2,nofsteps do - for k, v in next, steps[i].coverage do - local tk = target[k] - if tk then - if not tk[2] then - tk[2] = v[2] - end - if not tk[3] then - tk[3] = v[3] + local c = steps[i].coverage + if c then + for k, v in next, c do + local tk = target[k] + if tk then + if not tk[2] then + tk[2] = v[2] + end + if not tk[3] then + tk[3] = v[3] + end + else + target[k] = v + v[1] = hash end - else - target[k] = v - v[1] = hash end end end @@ -2319,7 +2567,9 @@ local function checkkerns(lookup) end end if kerns then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) + end local c = { } for g1, d1 in next, coverage do if d1 and d1 ~= true then @@ -2379,7 +2629,9 @@ local function checkpairs(lookup) if step.format == "pair" then local coverage = onlykerns(step) if coverage then - report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) + if trace_optimizations then + report_optimizations("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name) + end for g1, d1 in next, coverage do local d = { } for g2, d2 in next, d1 do @@ -2502,17 +2754,19 @@ function readers.compact(data) end end end - else - report("no lookups in %a",what) + elseif trace_optimizations then + report_optimizations("no lookups in %a",what) end end compact("sequences") compact("sublookups") - if merged > 0 then - report("%i steps of %i removed due to merging",merged,allsteps) - end - if kerned > 0 then - report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps) + if trace_optimizations then + if merged > 0 then + report_optimizations("%i steps of %i removed due to merging",merged,allsteps) + end + if kerned > 0 then + report_optimizations("%i steps of %i steps turned from pairs into kerns",kerned,allsteps) + end end end @@ -2612,7 +2866,7 @@ function readers.expand(data) -- or bb? d.width = defaultwidth elseif trace_markwidth and wd ~= 0 and d.class == "mark" then - report("mark %a with width %b found in %a",d.name or "",wd,basename) + report_markwidth("mark %a with width %b found in %a",d.name or "",wd,basename) end if bb then local ht = bb[4] diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv index b49bc560ee2..c1c24b8544f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/font-pre.mkiv @@ -53,10 +53,7 @@ script=auto, % on speed; 'base' just doesn't play well with dynamics; some day we can even autoscript=position, autolanguage=position, -% ccmp=yes, kern=yes, % consider skipping the base passes when no base mode is used -% palt=yes, -% pwid=yes, mark=yes, mkmk=yes, curs=yes] @@ -323,6 +320,22 @@ \definefontfeature [tamil-two] [tamil-one] [script=tml2] \definefontfeature [telugu-two] [telugu-one] [script=tel2] +% tibetan + +\definefontfeature + [tibetan] + [always] + [script=tibt, + language=dflt, + locl=yes, + ccmp=yes, + abvs=yes, + blws=yes, + calt=yes, + liga=yes, + abvm=yes, + blwm=yes] + % cjk \definefontfeature @@ -452,9 +465,37 @@ [slanted] [slant=.2] +% \definefontfeature +% [boldened] +% [extend=1.2] + +%D Neat: + +% By eye: +% +% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.125,extend=1.025,squeeze=0.99250}] +% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.250,extend=1.050,squeeze=0.98750}] +% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.375,extend=1.075,squeeze=0.98125}] +% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.500,extend=1.100,squeeze=0.97500}] +% +% By calculation: +% +% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.02500,ddelta=0.02500,vshift=0.02500,extend=1.050,squeeze=0.99500}] +% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.05625,ddelta=0.05625,vshift=0.05625,extend=1.075,squeeze=0.99250}] +% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.10000,ddelta=0.10000,vshift=0.10000,extend=1.100,squeeze=0.99000}] +% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.22500,ddelta=0.22500,vshift=0.22500,extend=1.150,squeeze=0.98500}] +% +% So we can do this: + +\definefontfeature[boldened-10][effect={width=0.10,auto=yes}] +\definefontfeature[boldened-15][effect={width=0.15,auto=yes}] +\definefontfeature[boldened-20][effect={width=0.20,auto=yes}] +\definefontfeature[boldened-25][effect={width=0.25,auto=yes}] +\definefontfeature[boldened-30][effect={width=0.30,auto=yes}] + \definefontfeature [boldened] - [extend=1.2] + [boldened-30] %D Emoji: diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-prv.lua b/Master/texmf-dist/tex/context/base/mkiv/font-prv.lua new file mode 100644 index 00000000000..20c06d2e54e --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-prv.lua @@ -0,0 +1,78 @@ +if not modules then modules = { } end modules ['font-prv'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-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 formatters = string.formatters + +local fonts = fonts +local helpers = fonts.helpers +local fontdata = fonts.hashes.identifiers + +local setmetatableindex = table.setmetatableindex + +local currentprivate = fonts.privateoffsets.textextrabase +local maximumprivate = currentprivate + 0xFFF + +local extraprivates = { } +helpers.extraprivates = extraprivates + +function fonts.helpers.addextraprivate(name,f) + extraprivates[#extraprivates+1] = { name, f } +end + +-- if we run out of space we can think of another range but by sharing we can +-- use these privates for mechanisms like alignments-on-character and such + +local sharedprivates = setmetatableindex(function(t,k) + local v = currentprivate + if currentprivate < maximumprivate then + currentprivate = currentprivate + 1 + else + -- reuse last slot, todo: warning + end + t[k] = v + return v +end) + +function helpers.addprivate(tfmdata,name,characterdata) + local properties = tfmdata.properties + local characters = tfmdata.characters + local privates = properties.privates + if not privates then + privates = { } + properties.privates = privates + end + if not name then + name = formatters["anonymous_private_0x%05X"](currentprivate) + end + local usedprivate = sharedprivates[name] + privates[name] = usedprivate + characters[usedprivate] = characterdata + return usedprivate +end + +function helpers.getprivates(tfmdata) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + return properties and properties.privates +end + +function helpers.hasprivate(tfmdata,name) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + local privates = properties and properties.privates + return privates and privates[name] or false +end + +function helpers.privateslot(name) + return rawget(sharedprivates,name) +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua b/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua index e7f56047b6e..15d3838f6d0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-sel.lua @@ -232,52 +232,6 @@ local m_alternative = { ["sc"] = "smallcaps" } ---~ methods["style"] = function(data,alternative,style) ---~ local family = data.metadata.family ---~ local style = m_alternative[style] or style ---~ if trace_alternatives then ---~ report_selectfont("Alternative '%s': Using method 'style' with argument '%s'",alternative,style) ---~ end ---~ local fontweight = m_name[style] and m_name[style]["weight"] or "regular" ---~ local fontstyle = m_name[style] and m_name[style]["style"] or "normal" ---~ local fontwidth = m_name[style] and m_name[style]["width"] or "normal" ---~ local pattern = getlookups{ ---~ familyname = cleanname(family), ---~ pfmweight = m_weight[fontweight], ---~ style = fontstyle ---~ } ---~ if #pattern == 1 then ---~ selectfont_savefile(data,alternative,0,"default",pattern[1]) ---~ elseif #pattern > 1 then ---~ local bodyfontsize, minsize, maxsize, width = nil, nil, nil, nil ---~ for patternindex, patternentry in next, pattern do ---~ minsize = patternentry["minsize"] ---~ maxsize = patternentry["maxsize"] ---~ width = patternentry["pfmwidth"] ---~ if minsize and maxsize then ---~ for fontsize, fontstate in next, bodyfontsizes do ---~ bodyfontsize, _ = number.splitdimen(fontsize) ---~ bodyfontsize = bodyfontsize * 10 ---~ if minsize < bodyfontsize and bodyfontsize < maxsize then ---~ if bodyfontsize == 100 then ---~ selectfont_savefile(data,alternative,0,"default",patternentry) ---~ end ---~ selectfont_savefile(data,alternative,bodyfontsize,fontsize,patternentry) ---~ end ---~ end ---~ else ---~ if width == m_width[fontwidth] then ---~ selectfont_savefile(data,alternative,0,"default",patternentry) ---~ end ---~ end ---~ end ---~ else ---~ if trace_alternatives then ---~ report_selectfont("Alternative '%s': No font was found for the requested style '%s' from '%s'",alternative,style,family) ---~ end ---~ end ---~ end - local function m_style_family(family) local askedname = cleanname(family) local familyname = getlookups{ familyname = askedname } @@ -348,7 +302,7 @@ local function m_style_style(entries,style) if style == "italic" and entry["angle"] and entry["angle"] ~= 0 then t[#t+1] = entry elseif style == "normal" and entry["angle"] and entry["angle"] ~= 0 then - --~ Fix needed for fonts with wrong value for the style field + -- Fix needed for fonts with wrong value for the style field elseif entry["style"] == style then t[#t+1] = entry end @@ -448,10 +402,10 @@ methods[v_default] = function(data,alternative) report_selectfont("Alternative '%s': The family '%s' contains only one font",alternative,family) end selectfont_savefile(data,alternative,0,"default",result[1]) - --~ if trace_alternatives then - --~ report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative) - --~ end - --~ methods["file"](data,alternative,result[1]["filename"]) + -- if trace_alternatives then + -- report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative) + -- end + -- methods["file"](data,alternative,result[1]["filename"]) else if trace_alternatives then report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative) @@ -499,38 +453,6 @@ function selectfont.userdata(index) end end ---~ function selectfont.registerfiles(index) ---~ local data = data[index] ---~ local colon = splitat(":",true) ---~ for alternative, _ in next, alternatives do ---~ local arguments = data.alternatives[alternative] ---~ if arguments ~= "" then ---~ local entries = settings_to_array(arguments) ---~ local setmethod = false ---~ for index, entry in next, entries do ---~ method, argument = lpegmatch(colon,entry) ---~ if not argument then ---~ argument = method ---~ method = "name" ---~ end ---~ if extras[method] then ---~ extras[method](data,alternative,argument) ---~ elseif methods[method] then ---~ if not setmethod then ---~ setmethod = true ---~ methods[method](data,alternative,argument) ---~ end ---~ end ---~ end ---~ if not setmethod then ---~ methods[v_default](data,alternative) ---~ end ---~ else ---~ methods[v_default](data,alternative) ---~ end ---~ end ---~ end - function selectfont.registerfiles(index) local data = data[index] local colon = splitat(":",true) @@ -662,8 +584,8 @@ function selectfont.fontsynonym(data,class,style,alternative,index) local fontsizes = sortedkeys(fontfiles) local fallback = index ~= 0 local fontclass = lower(class) - --~ local fontfeature = data.features and data.features[alternative] or data.options.features - --~ local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies + --local fontfeature = data.features and data.features[alternative] or data.options.features + --local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies local fontfeature = selectfont.features(data,style,alternative) local fontgoodie = selectfont.goodies (data,style,alternative) local synonym = m_synonym[style] and m_synonym[style][alternative] @@ -675,25 +597,25 @@ function selectfont.fontsynonym(data,class,style,alternative,index) end local fontfallback = formatters["fallback-%s-%s-%s"](fontclass,style,alternative) for _, fontsize in next, fontsizes do - --~ if trace_typescript then - --~ report_typescript("Synonym: '%s', Size: '%s', File: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2]) - --~ end + -- if trace_typescript then + -- report_typescript("Synonym: '%s', Size: '%s', File: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2]) + -- end registerdesignsizes(fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2]) end if fallback then - --~ if trace_typescript then - --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s'",fontsynonym,fontfile,fontfeature) - --~ end + -- if trace_typescript then + -- report_typescript("Synonym: '%s', File: '%s', Features: '%s'",fontsynonym,fontfile,fontfeature) + -- end ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature } ) else - --~ if trace_typescript then - --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s', Goodies: '%s', Fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback) - --~ end + -- if trace_typescript then + -- report_typescript("Synonym: '%s', File: '%s', Features: '%s', Goodies: '%s', Fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback) + -- end ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature, goodies = fontgoodie, fallbacks = fontfallback } ) if synonym then - --~ if trace_typescript then - --~ report_typescript("Synonym: '%s', File: '%s'",synonym,fontsynonym) - --~ end + -- if trace_typescript then + -- report_typescript("Synonym: '%s', File: '%s'",synonym,fontsynonym) + -- end ctx_definefontsynonym( { synonym }, { fontsynonym } ) end end @@ -711,9 +633,9 @@ function selectfont.fontfallback(data,class,style,alternative,index) if index == 1 then ctx_resetfontfallback( { fontfallback } ) end - --~ if trace_typescript then - --~ report_typescript("Fallback: '%s', Synonym: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s'",fontfallback,fontsynonym,range,scale,check,force) - --~ end + -- if trace_typescript then + -- report_typescript("Fallback: '%s', Synonym: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s'",fontfallback,fontsynonym,range,scale,check,force) + -- end ctx_definefontfallback( { fontfallback }, { fontsynonym }, { range }, { rscale = scale, check = check, force = force } ) end @@ -730,9 +652,9 @@ function selectfont.filefallback(data,class,style,alternative,index) if index == 1 then ctx_resetfontfallback( { fontfallback } ) end - --~ if trace_typescript then - --~ report_typescript("Fallback: '%s', File: '%s', Features: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s', Offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset) - --~ end + -- if trace_typescript then + -- report_typescript("Fallback: '%s', File: '%s', Features: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s', Offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset) + -- end ctx_definefontfallback( { fontfallback }, { formatters["file:%s*%s"](fontfile[2],fontfeature) }, { range }, { rscale = scale, check = check, force = force, offset = offset } ) end @@ -763,9 +685,9 @@ function selectfont.fallback(data) local fallbacks = fallbacks[fontclass] and fallbacks[fontclass][fontstyle] if fallbacks then for index, entry in next, fallbacks do - --~ I need different fallback routines for math and text because - --~ font synonyms can’t be used with math fonts and I have to apply - --~ feature settings with the \definefontfallback command. + -- I need different fallback routines for math and text because + -- font synonyms can’t be used with math fonts and I have to apply + -- feature settings with the \definefontfallback command. if fontstyle == "mm" then selectfont.mathfallback(index,entry,fontclass,fontstyle) else @@ -792,7 +714,8 @@ function selectfont.typescript(data) end end for alternative, _ in next, alternatives do - if style == "mm" then -- Set math fonts only for upright and bold alternatives + if style == "mm" then + -- Set math fonts only for upright and bold alternatives if alternative == "tf" or alternative == "bf" then selectfont.fontsynonym (data,class,style,alternative,0) end @@ -813,9 +736,9 @@ function selectfont.bodyfont(data) for alternative, _ in next, alternatives do fontsynonym = formatters["synonym-%s-%s-%s"](fontclass,fontstyle,alternative) fontlist[#fontlist+1] = formatters["%s=%s sa 1"] (alternative,fontsynonym) - --~ if trace_typescript then - --~ report_typescript("Alternative '%s': Synonym '%s'",alternative,fontsynonym) - --~ end + -- if trace_typescript then + -- report_typescript("Alternative '%s': Synonym '%s'",alternative,fontsynonym) + -- end end fontlist = concat(fontlist,",") ctx_definebodyfont( { class }, { fontsizes }, { fontstyle }, { fontlist } ) @@ -836,9 +759,9 @@ function selectfont.typeface(data) local style = m_style[fontstyle] local size = data.options.designsize ~= "" and data.options.designsize or "default" local scale = data.options.rscale ~= "" and data.options.rscale or 1 - --~ if trace_typescript then - --~ report_typescript("Class: '%s', Style: '%s', Size: '%s', Scale: '%s'",fontclass,fontstyle,size,scale) - --~ end + -- if trace_typescript then + -- report_typescript("Class: '%s', Style: '%s', Size: '%s', Scale: '%s'",fontclass,fontstyle,size,scale) + -- end ctx_definetypeface( { fontclass }, { fontstyle }, { style }, { "" }, { "default" }, { designsize = size, rscale = scale } ) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi index 2c6d065d86c..aac83e1aa5f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-set.mkvi @@ -46,7 +46,7 @@ % \def\font_preloads_reset_nullfont % this is needed because some macro packages (tikz) misuse \nullfont % {\dorecurse\plusseven{\fontdimen\recurselevel\nullfont\zeropoint}% keep en eye on this as: % \clf_resetnullfont % in luatex 0.70 this will also do the previous -% \globallet\font_preloads_reset_nullfont\relax} +% \glet\font_preloads_reset_nullfont\relax} \def\font_preload_check_mode {\doifelsemode{lmmath} @@ -122,14 +122,14 @@ \font_preloads_reset \else \font_preloads_reset - \pushmacro\fontstyle + \push_macro_fontstyle \ifcsname\??fontclass\fontclass\s!mm\s!features\endcsname \else \font_preload_default_fonts_mm \fi \ifcsname\??fontclass\fontclass\s!tt\s!features\endcsname \else \font_preload_default_fonts_tt \fi - \popmacro\fontstyle + \pop_macro_fontstyle \font_preloads_reset_checked % reset third, mm and tt \setupbodyfont[\fontstyle]% \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-shp.lua b/Master/texmf-dist/tex/context/base/mkiv/font-shp.lua index 75a12ac821c..d5c194c858e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-shp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-shp.lua @@ -12,6 +12,7 @@ local formatters = string.formatters local otf = fonts.handlers.otf local afm = fonts.handlers.afm +local pfb = fonts.handlers.pfb local hashes = fonts.hashes local identifiers = hashes.identifiers @@ -39,7 +40,8 @@ local function packoutlines(data,makesequence) return end if makesequence then - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local glyph = glyphs[index] local segments = glyph.segments if segments then @@ -48,6 +50,7 @@ local function packoutlines(data,makesequence) for i=1,#segments do local segment = segments[i] local nofsegment = #segment + -- why last first ... needs documenting nofsequence = nofsequence + 1 sequence[nofsequence] = segment[nofsegment] for i=1,nofsegment-1 do @@ -64,7 +67,8 @@ local function packoutlines(data,makesequence) local common = { } local reverse = { } local last = 0 - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local segments = glyphs[index].segments if segments then for i=1,#segments do @@ -73,7 +77,8 @@ local function packoutlines(data,makesequence) end end end - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local segments = glyphs[index].segments if segments then for i=1,#segments do @@ -114,7 +119,8 @@ local function unpackoutlines(data) if not glyphs then return end - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local segments = glyphs[index].segments if segments then for i=1,#segments do @@ -131,7 +137,7 @@ end -- todo: loaders per format local readers = otf.readers -local cleanname = readers.helpers.cleanname +local cleanname = otf.readers.helpers.cleanname local function makehash(filename,sub,instance) local name = cleanname(file.basename(filename)) @@ -157,7 +163,7 @@ local function loadoutlines(cache,filename,sub,instance) local hash = makehash(filename,sub,instance) data = containers.read(cache,hash) if not data or data.time ~= time or data.size ~= size then - data = readers.loadshapes(filename,sub,instance) + data = otf.readers.loadshapes(filename,sub,instance) if data then data.size = size data.format = data.format or (kind == "otf" and "opentype") or "truetype" @@ -204,19 +210,16 @@ local function loadstreams(cache,filename,sub,instance) local size = attr and attr.size or 0 local time = attr and attr.modification or 0 local sub = tonumber(sub) - - -- fonts.formats - if size > 0 and (kind == "otf" or kind == "ttf" or kind == "tcc") then local hash = makehash(filename,sub,instance) data = containers.read(cache,hash) if not data or data.time ~= time or data.size ~= size then - data = readers.loadshapes(filename,sub,instance,true) + data = otf.readers.loadshapes(filename,sub,instance,true) if data then local glyphs = data.glyphs local streams = { } if glyphs then - for i=0,#glyphs do + for i=0,#glyphs-1 do streams[i] = glyphs[i].stream or "" end end @@ -229,13 +232,68 @@ local function loadstreams(cache,filename,sub,instance) data = containers.read(cache,hash) -- frees old mem end end + elseif size > 0 and (kind == "pfb") then + local hash = makehash(filename,sub,instance) + data = containers.read(cache,hash) + if not data or data.time ~= time or data.size ~= size then + local names, encoding, streams, metadata = pfb.loadvector(filename,false,true) + if streams then + local fontbbox = metadata.fontbbox or { 0, 0, 0, 0 } + for i=0,#streams do + streams[i] = streams[i].stream or "\14" + end + data = { + filename = filename, + size = size, + time = time, + format = "type1", + streams = streams, + fontheader = { + fontversion = metadata.version, + units = 1000, -- can this be different? + xmin = fontbbox[1], + ymin = fontbbox[2], + xmax = fontbbox[3], + ymax = fontbbox[4], + }, + horizontalheader = { + ascender = 0, + descender = 0, + }, + maximumprofile = { + nofglyphs = #streams + 1, + }, + names = { + copyright = metadata.copyright, + family = metadata.familyname, + fullname = metadata.fullname, + fontname = metadata.fontname, + subfamily = metadata.subfamilyname, + trademark = metadata.trademark, + notice = metadata.notice, + version = metadata.version, + }, + cffinfo = { + familyname = metadata.familyname, + fullname = metadata.fullname, + italicangle = metadata.italicangle, + monospaced = metadata.isfixedpitch and true or false, + underlineposition = metadata.underlineposition, + underlinethickness = metadata.underlinethickness, + weight = metadata.weight, + }, + } + containers.write(cache,hash,data) + data = containers.read(cache,hash) -- frees old mem + end + end else data = { filename = filename, size = 0, time = time, format = "unknown", - glyphs = { } + streams = { } } end return data @@ -265,7 +323,15 @@ hashes.shapes = table.setmetatableindex(function(t,k) end end) -local function loadstreamdata(fontdata,streams) +local function getstreamhash(fontid) + local fontdata = identifiers[fontid] + if fontdata then + local properties = fontdata.properties + return makehash(properties.filename,fontdata.subindex,properties.instance) + end +end + +local function loadstreamdata(fontdata) local properties = fontdata.properties local filename = properties.filename local subindex = fontdata.subindex @@ -289,12 +355,19 @@ end) otf.loadoutlinedata = loadoutlinedata -- not public otf.loadstreamdata = loadstreamdata -- not public otf.loadshapes = loadshapes +otf.getstreamhash = getstreamhash -- not public, might move to other namespace --- experimental code, for me only ... unsupported +-- experimental code, for me only ... unsupported (todo: use %N) -local f_c = string.formatters["%F %F %F %F %F %F c"] -local f_l = string.formatters["%F %F l"] -local f_m = string.formatters["%F %F m"] +local f_c = formatters["%F %F %F %F %F %F c"] +local f_l = formatters["%F %F l"] +local f_m = formatters["%F %F m"] + +directives.register("pdf.stripzeros",function() + f_c = formatters["%N %N %N %N %N %N c"] + f_l = formatters["%N %N l"] + f_m = formatters["%N %N m"] +end) local function segmentstopdf(segments,factor,bt,et) local t = { } @@ -316,9 +389,12 @@ local function segmentstopdf(segments,factor,bt,et) elseif w == "q" then local p = segments[i-1] local n = #p - local l_x, l_y = factor*p[n-2], factor*p[n-1] - local m_x, m_y = factor*s[1], factor*s[2] - local r_x, r_y = factor*s[3], factor*s[4] + local l_x = factor*p[n-2] + local l_y = factor*p[n-1] + local m_x = factor*s[1] + local m_y = factor*s[2] + local r_x = factor*s[3] + local r_y = factor*s[4] m = m + 1 t[m] = f_c ( l_x + 2/3 * (m_x-l_x), l_y + 2/3 * (m_y-l_y), @@ -338,7 +414,7 @@ local function segmentstopdf(segments,factor,bt,et) end end -local function addvariableshapes(tfmdata,key,value) +local function initialize(tfmdata,key,value) if value then local shapes = otf.loadoutlinedata(tfmdata) if not shapes then @@ -354,7 +430,9 @@ local function addvariableshapes(tfmdata,key,value) local factor = hfactor / 65536 local getactualtext = otf.getactualtext for unicode, char in next, characters do - if not char.commands then + if char.commands then + -- can't happen as we're doing this before other messing around + else local shape = glyphs[char.index] if shape then local segments = shape.segments @@ -375,12 +453,12 @@ otf.features.register { name = "variableshapes", -- enforced for now description = "variable shapes", manipulators = { - base = addvariableshapes, - node = addvariableshapes, + base = initialize, + node = initialize, } } --- In the end it is easier to just provide the new charstring (cff) and points (ttdf). First +-- In the end it is easier to just provide the new charstring (cff) and points (ttf). First -- of all we already have the right information so there is no need to patch the already complex -- backend code (we only need to make sure the cff is valid). Also, I prototyped support for -- these fonts using (converted to) normal postscript shapes, a functionality that was already diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua b/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua index 8967d88e60b..002f9df131f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-sol.lua @@ -54,8 +54,6 @@ local settings_to_hash = utilities.parsers.settings_to_hash local tasks = nodes.tasks local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getfield = nuts.getfield local getnext = nuts.getnext @@ -65,8 +63,10 @@ local getattr = nuts.getattr local getfont = nuts.getfont local getsubtype = nuts.getsubtype local getlist = nuts.getlist -local getdir = nuts.getdir +local getdirection = nuts.getdirection local getwidth = nuts.getwidth +local getdata = nuts.getdata + local getboxglue = nuts.getboxglue local setattr = nuts.setattr @@ -78,13 +78,15 @@ local find_node_tail = nuts.tail local flush_node = nuts.flush_node local flush_node_list = nuts.flush_list local copy_node_list = nuts.copy_list -local traverse_nodes = nuts.traverse -local traverse_ids = nuts.traverse_id local hpack_nodes = nuts.hpack local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local protect_glyphs = nuts.protect_glyphs +local nextnode = nuts.traversers.next +local nexthlist = nuts.traversers.hlist +local nextwhatsit = nuts.traversers.whatsit + local repack_hlist = nuts.repackhlist local nodes_to_utf = nodes.listtoutf @@ -108,13 +110,15 @@ local whatsit_code = nodecodes.whatsit local fontkern_code = kerncodes.fontkern -local userdefined_code = whatsitcodes.userdefined +local userdefinedwhatsit_code = whatsitcodes.userdefined + +local nodeproperties = nodes.properties.data local nodepool = nuts.pool local usernodeids = nodepool.userids -local new_textdir = nodepool.textdir -local new_usernumber = nodepool.usernumber +local new_direction = nodepool.direction +local new_usernode = nodepool.usernode local new_glue = nodepool.glue local new_leftskip = nodepool.leftskip @@ -237,7 +241,6 @@ local function convert(featuresets,name,list) fs = contextsetups[feature] fn = fs and fs.number end --- inspect(fs) if fn then nofnumbers = nofnumbers + 1 numbers[nofnumbers] = fn @@ -344,20 +347,23 @@ directives.register("builders.paragraphs.solutions.splitters.encapsulate", funct encapsulate = v end) -function splitters.split(head) - -- quite fast - head = tonut(head) - local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 - cache, max_less, max_more = { }, 0, 0 +function splitters.split(head) -- best also pass the direction + local current = head + local r2l = false + local start = nil + local stop = nil + local attribute = 0 + cache = { } + max_less = 0 + max_more = 0 local function flush() -- we can move this local font = getfont(start) local last = getnext(stop) --- local list = last and copy_node_list(start,last) or copy_node_list(start) - local list = last and copy_node_list(start,stop) or copy_node_list(start) - local n = #cache + 1 + local list = last and copy_node_list(start,last) or copy_node_list(start) + local n = #cache + 1 if encapsulate then - local user_one = new_usernumber(splitter_one,n) - local user_two = new_usernumber(splitter_two,n) + local user_one = new_usernode(splitter_one,n) + local user_two = new_usernode(splitter_two,n) head, start = insert_node_before(head,start,user_one) insert_node_after(head,stop,user_two) else @@ -371,9 +377,8 @@ function splitters.split(head) end end end - local r2l = rlmode == "TRT" or rlmode == "+TRT" if r2l then - local dirnode = new_textdir("+TRT") + local dirnode = new_direction(righttoleft) -- brrr, we don't pop ... to be done (when used at all) setlink(dirnode,list) list = dirnode end @@ -393,7 +398,7 @@ function splitters.split(head) local m = #solution.more if l > max_less then max_less = l end if m > max_more then max_more = m end - start, stop, done = nil, nil, true + start, stop = nil, nil end while current do -- also ischar local next = getnext(current) @@ -422,11 +427,19 @@ function splitters.split(head) else start, stop = nil, nil end - elseif id == dir_code or id == localpar_code then + elseif id == dir_code then + -- not tested (to be done by idris when font is ready) if start then flush() end - rlmode = getdir(current) + local direction, pop = getdirection(current) + r2l = not pop and direction == righttoleft + elseif id == localpar_code and getsubtype(current) == 0 then + if start then + flush() -- very unlikely as this starts a paragraph + end + local direction = getdirection(current) + r2l = direction == righttoleft or direction == "TRT" -- for old times sake else if start then flush() @@ -438,31 +451,37 @@ function splitters.split(head) flush() end nofparagraphs = nofparagraphs + 1 - nofwords = nofwords + #cache - return tonode(head), done + nofwords = nofwords + #cache + return head end local function collect_words(list) -- can be made faster for attributes - local words, w, word = { }, 0, nil + local words = { } + local w = 0 + local word = nil if encapsulate then - for current in traverse_ids(whatsit_code,list) do - if getsubtype(current) == userdefined_code then -- hm - local user_id = getfield(current,"user_id") - if user_id == splitter_one then - word = { getfield(current,"value"), current, current } - w = w + 1 - words[w] = word - elseif user_id == splitter_two then - if word then - word[3] = current - else - -- something is wrong + for current, subtype in nextwhatsit, list do + if subtype == userdefinedwhatsit_code then -- hm + local p = nodeproperties[current] + if p then + local user_id = p.id + if user_id == splitter_one then + word = { p.data, current, current } + w = w + 1 + words[w] = word + elseif user_id == splitter_two then + if word then + word[3] = current + else + -- something is wrong + end end end end end else - local current, first, last, index = list, nil, nil, nil + local first, last, index + local current = list while current do -- todo: disc and kern local id = getid(current) @@ -527,7 +546,9 @@ local function collect_words(list) -- can be made faster for attributes if trace_split then for i=1,#words do local w = words[i] - local n, f, l = w[1], w[2], w[3] + local n = w[1] + local f = w[2] + local l = w[3] local c = cache[n] if c then report_splitters("found %4i: word %a, cached %a",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true)) @@ -584,21 +605,20 @@ local function doit(word,list,best,width,badness,line,set,listdir) noftries = noftries + 1 local first = copy_node_list(original) if not trace_colors then - for n in traverse_nodes(first) do -- maybe fast force so no attr needed + for n in nextnode, first do -- maybe fast force so no attr needed setattr(n,0,featurenumber) -- this forces dynamics end elseif set == "less" then - for n in traverse_nodes(first) do + for n in nextnode, first do setnodecolor(n,"font:isol") -- yellow setattr(n,0,featurenumber) end else - for n in traverse_nodes(first) do + for n in nextnode, first do setnodecolor(n,"font:medi") -- green setattr(n,0,featurenumber) end end -first = tonode(first) local font = found.font local setdynamics = setfontdynamics[font] if setdynamics then @@ -610,7 +630,6 @@ first = tonode(first) report_solutions("fatal error, no dynamics for font %a",font) end first = inject_kerns(first) -first = tonut(first) if getid(first) == whatsit_code then local temp = first first = getnext(first) @@ -753,19 +772,19 @@ function splitters.optimize(head) if trace_optimize then report_optimizers("preroll %a, variant %a, criterium %a, cache size %a",preroll,variant,criterium,nc) end - for current in traverse_ids(hlist_code,tonut(head)) do + for current in nexthlist, head do line = line + 1 - local sign = getfield(current,"glue_sign") - local dir = getdir(current) - local width = getwidth(current) - local list = getlist(current) + local sign = getfield(current,"glue_sign") + local direction = getdirection(current) + local width = getwidth(current) + local list = getlist(current) if not encapsulate and getid(list) == glyph_code then -- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set -- is this assignment ok ? .. needs checking list = insert_node_before(list,list,new_leftskip(0)) -- new_glue(0) setlist(current,list) end - local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node + local temp, badness = repack_hlist(list,width,"exactly",direction) -- it would be nice if the badness was stored in the node if badness > 0 then if sign == 0 then if trace_optimize then @@ -785,7 +804,8 @@ function splitters.optimize(head) set, max = "less", max_less end -- we can keep the best variants - local lastbest, lastbadness = nil, badness + local lastbest = nil + local lastbadness = badness if preroll then local bb, base for i=1,max do @@ -858,7 +878,7 @@ statistics.register("optimizer statistics", function() if nofwords > 0 then local elapsed = statistics.elapsedtime(splitters) local average = noftries/elapsed - return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second", + return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %s seconds used, %s adapted, %0.1f lines per second", nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average) end end) diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi index 2d00c5ec814..8200aa95748 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-sty.mkvi @@ -59,17 +59,17 @@ \newconstant\c_fonts_basics_alternative_style_method \def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command% - {\setvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}% + {\setuvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}% \ifcsname#command\endcsname % no redefinition \else\ifnum\c_fonts_basics_alternative_style_method=\plusone \ifthirdargument - \setuevalue{#command}{\groupedcommand{\expandafter\noexpand\begincsname\??alternativestyle#command\endcsname}{}}% + \setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}% \else - \setuvalue{#command}{\groupedcommand{#variantone}{}}% + \setuvalue{#command}{\triggergroupedcommand{#variantone}}% \fi \else - \setuvalue{#command}{\groupedcommand{#variantone}{}}% + \setuvalue{#command}{\triggergroupedcommand{#variantone}}% \fi\fi} \def\font_helpers_apply_alternative_style @@ -279,17 +279,26 @@ \fi\fi \endcsname{#name}} +% \setvalue{\??styleargument1}#name% +% {\groupedcommand{\begincsname#name\endcsname}{}} + \setvalue{\??styleargument1}#name% - {\groupedcommand{\csname#name\endcsname}{}} + {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname} + +% \setvalue{\??styleargument2}#name% +% {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}} \setvalue{\??styleargument2}#name% - {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}} + {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}} \setvalue{\??styleargument3}#specification% {\doifelseassignment{#specification}\font_styles_assignment\font_styles_direct{#specification}} -\def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}} -\def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}} +% \def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}} +% \def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}} + +\def\font_styles_assignment#specification{\triggergroupedcommand{\font_styles_use_generic{#specification}}} +\def\font_styles_direct #specification{\triggergroupedcommand{\definedfont[#specification]}} % environments diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi index 0e709f161a7..3ff85fb4a84 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-sym.mkvi @@ -167,7 +167,7 @@ \def\font_basics_define_symbolic_font {\definefont[currentsymbolfont][\askedsymbolfont]% \currentsymbolfont - \global\expandafter\let\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall} + \expandafter\glet\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall} \unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}} \unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}} diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua b/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua index 52f425db3bf..dfe32b57b26 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-syn.lua @@ -1172,7 +1172,7 @@ local function analyzefiles(olddata) report_names("scanning path %a for %s files",blobpath,suffix) end, function(blobtype,blobpath,pattern,total,checked,done) blobpath = resolveprefix(blobpath) -- no shortcut - report_names("%s entries found, %s %s files checked, %s okay",total,checked,suffix,done) + report_names("%s %s files checked, %s okay",checked,suffix,done) end) end @@ -2009,7 +2009,8 @@ local lastlookups, lastpattern = { }, "" local function look_them_up(lookups,specification) for key, value in sortedhash(specification) do - local t, n = { }, 0 + local t = { } + local n = 0 if find(value,"*",1,true) then value = topattern(value) for i=1,#lookups do diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua index 0059e6296cc..6e4f8698052 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-tfm.lua @@ -9,6 +9,7 @@ if not modules then modules = { } end modules ['font-tfm'] = { local next, type = next, type local match, format = string.match, string.format local concat, sortedhash = table.concat, table.sortedhash +local idiv = number.idiv local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) local trace_features = false trackers.register("tfm.features", function(v) trace_features = v end) @@ -21,6 +22,7 @@ local setmetatableindex = table.setmetatableindex local fonts = fonts local handlers = fonts.handlers +local helpers = fonts.helpers local readers = fonts.readers local constructors = fonts.constructors local encodings = fonts.encodings @@ -39,6 +41,8 @@ local registertfmfeature = tfmfeatures.register local tfmenhancers = constructors.enhancers.tfm local registertfmenhancer = tfmenhancers.register +local charcommand = helpers.commands.char + constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua fonts.formats.tfm = "type1" -- we need to have at least a value here @@ -114,219 +118,266 @@ local depth = { } -- table.setmetatableindex("number") -- -- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat. +local read_from_tfm, check_tfm do -local function read_from_tfm(specification) - local filename = specification.filename - local size = specification.size - depth[filename] = (depth[filename] or 0) + 1 - if trace_defining then - report_defining("loading tfm file %a at size %s",filename,size) - end - local tfmdata = font.read_tfm(filename,size) -- not cached, fast enough - if tfmdata then - - local features = specification.features and specification.features.normal or { } - local features = constructors.checkedfeatures("tfm",features) - specification.features.normal = features + local tfmreaders = context and tfm.readers + local loadtfmvf = tfmreaders and tfmreaders.loadtfmvf + local loadtfm = font.read_tfm + local loadvf = font.read_vf - -- If reencode returns a new table, we assume that we're doing something - -- special. An 'auto' reencode pickt up its vector from the pfb file. + directives.register("fonts.tfm.builtin",function(v) + loadtfmvf = tfmreaders and tfmreaders.loadtfmvf + if v and loadtfm then + loadtfmvf = false + end + end) - local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification) - if newtfmdata then - tfmdata = newtfmdata + read_from_tfm = function(specification) + local filename = specification.filename + local size = specification.size + depth[filename] = (depth[filename] or 0) + 1 + if trace_defining then + report_defining("loading tfm file %a at size %s",filename,size) + end + local tfmdata -- not cached, fast enough + if loadtfmvf then + tfmdata = loadtfmvf(filename,size) + else + tfmdata = loadtfm(filename,size) end + if tfmdata then - local resources = tfmdata.resources or { } - local properties = tfmdata.properties or { } - local parameters = tfmdata.parameters or { } - local shared = tfmdata.shared or { } - -- - shared.features = features - shared.resources = resources - -- - properties.name = tfmdata.name -- todo: fallback - properties.fontname = tfmdata.fontname -- todo: fallback - properties.psname = tfmdata.psname -- todo: fallback - properties.fullname = tfmdata.fullname -- todo: fallback - properties.filename = specification.filename -- todo: fallback - properties.format = fonts.formats.tfm -- better than nothing - -- - tfmdata.properties = properties - tfmdata.resources = resources - tfmdata.parameters = parameters - tfmdata.shared = shared - -- - shared.rawdata = { resources = resources } - shared.features = features - -- - -- The next branch is only entered when we have a proper encoded file i.e. - -- unicodes and such. It really nakes no sense to do feature juggling when - -- we have no names and unicodes. - -- - if newtfmdata then - -- - -- Some opentype processing assumes these to be present: - -- - if not resources.marks then - resources.marks = { } - end - if not resources.sequences then - resources.sequences = { } - end - if not resources.features then - resources.features = { - gsub = { }, - gpos = { }, - } - end - if not tfmdata.changed then - tfmdata.changed = { } - end - if not tfmdata.descriptions then - tfmdata.descriptions = tfmdata.characters + local features = specification.features and specification.features.normal or { } + local features = constructors.checkedfeatures("tfm",features) + specification.features.normal = features + + -- If reencode returns a new table, we assume that we're doing something + -- special. An 'auto' reencode picks up its vector from the pfb file. + + local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification) + if newtfmdata then + tfmdata = newtfmdata end + + local resources = tfmdata.resources or { } + local properties = tfmdata.properties or { } + local parameters = tfmdata.parameters or { } + local shared = tfmdata.shared or { } -- - -- It might be handy to have this: - -- - otf.readers.addunicodetable(tfmdata) - -- - -- We make a pseudo opentype font, e.g. kerns and ligatures etc: - -- - tfmenhancers.apply(tfmdata,filename) - -- - -- Now user stuff can kick in. - -- - constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) - -- - -- As that can also mess with names and such, we are now ready for finalizing - -- the unicode information. This is a different order that for instance type one - -- (afm) files. First we try to deduce unicodes from already present information. + shared.features = features + shared.resources = resources -- - otf.readers.unifymissing(tfmdata) + properties.name = tfmdata.name -- todo: fallback + properties.fontname = tfmdata.fontname -- todo: fallback + properties.psname = tfmdata.psname -- todo: fallback + properties.fullname = tfmdata.fullname -- todo: fallback + properties.filename = specification.filename -- todo: fallback + properties.format = tfmdata.format or fonts.formats.tfm -- better than nothing + properties.usedbitmap = tfmdata.usedbitmap -- - -- Next we fill in the gaps, based on names from teh agl. Probably not much will - -- happen here. + tfmdata.properties = properties + tfmdata.resources = resources + tfmdata.parameters = parameters + tfmdata.shared = shared -- - fonts.mappings.addtounicode(tfmdata,filename) + shared.rawdata = { resources = resources } + shared.features = features -- - -- The tounicode data is passed to the backend that constructs the vectors for us. + -- The next branch is only entered when we have a proper encoded file i.e. + -- unicodes and such. It really nakes no sense to do feature juggling when + -- we have no names and unicodes. -- - tfmdata.tounicode = 1 - local tounicode = fonts.mappings.tounicode - for unicode, v in next, tfmdata.characters do - local u = v.unicode - if u then - v.tounicode = tounicode(u) + if newtfmdata then + -- + -- Some opentype processing assumes these to be present: + -- + if not resources.marks then + resources.marks = { } + end + if not resources.sequences then + resources.sequences = { } + end + if not resources.features then + resources.features = { + gsub = { }, + gpos = { }, + } + end + if not tfmdata.changed then + tfmdata.changed = { } + end + if not tfmdata.descriptions then + tfmdata.descriptions = tfmdata.characters + end + -- + -- It might be handy to have this: + -- + otf.readers.addunicodetable(tfmdata) + -- + -- We make a pseudo opentype font, e.g. kerns and ligatures etc: + -- + tfmenhancers.apply(tfmdata,filename) + -- + -- Now user stuff can kick in. + -- + constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm) + -- + -- As that can also mess with names and such, we are now ready for finalizing + -- the unicode information. This is a different order that for instance type one + -- (afm) files. First we try to deduce unicodes from already present information. + -- + otf.readers.unifymissing(tfmdata) + -- + -- Next we fill in the gaps, based on names from teh agl. Probably not much will + -- happen here. + -- + fonts.mappings.addtounicode(tfmdata,filename) + -- + -- The tounicode data is passed to the backend that constructs the vectors for us. + -- + tfmdata.tounicode = 1 + local tounicode = fonts.mappings.tounicode + for unicode, v in next, tfmdata.characters do + local u = v.unicode + if u then + v.tounicode = tounicode(u) + end + end + -- + -- However, when we use a bitmap font those vectors can't be constructed because + -- that information is not carried with those fonts (there is no name info, nor + -- proper index info, nor unicodes at that end). So, we provide it ourselves. + -- + if tfmdata.usedbitmap then + tfm.addtounicode(tfmdata) end end -- - -- However, when we use a bitmap font those vectors can't be constructed because - -- that information is not carried with those fonts (there is no name info, nor - -- proper index info, nor unicodes at that end). So, we provide it ourselves. + shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil -- - if tfmdata.usedbitmap then - tfm.addtounicode(tfmdata) + if size < 0 then + size = idiv(65536 * -size,100) end - end - -- - shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil - -- - parameters.factor = 1 -- already scaled - parameters.size = size - parameters.slant = parameters.slant or parameters[1] or 0 - parameters.space = parameters.space or parameters[2] or 0 - parameters.space_stretch = parameters.space_stretch or parameters[3] or 0 - parameters.space_shrink = parameters.space_shrink or parameters[4] or 0 - parameters.x_height = parameters.x_height or parameters[5] or 0 - parameters.quad = parameters.quad or parameters[6] or 0 - parameters.extra_space = parameters.extra_space or parameters[7] or 0 - -- - constructors.enhanceparameters(parameters) -- official copies for us - -- - properties.private = properties.private or tfmdata.private or privateoffset - -- - if newtfmdata then + parameters.factor = 1 -- already scaled + parameters.units = 1000 -- just in case + parameters.size = size + parameters.slant = parameters.slant or parameters[1] or 0 + parameters.space = parameters.space or parameters[2] or 0 + parameters.space_stretch = parameters.space_stretch or parameters[3] or 0 + parameters.space_shrink = parameters.space_shrink or parameters[4] or 0 + parameters.x_height = parameters.x_height or parameters[5] or 0 + parameters.quad = parameters.quad or parameters[6] or 0 + parameters.extra_space = parameters.extra_space or parameters[7] or 0 -- - -- We do nothing as we assume flat tfm files. It would become real messy - -- otherwise and I don't have something for testing on my system anyway. + constructors.enhanceparameters(parameters) -- official copies for us -- - elseif constructors.resolvevirtualtoo then - fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here - local vfname = findbinfile(specification.name, 'ovf') - if vfname and vfname ~= "" then - local vfdata = font.read_vf(vfname,size) -- not cached, fast enough - if vfdata then - local chars = tfmdata.characters - for k,v in next, vfdata.characters do - chars[k].commands = v.commands + properties.private = properties.private or tfmdata.private or privateoffset + -- + if newtfmdata then + -- + -- We do nothing as we assume flat tfm files. It would become real messy + -- otherwise and I don't have something for testing on my system anyway. + -- + elseif loadtfmvf then + -- already loaded + local fonts = tfmdata.fonts + if fonts then + for i=1,#fonts do + local font = fonts[i] + local id = font.id + if not id then + local name = font.name + local size = font.size + if name and size then + local data, id = constructors.readanddefine(name,size) + if id then + font.id = id + font.name = nil + font.size = nil + end + end + end end - properties.virtualized = true - tfmdata.fonts = vfdata.fonts - tfmdata.type = "virtual" -- else nested calls with cummulative scaling - local fontlist = vfdata.fonts - local name = file.nameonly(filename) - for i=1,#fontlist do - local n = fontlist[i].name - local s = fontlist[i].size - local d = depth[filename] - s = constructors.scaled(s,vfdata.designsize) - if d > tfm.maxnestingdepth then - report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) - fontlist[i] = { id = 0 } - elseif (d > 1) and (s > tfm.maxnestingsize) then - report_defining("virtual font %a exceeds size %s",n,s) - fontlist[i] = { id = 0 } - else - local t, id = fonts.constructors.readanddefine(n,s) - fontlist[i] = { id = id } + end + elseif constructors.resolvevirtualtoo then + fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here + local vfname = findbinfile(specification.name, 'ovf') + if vfname and vfname ~= "" then + local vfdata = loadvf(vfname,size) + if vfdata then + local chars = tfmdata.characters + for k,v in next, vfdata.characters do + chars[k].commands = v.commands + end + properties.virtualized = true + tfmdata.fonts = vfdata.fonts + tfmdata.type = "virtual" -- else nested calls with cummulative scaling + local fontlist = vfdata.fonts + local name = file.nameonly(filename) + for i=1,#fontlist do + local n = fontlist[i].name + local s = fontlist[i].size + local d = depth[filename] + s = constructors.scaled(s,vfdata.designsize) + if d > tfm.maxnestingdepth then + report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth) + fontlist[i] = { id = 0 } + elseif (d > 1) and (s > tfm.maxnestingsize) then + report_defining("virtual font %a exceeds size %s",n,s) + fontlist[i] = { id = 0 } + else + local t, id = constructors.readanddefine(n,s) + fontlist[i] = { id = id } + end end end end end + -- + -- This is for old times sake (and context specific) so we comment it. It has + -- to do with encoding prefixes (a context naming that was later adopted by + -- the lm/gyre project) + -- + -- if not features.encoding then + -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") + -- if filename and encoding and encodings.known and encodings.known[encoding] then + -- features.encoding = encoding + -- end + -- end + -- + -- Some afterthoughts: + -- + properties.haskerns = true + properties.hasligatures = true + properties.hasitalics = true + resources.unicodes = { } + resources.lookuptags = { } + -- + depth[filename] = depth[filename] - 1 + -- + return tfmdata + else + depth[filename] = depth[filename] - 1 end - -- - -- This is for old times sake (and context specific) so we comment it. It has - -- to do with encoding prefixes (a context naming that was later adopted by - -- the lm/gyre project) - -- - -- if not features.encoding then - -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") - -- if filename and encoding and encodings.known and encodings.known[encoding] then - -- features.encoding = encoding - -- end - -- end - -- - -- Some afterthoughts: - -- - properties.haskerns = true - properties.hasligatures = true - resources.unicodes = { } - resources.lookuptags = { } - -- - depth[filename] = depth[filename] - 1 - -- - return tfmdata - else - depth[filename] = depth[filename] - 1 end -end -local function check_tfm(specification,fullname) -- we could split up like afm/otf - local foundname = findbinfile(fullname, 'tfm') or "" - if foundname == "" then - foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context - end - if foundname == "" then - foundname = fonts.names.getfilename(fullname,"tfm") or "" - end - if foundname ~= "" then - specification.filename = foundname - specification.format = "ofm" - return read_from_tfm(specification) - elseif trace_defining then - report_defining("loading tfm with name %a fails",specification.name) + check_tfm = function(specification,fullname) -- we could split up like afm/otf + local foundname = findbinfile(fullname, 'tfm') or "" + if foundname == "" then + foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context + end + if foundname == "" then + foundname = fonts.names.getfilename(fullname,"tfm") or "" + end + if foundname ~= "" then + specification.filename = foundname + specification.format = "ofm" + return read_from_tfm(specification) + elseif trace_defining then + report_defining("loading tfm with name %a fails",specification.name) + end end + end readers.check_tfm = check_tfm @@ -409,7 +460,7 @@ do local vector = false if type(pfbfile) == "string" then - local pfb = fonts.constructors.handlers.pfb + local pfb = constructors.handlers.pfb if pfb and pfb.loadvector then local v, e = pfb.loadvector(pfbfile) if v then @@ -438,7 +489,7 @@ do local originals = tfmdata.characters local indices = { } local parentfont = { "font", 1 } - local private = tfmdata or fonts.constructors.privateoffset + local private = tfmdata.privateoffset or constructors.privateoffset local reported = encdone[tfmfile][encfile] -- create characters table @@ -463,9 +514,9 @@ do indices[index] = unicode original.name = name -- so one can lookup weird names if backmap then - original.index = backmap[name] + original.index = backmap[name] else -- probably bitmap - original.commands = { parentfont, { "char", index } } + original.commands = { parentfont, charcommand[index] } -- or "slot" original.oindex = index end done[name] = true @@ -512,6 +563,7 @@ do tfmdata.psname = file.nameonly(pfbfile or tfmdata.name) tfmdata.filename = pfbfile tfmdata.encodingbytes = 2 + -- tfmdata.format = bitmap and "type3" or "type1" tfmdata.format = "type1" tfmdata.tounicode = 1 tfmdata.embedding = "subset" @@ -548,24 +600,18 @@ end end ]] - local flushstreamobject = lpdf and lpdf.flushstreamobject - local setfontattributes = pdf.setfontattributes + local flushstreamobject = lpdf and lpdf.flushstreamobject -- context + local setfontattributes = lpdf and lpdf.setfontattributes -- context - if flushstreamobject then - -- we're in context - else + if not flushstreamobject then flushstreamobject = function(data) - return pdf.obj { - immediate = true, - type = "stream", - string = data, - } + return pdf.obj { immediate = true, type = "stream", string = data } -- generic end end if not setfontattributes then setfontattributes = function(id,data) - print(format("your luatex is too old so no tounicode bitmap font%i",id)) + return pdf.setfontattributes(id,data) -- generic end end @@ -593,7 +639,7 @@ end -- Now we implement the regular features handlers. We need to convert the -- tfm specific structures to opentype structures. In basemode they are --- converted back so that is a bti of a waste but it's fast enough. +-- converted back so that is a bit of a waste but it's fast enough. do diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv b/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv index c51ba78fc23..205ca5ca02d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/font-tra.mkiv @@ -188,7 +188,7 @@ % \showotfstepmessages\recurselevel % \blank % \startlinecorrection -% \dontleavehmode\bgroup\resetallattributes\pardir TLT\textdir TLT\relax\tttf\recurselevel: \showotfstepchars\recurselevel\egroup +% \dontleavehmode\bgroup\resetallattributes\lefttoright\tttf\recurselevel: \showotfstepchars\recurselevel\egroup % \stoplinecorrection % \blank % \startlinecorrection diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua b/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua index df08787f9a8..d2fe0917c53 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-ttf.lua @@ -35,26 +35,53 @@ if not modules then modules = { } end modules ['font-ttf'] = { local next, type, unpack = next, type, unpack local band, rshift = bit32.band, bit32.rshift local sqrt, round = math.sqrt, math.round -local char = string.char +local char, rep = string.char, string.rep local concat = table.concat +local idiv = number.idiv +local setmetatableindex = table.setmetatableindex -local report = logs.reporter("otf reader","ttf") +local report = logs.reporter("otf reader","ttf") -local trace_deltas = false +local trace_deltas = false -local readers = fonts.handlers.otf.readers -local streamreader = readers.streamreader +local readers = fonts.handlers.otf.readers +local streamreader = readers.streamreader -local setposition = streamreader.setposition -local getposition = streamreader.getposition -local skipbytes = streamreader.skip -local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer -local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer -local readchar = streamreader.readinteger1 -- 8-bit signed integer -local readshort = streamreader.readinteger2 -- 16-bit signed integer -local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) -local readinteger = streamreader.readinteger1 +local setposition = streamreader.setposition +local getposition = streamreader.getposition +local skipbytes = streamreader.skip +local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer +local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer +local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readchar = streamreader.readinteger1 -- 8-bit signed integer +local readshort = streamreader.readinteger2 -- 16-bit signed integer +local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) +local readinteger = streamreader.readinteger1 +local readcardinaltable = streamreader.readcardinaltable +local readintegertable = streamreader.readintegertable + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + setposition = streamreader.setposition + getposition = streamreader.getposition + skipbytes = streamreader.skip + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readulong = streamreader.readcardinal4 + readchar = streamreader.readinteger1 + readshort = streamreader.readinteger2 + read2dot14 = streamreader.read2dot14 + readinteger = streamreader.readinteger1 + readcardinaltable = streamreader.readcardinaltable + readintegertable = streamreader.readintegertable + +end) + +local short = 2 +local ushort = 2 +local ulong = 4 local helpers = readers.helpers local gotodatatable = helpers.gotodatatable @@ -90,22 +117,41 @@ local function mergecomposites(glyphs,shapes) local yscale = matrix[4] local xoffset = matrix[5] local yoffset = matrix[6] - for i=1,#subpoints do - local p = subpoints[i] - local x = p[1] - local y = p[2] - nofpoints = nofpoints + 1 - points[nofpoints] = { - xscale * x + xrotate * y + xoffset, - yscale * y + yrotate * x + yoffset, - p[3] - } + local count = #subpoints + if xscale == 1 and yscale == 1 and xrotate == 0 and yrotate == 0 then + for i=1,count do + local p = subpoints[i] + nofpoints = nofpoints + 1 + points[nofpoints] = { + p[1] + xoffset, + p[2] + yoffset, + p[3] + } + end + else + for i=1,count do + local p = subpoints[i] + local x = p[1] + local y = p[2] + nofpoints = nofpoints + 1 + points[nofpoints] = { + xscale * x + xrotate * y + xoffset, + yscale * y + yrotate * x + yoffset, + p[3] + } + end end - for i=1,#subcontours do + local subcount = #subcontours + if subcount == 1 then nofcontours = nofcontours + 1 - contours[nofcontours] = offset + subcontours[i] + contours[nofcontours] = offset + subcontours[1] + else + for i=1,#subcontours do + nofcontours = nofcontours + 1 + contours[nofcontours] = offset + subcontours[i] + end end - offset = offset + #subpoints + offset = offset + count else report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) end @@ -116,7 +162,8 @@ local function mergecomposites(glyphs,shapes) return contours, points end - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local shape = shapes[index] if shape then local components = shape.components @@ -128,7 +175,7 @@ local function mergecomposites(glyphs,shapes) end -local function readnothing(f,nofcontours) +local function readnothing(f) return { type = "nothing", } @@ -259,7 +306,8 @@ end local quadratic = false local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox overhead - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local shape = shapes[index] if shape then local glyph = glyphs[index] @@ -271,7 +319,8 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox local nofsegments = 0 glyph.segments = segments if nofcontours > 0 then - local px, py = 0, 0 -- we could use these in calculations which saves a copy + local px = 0 + local py = 0 local first = 1 for i=1,nofcontours do local last = contours[i] @@ -299,15 +348,20 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox end control_pt = first_pt end - local x, y = first_pt[1], first_pt[2] + local x = first_pt[1] + local y = first_pt[2] if not done then - xmin, ymin, xmax, ymax = x, y, x, y + xmin = x + ymin = y + xmax = x + ymax = y done = true end nofsegments = nofsegments + 1 segments[nofsegments] = { x, y, "m" } -- "moveto" if not quadratic then - px, py = x, y + px = x + py = y end local previous_pt = first_pt for i=first,last do @@ -327,8 +381,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox control_pt = current_pt end elseif current_on then - local x1, y1 = control_pt[1], control_pt[2] - local x2, y2 = current_pt[1], current_pt[2] + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = current_pt[1] + local y2 = current_pt[2] nofsegments = nofsegments + 1 if quadratic then segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" @@ -338,8 +394,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox end control_pt = false else - local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2 - local x1, y1 = control_pt[1], control_pt[2] + local x2 = (previous_pt[1]+current_pt[1])/2 + local y2 = (previous_pt[2]+current_pt[2])/2 + local x1 = control_pt[1] + local y1 = control_pt[2] nofsegments = nofsegments + 1 if quadratic then segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" @@ -355,14 +413,17 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox -- we're already done, probably a simple curve else nofsegments = nofsegments + 1 - local x2, y2 = first_pt[1], first_pt[2] + local x2 = first_pt[1] + local y2 = first_pt[2] if not control_pt then segments[nofsegments] = { x2, y2, "l" } -- "lineto" elseif quadratic then - local x1, y1 = control_pt[1], control_pt[2] + local x1 = control_pt[1] + local y1 = control_pt[2] segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto" else - local x1, y1 = control_pt[1], control_pt[2] + local x1 = control_pt[1] + local y1 = control_pt[2] x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2) segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto" -- px, py = x2, y2 @@ -379,7 +440,8 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox end local function contours2outlines_shaped(glyphs,shapes,keepcurve) - for index=1,#glyphs do +-- for index=1,#glyphs do + for index=0,#glyphs-1 do local shape = shapes[index] if shape then local glyph = glyphs[index] @@ -425,7 +487,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) end control_pt = first_pt end - local x, y = first_pt[1], first_pt[2] + local x = first_pt[1] + local y = first_pt[2] if not done then xmin, ymin, xmax, ymax = x, y, x, y done = true @@ -438,7 +501,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) segments[nofsegments] = { x, y, "m" } -- "moveto" end if not quadratic then - px, py = x, y + px = x + py = y end local previous_pt = first_pt for i=first,last do @@ -448,7 +512,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) if previous_on then if current_on then -- both normal points - local x, y = current_pt[1], current_pt[2] + local x = current_pt[1] + local y = current_pt[2] if x < xmin then xmin = x elseif x > xmax then xmax = x end if y < ymin then ymin = y elseif y > ymax then ymax = y end if keepcurve then @@ -456,14 +521,17 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) segments[nofsegments] = { x, y, "l" } -- "lineto" end if not quadratic then - px, py = x, y + px = x + py = y end else control_pt = current_pt end elseif current_on then - local x1, y1 = control_pt[1], control_pt[2] - local x2, y2 = current_pt[1], current_pt[2] + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = current_pt[1] + local y2 = current_pt[2] if quadratic then if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end @@ -486,8 +554,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) end control_pt = false else - local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2 - local x1, y1 = control_pt[1], control_pt[2] + local x2 = (previous_pt[1]+current_pt[1])/2 + local y2 = (previous_pt[2]+current_pt[2])/2 + local x1 = control_pt[1] + local y1 = control_pt[2] if quadratic then if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end @@ -520,8 +590,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve) segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto" end else - local x1, y1 = control_pt[1], control_pt[2] - local x2, y2 = first_pt[1], first_pt[2] + local x1 = control_pt[1] + local y1 = control_pt[2] + local x2 = first_pt[1] + local y2 = first_pt[2] if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end if quadratic then @@ -558,8 +630,13 @@ end local c_zero = char(0) local s_zero = char(0,0) +-- local shorthash = setmetatableindex(function(t,k) +-- t[k] = char(band(rshift(k,8),0xFF),band(k,0xFF)) return t[k] +-- end) + local function toushort(n) return char(band(rshift(n,8),0xFF),band(n,0xFF)) + -- return shorthash[n] end local function toshort(n) @@ -567,125 +644,152 @@ local function toshort(n) n = n + 0x10000 end return char(band(rshift(n,8),0xFF),band(n,0xFF)) + -- return shorthash[n] end -- todo: we can reuse result, xpoints and ypoints +local chars = setmetatableindex(function(t,k) + for i=0,255 do local v = char(i) t[i] = v end return t[k] +end) + local function repackpoints(glyphs,shapes) local noboundingbox = { 0, 0, 0, 0 } local result = { } -- reused - for index=1,#glyphs do + local xpoints = { } -- reused + local ypoints = { } -- reused + for index=0,#glyphs-1 do local shape = shapes[index] if shape then local r = 0 local glyph = glyphs[index] - if false then -- shape.type == "composite" - -- we merged them - else - local contours = shape.contours - local nofcontours = contours and #contours or 0 - local boundingbox = glyph.boundingbox or noboundingbox - r = r + 1 result[r] = toshort(nofcontours) - r = r + 1 result[r] = toshort(boundingbox[1]) -- xmin - r = r + 1 result[r] = toshort(boundingbox[2]) -- ymin - r = r + 1 result[r] = toshort(boundingbox[3]) -- xmax - r = r + 1 result[r] = toshort(boundingbox[4]) -- ymax - if nofcontours > 0 then - for i=1,nofcontours do - r = r + 1 result[r] = toshort(contours[i]-1) - end - r = r + 1 result[r] = s_zero -- no instructions - local points = shape.points - local currentx = 0 - local currenty = 0 - local xpoints = { } - local ypoints = { } - local x = 0 - local y = 0 - local lastflag = nil - local nofflags = 0 - for i=1,#points do - local pt = points[i] - local px = pt[1] - local py = pt[2] - local fl = pt[3] and 0x01 or 0x00 - if px == currentx then - fl = fl + 0x10 + local contours = shape.contours + local nofcontours = contours and #contours or 0 + local boundingbox = glyph.boundingbox or noboundingbox + r = r + 1 result[r] = toshort(nofcontours) + r = r + 1 result[r] = toshort(boundingbox[1]) -- xmin + r = r + 1 result[r] = toshort(boundingbox[2]) -- ymin + r = r + 1 result[r] = toshort(boundingbox[3]) -- xmax + r = r + 1 result[r] = toshort(boundingbox[4]) -- ymax + if nofcontours > 0 then + for i=1,nofcontours do + r = r + 1 result[r] = toshort(contours[i]-1) + end + r = r + 1 result[r] = s_zero -- no instructions + local points = shape.points + local currentx = 0 + local currenty = 0 + -- local xpoints = { } + -- local ypoints = { } + local x = 0 + local y = 0 + local lastflag = nil + local nofflags = 0 + for i=1,#points do + local pt = points[i] + local px = pt[1] + local py = pt[2] + local fl = pt[3] and 0x01 or 0x00 + if px == currentx then + fl = fl + 0x10 + else + local dx = round(px - currentx) + x = x + 1 + if dx < -255 or dx > 255 then + xpoints[x] = toshort(dx) + elseif dx < 0 then + fl = fl + 0x02 + -- xpoints[x] = char(-dx) + xpoints[x] = chars[-dx] + elseif dx > 0 then + fl = fl + 0x12 + -- xpoints[x] = char(dx) + xpoints[x] = chars[dx] else - local dx = round(px - currentx) - if dx < -255 or dx > 255 then - x = x + 1 xpoints[x] = toshort(dx) - elseif dx < 0 then - fl = fl + 0x02 - x = x + 1 xpoints[x] = char(-dx) - elseif dx > 0 then - fl = fl + 0x12 - x = x + 1 xpoints[x] = char(dx) - else - fl = fl + 0x02 - x = x + 1 xpoints[x] = c_zero - end + fl = fl + 0x02 + xpoints[x] = c_zero end - if py == currenty then - fl = fl + 0x20 + end + if py == currenty then + fl = fl + 0x20 + else + local dy = round(py - currenty) + y = y + 1 + if dy < -255 or dy > 255 then + ypoints[y] = toshort(dy) + elseif dy < 0 then + fl = fl + 0x04 + -- ypoints[y] = char(-dy) + ypoints[y] = chars[-dy] + elseif dy > 0 then + fl = fl + 0x24 + -- ypoints[y] = char(dy) + ypoints[y] = chars[dy] else - local dy = round(py - currenty) - if dy < -255 or dy > 255 then - y = y + 1 ypoints[y] = toshort(dy) - elseif dy < 0 then - fl = fl + 0x04 - y = y + 1 ypoints[y] = char(-dy) - elseif dy > 0 then - fl = fl + 0x24 - y = y + 1 ypoints[y] = char(dy) - else - fl = fl + 0x04 - y = y + 1 ypoints[y] = c_zero - end - end - currentx = px - currenty = py - if lastflag == fl then - nofflags = nofflags + 1 - else -- if > 255 - if nofflags == 1 then - r = r + 1 result[r] = char(lastflag) - elseif nofflags == 2 then - r = r + 1 result[r] = char(lastflag,lastflag) - elseif nofflags > 2 then - lastflag = lastflag + 0x08 - r = r + 1 result[r] = char(lastflag,nofflags-1) - end - nofflags = 1 - lastflag = fl + fl = fl + 0x04 + ypoints[y] = c_zero end end - if nofflags == 1 then - r = r + 1 result[r] = char(lastflag) - elseif nofflags == 2 then - r = r + 1 result[r] = char(lastflag,lastflag) - elseif nofflags > 2 then - lastflag = lastflag + 0x08 - r = r + 1 result[r] = char(lastflag,nofflags-1) + currentx = px + currenty = py + if lastflag == fl then + nofflags = nofflags + 1 + else -- if > 255 + if nofflags == 1 then + -- r = r + 1 result[r] = char(lastflag) + r = r + 1 result[r] = chars[lastflag] + elseif nofflags == 2 then + r = r + 1 result[r] = char(lastflag,lastflag) + elseif nofflags > 2 then + lastflag = lastflag + 0x08 + r = r + 1 result[r] = char(lastflag,nofflags-1) + end + nofflags = 1 + lastflag = fl end - r = r + 1 result[r] = concat(xpoints) - r = r + 1 result[r] = concat(ypoints) end + if nofflags == 1 then + -- r = r + 1 result[r] = char(lastflag) + r = r + 1 result[r] = chars[lastflag] + elseif nofflags == 2 then + r = r + 1 result[r] = char(lastflag,lastflag) + elseif nofflags > 2 then + lastflag = lastflag + 0x08 + r = r + 1 result[r] = char(lastflag,nofflags-1) + end + -- r = r + 1 result[r] = concat(xpoints) + -- r = r + 1 result[r] = concat(ypoints) + r = r + 1 result[r] = concat(xpoints,"",1,x) + r = r + 1 result[r] = concat(ypoints,"",1,y) end - glyph.stream = concat(result,"",1,r) - else - -- fatal + -- can be helper or delegated to user + local stream = concat(result,"",1,r) + local length = #stream + local padding = idiv(length+3,4) * 4 - length + if padding > 0 then + -- stream = stream .. rep("\0",padding) -- can be a repeater + if padding == 1 then + padding = "\0" + elseif padding == 2 then + padding = "\0\0" + else + padding = "\0\0\0" + end + padding = stream .. padding + end + glyph.stream = stream end end end -- end of converter +local flags = { } + local function readglyph(f,nofcontours) -- read deltas here, saves space - local points = { } - local contours = { } - local instructions = { } - local flags = { } + local points = { } + -- local instructions = { } + local contours = { } -- readintegertable(f,nofcontours,short) for i=1,nofcontours do contours[i] = readshort(f) + 1 end @@ -699,9 +803,15 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space local flag = readbyte(f) flags[i] = flag if band(flag,0x08) ~= 0 then - for j=1,readbyte(f) do + local n = readbyte(f) + if n == 1 then i = i + 1 flags[i] = flag + else + for j=1,n do + i = i + 1 + flags[i] = flag + end end end i = i + 1 @@ -710,16 +820,16 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space -- can be repeated local x = 0 for i=1,nofpoints do - local flag = flags[i] - local short = band(flag,0x02) ~= 0 - local same = band(flag,0x10) ~= 0 - if short then - if same then + local flag = flags[i] + -- local short = band(flag,0x04) ~= 0 + -- local same = band(flag,0x20) ~= 0 + if band(flag,0x02) ~= 0 then + if band(flag,0x10) ~= 0 then x = x + readbyte(f) else x = x - readbyte(f) end - elseif same then + elseif band(flag,0x10) ~= 0 then -- copy else x = x + readshort(f) @@ -728,16 +838,16 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space end local y = 0 for i=1,nofpoints do - local flag = flags[i] - local short = band(flag,0x04) ~= 0 - local same = band(flag,0x20) ~= 0 - if short then - if same then + local flag = flags[i] + -- local short = band(flag,0x04) ~= 0 + -- local same = band(flag,0x20) ~= 0 + if band(flag,0x04) ~= 0 then + if band(flag,0x20) ~= 0 then y = y + readbyte(f) else y = y - readbyte(f) end - elseif same then + elseif band(flag,0x20) ~= 0 then -- copy else y = y + readshort(f) @@ -833,7 +943,7 @@ local function readcomposite(f) if band(flags,0x0100) ~= 0 then instructions = true end - if not band(flags,0x0020) ~= 0 then -- f_more + if band(flags,0x0020) == 0 then -- f_more break end end @@ -858,21 +968,27 @@ function readers.loca(f,fontdata,specification) -- locations are relative to the glypdata table (glyf) local offset = fontdata.tables.glyf.offset local format = fontdata.fontheader.indextolocformat + local profile = fontdata.maximumprofile + local nofglyphs = profile and profile.nofglyphs local locations = { } setposition(f,datatable.offset) if format == 1 then - local nofglyphs = datatable.length/4 - 2 + if not nofglyphs then + nofglyphs = idiv(datatable.length,4) - 1 + end for i=0,nofglyphs do locations[i] = offset + readulong(f) end fontdata.nofglyphs = nofglyphs else - local nofglyphs = datatable.length/2 - 2 + if not nofglyphs then + nofglyphs = idiv(datatable.length,2) - 1 + end for i=0,nofglyphs do locations[i] = offset + readushort(f) * 2 end - fontdata.nofglyphs = nofglyphs end + fontdata.nofglyphs = nofglyphs fontdata.locations = locations end end @@ -888,15 +1004,16 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module local filesize = fontdata.filesize local nothing = { 0, 0, 0, 0 } local shapes = { } - local loadshapes = specification.shapes or specification.instance - for index=0,nofglyphs do + local loadshapes = specification.shapes or specification.instance or specification.streams + for index=0,nofglyphs-1 do local location = locations[index] + local length = locations[index+1] - location if location >= filesize then report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) fontdata.nofglyphs = index - 1 fontdata.badfont = true break - elseif location > 0 then + elseif length > 0 then setposition(f,location) local nofcontours = readshort(f) glyphs[index].boundingbox = { @@ -908,7 +1025,7 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module if not loadshapes then -- save space elseif nofcontours == 0 then - shapes[index] = readnothing(f,nofcontours) + shapes[index] = readnothing(f) elseif nofcontours > 0 then shapes[index] = readglyph(f,nofcontours) else @@ -916,7 +1033,7 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module end else if loadshapes then - shapes[index] = { } + shapes[index] = readnothing(f) end glyphs[index].boundingbox = nothing end @@ -933,7 +1050,13 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module contours2outlines_shaped(glyphs,shapes,specification.shapes) end elseif specification.shapes then - contours2outlines_normal(glyphs,shapes) + if specification.streams then + repackpoints(glyphs,shapes) + else + contours2outlines_normal(glyphs,shapes) + end + elseif specification.streams then + repackpoints(glyphs,shapes) end end end @@ -1234,10 +1357,6 @@ function readers.gvar(f,fontdata,specification,glyphdata,shapedata) end end if shape.type == "glyph" then --- if glyph.name == "u1f31d" then --- if glyph.unicode == 127773 then --- inspect(deltas) --- end applyaxis(glyph,shape,deltas,dowidth) else -- todo: args_are_xy_values mess .. i have to be really bored diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi b/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi index fb60b711cef..8520a5c32c9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/font-var.mkvi @@ -50,6 +50,8 @@ \let\fontsize \defaultfontsize \let\fontface \!!zerocount +\installmacrostack\fontstyle + % we can use an indirect mapping for fontclasses (map string onto numbers) and indeed this % is somewhat more efficient but also makes the code messy ... maybe some day ... diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-vfc.lua b/Master/texmf-dist/tex/context/base/mkiv/font-vfc.lua new file mode 100644 index 00000000000..dfe6b3afc46 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/font-vfc.lua @@ -0,0 +1,123 @@ +if not modules then modules = { } end modules ['font-vfc'] = { + version = 1.001, + comment = "companion to font-ini.mkiv and hand-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local select, type = select, type +local insert = table.insert + +local fonts = fonts +local helpers = fonts.helpers + +local setmetatableindex = table.setmetatableindex +local makeweak = table.makeweak + +-- Helpers dealing with virtual fonts: beware, these are final values so +-- don't change the content of tables gotten this way! + +local push = { "push" } +local pop = { "pop" } +local dummy = { "comment" } + +function helpers.prependcommands(commands,...) + insert(commands,1,push) + for i=select("#",...),1,-1 do + local s = (select(i,...)) + if s then + insert(commands,1,s) + end + end + insert(commands,pop) + return commands +end + +function helpers.appendcommands(commands,...) + insert(commands,1,push) + insert(commands,pop) + for i=1,select("#",...) do + local s = (select(i,...)) + if s then + insert(commands,s) + end + end + return commands +end + +function helpers.prependcommandtable(commands,t) + insert(commands,1,push) + for i=#t,1,-1 do + local s = t[i] + if s then + insert(commands,1,s) + end + end + insert(commands,pop) + return commands +end + +function helpers.appendcommandtable(commands,t) + insert(commands,1,push) + insert(commands,pop) + for i=1,#t do + local s = t[i] + if s then + insert(commands,s) + end + end + return commands +end + +-- todo: maybe weak +-- todo: maybe indirect so that we can't change them + +local char = setmetatableindex(function(t,k) + -- local v = { "char", k } + local v = { "slot", 0, k } + t[k] = v + return v +end) + +local right = setmetatableindex(function(t,k) + local v = { "right", k } + t[k] = v + return v +end) + +local left = setmetatableindex(function(t,k) + local v = { "right", -k } + t[k] = v + return v +end) + +local down = setmetatableindex(function(t,k) + local v = { "down", k } + t[k] = v + return v +end) + +local up = setmetatableindex(function(t,k) + local v = { "down", -k } + t[k] = v + return v +end) + +-- makeweak(char) +-- makeweak(right) +-- makeweak(left) +-- makeweak(up) +-- makeweak(down) + +helpers.commands = utilities.storage.allocate { + char = char, + right = right, + left = left, + down = down, + up = up, + push = push, + pop = pop, + dummy = dummy, +} + diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-vir.lua b/Master/texmf-dist/tex/context/base/mkiv/font-vir.lua index 03ad7fc8551..c3071cac0b6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-vir.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-vir.lua @@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['font-vir'] = { -- -- vf.rule vf.special vf.right vf.push vf.down vf.char vf.node vf.fontid vf.pop vf.image vf.nop -local next = next +local next, setmetatable, getmetatable = next, setmetatable, getmetatable local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -66,11 +66,7 @@ local combinations = { } local combiner = { } local whatever = allocate() local helpers = allocate() -local predefined = allocate { - dummy = { "comment" }, - push = { "push" }, - pop = { "pop" }, -} +local predefined = fonts.helpers.commands methods.variants = variants -- todo .. wrong namespace vf.combinations = combinations @@ -110,8 +106,10 @@ local function combine_assign(g, name, from, to, start, force) if not from then from, to = 0, 0xFF00 end if not to then to = from end if not start then start = from end - local fc, gc = f.characters, g.characters - local fd, gd = f.descriptions, g.descriptions + local fc = f.characters + local gc = g.characters + local fd = f.descriptions + local gd = g.descriptions local hn = #g.fonts+1 g.fonts[hn] = { id = id } -- no need to be sparse for i=from,to do @@ -137,8 +135,10 @@ end local function combine_names(g,name,force) local f, id = constructors.readanddefine(name,g.specification.size) if f and id then - local fc, gc = f.characters, g.characters - local fd, gd = f.descriptions, g.descriptions + local fc = f.characters + local gc = g.characters + local fd = f.descriptions + local gd = g.descriptions g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse local hn = #g.fonts for k, v in next, fc do @@ -153,7 +153,8 @@ local function combine_names(g,name,force) end local combine_feature = function(g,v) - local key, value = v[2], v[3] + local key = v[2] + local value = v[3] if key then if value == nil then value = true diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-web.lua b/Master/texmf-dist/tex/context/base/mkiv/font-web.lua index 452a8f59b67..376b036f2dd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-web.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-web.lua @@ -23,18 +23,30 @@ local streamwriter = readers and readers.streamwriter or utilities.files local readstring = streamreader.readstring local readcardinal2 = streamreader.readcardinal2 local readcardinal4 = streamreader.readcardinal4 +local getsize = streamreader.getsize +local setposition = streamreader.setposition +local getposition = streamreader.getposition local writestring = streamwriter.writestring local writecardinal4 = streamwriter.writecardinal4 local writecardinal2 = streamwriter.writecardinal2 local writebyte = streamwriter.writebyte -local getsize = streamreader.getsize -local setposition = streamreader.setposition -local getposition = streamreader.getposition - local decompress = zlib.decompress +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + readstring = streamreader.readstring + readcardinal2 = streamreader.readcardinal2 + readcardinal4 = streamreader.readcardinal4 + getsize = streamreader.getsize + setposition = streamreader.setposition + getposition = streamreader.getposition + +end) + local infotags = { ["os/2"] = true, ["head"] = true, diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua b/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua deleted file mode 100644 index 494ac00a928..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/font-xtx.lua +++ /dev/null @@ -1,97 +0,0 @@ -if not modules then modules = { } end modules ['luatex-fonts-def'] = { - version = 1.001, - comment = "companion to luatex-*.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if context then - texio.write_nl("fatal error: this module is not for context") - os.exit() -end - -local fonts = fonts - --- A bit of tuning for definitions. - -fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload - --- tricky: we sort of bypass the parser and directly feed all into --- the sub parser - -function fonts.definers.getspecification(str) - return "", str, "", ":", str -end - --- the generic name parser (different from context!) - -local list = { } - -local function issome () list.lookup = 'name' end -- xetex mode prefers name (not in context!) -local function isfile () list.lookup = 'file' end -local function isname () list.lookup = 'name' end -local function thename(s) list.name = s end -local function issub (v) list.sub = v end -local function iscrap (s) list.crap = string.lower(s) end -local function iskey (k,v) list[k] = v end -local function istrue (s) list[s] = true end -local function isfalse(s) list[s] = false end - -local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C - -local spaces = P(" ")^0 -local namespec = (1-S("/:("))^0 -- was: (1-S("/: ("))^0 -local crapspec = spaces * P("/") * (((1-P(":"))^0)/iscrap) * spaces -local filename_1 = P("file:")/isfile * (namespec/thename) -local filename_2 = P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]") -local fontname_1 = P("name:")/isname * (namespec/thename) -local fontname_2 = P(true)/issome * (namespec/thename) -local sometext = (R("az","AZ","09") + S("+-.{}"))^1 -local truevalue = P("+") * spaces * (sometext/istrue) -local falsevalue = P("-") * spaces * (sometext/isfalse) -local keyvalue = (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey -local somevalue = sometext/istrue -local subvalue = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim -local option = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces -local options = P(":") * spaces * (P(";")^0 * option)^0 - -local pattern = (filename_1 + filename_2 + fontname_1 + fontname_2) * subvalue^0 * crapspec^0 * options^0 - -local function colonized(specification) -- xetex mode - list = { } - lpeg.match(pattern,specification.specification) - list.crap = nil -- style not supported, maybe some day - if list.name then - specification.name = list.name - list.name = nil - end - if list.lookup then - specification.lookup = list.lookup - list.lookup = nil - end - if list.sub then - specification.sub = list.sub - list.sub = nil - end - specification.features.normal = fonts.handlers.otf.features.normalize(list) - return specification -end - -fonts.definers.registersplit(":",colonized,"cryptic") -fonts.definers.registersplit("", colonized,"more cryptic") -- catches \font\text=[names] - -function fonts.definers.applypostprocessors(tfmdata) - local postprocessors = tfmdata.postprocessors - if postprocessors then - for i=1,#postprocessors do - local extrahash = postprocessors[i](tfmdata) -- after scaling etc - if type(extrahash) == "string" and extrahash ~= "" then - -- e.g. a reencoding needs this - extrahash = string.gsub(lower(extrahash),"[^a-z]","-") - tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash) - end - end - end - return tfmdata -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/good-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/good-ctx.lua index 00e4ed78d89..82ef25e29de 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/good-ctx.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/good-ctx.lua @@ -29,14 +29,10 @@ local registerotffeature = fonts.handlers.otf.features.register local fontgoodies = fonts.goodies or { } -local glyph_code = nodes.nodecodes.glyph - local nuts = nodes.nuts local tonut = nuts.tonut -local getfont = nuts.getfont -local getchar = nuts.getchar local getattr = nuts.getattr -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph -- colorschemes @@ -100,10 +96,10 @@ local function setcolorscheme(tfmdata,scheme) end end if privatestoo then - local private = fonts.constructors.privateoffset - local descriptions = tfmdata.descriptions + local privateoffset = fonts.constructors.privateoffset + local descriptions = tfmdata.descriptions for unicode, data in next, characters do - if unicode >= private then + if unicode >= privateoffset then if not reverse[unicode] then local d = descriptions[unicode] if d then @@ -128,68 +124,9 @@ local function setcolorscheme(tfmdata,scheme) end local fontproperties = fonts.hashes.properties - local a_colorscheme = attributes.private('colorscheme') local setnodecolor = nodes.tracers.colors.set - --- function colorschemes.coloring(head) --- local lastfont, lastscheme --- local done = false --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) --- if a then --- local f = getfont(n) --- if f ~= lastfont then --- lastscheme = fontproperties[f].colorscheme --- lastfont = f --- end --- if lastscheme then --- local sc = lastscheme[getchar(n)] --- if sc then --- done = true --- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow --- end --- end --- end --- end --- return head, done --- end - --- seldom used, mostly in manuals, so non critical .. anyhow, somewhat faster: - --- function colorschemes.coloring(head) --- local lastfont = nil --- local lastattr = nil --- local lastscheme = nil --- local lastprefix = nil --- local done = nil --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) --- if a then --- if a ~= lastattr then --- lastattr = a --- lastprefix = "colorscheme:" .. a .. ":" --- end --- local f = getfont(n) --- if f ~= lastfont then --- lastfont = f --- lastscheme = fontproperties[f].colorscheme --- end --- if lastscheme then --- local sc = lastscheme[getchar(n)] --- if sc then --- setnodecolor(n,lastprefix .. sc) -- slow --- done = true --- end --- end --- end --- end --- return head, done --- end - --- ok, in case we have hundreds of pages colored: - -local cache = { } -- this could be a weak table +local cache = { } -- this could be a weak table setmetatableindex(cache,function(t,a) local v = { } @@ -207,11 +144,9 @@ function colorschemes.coloring(head) local lastattr = nil local lastcache = nil local lastscheme = nil - local done = nil - for n in traverse_id(glyph_code,tonut(head)) do + for n, char, f in nextglyph, head do local a = getattr(n,a_colorscheme) if a then - local f = getfont(n) if f ~= lastfont then lastfont = f lastscheme = fontproperties[f].colorscheme @@ -221,19 +156,18 @@ function colorschemes.coloring(head) lastcache = cache[a] end if lastscheme then - local sc = lastscheme[getchar(n)] + local sc = lastscheme[char] if sc then setnodecolor(n,lastcache[sc]) -- we could inline this one - done = true end end end end - return head, done + return head end function colorschemes.enable() - nodes.tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring") + nodes.tasks.enableaction("processors","fonts.goodies.colorschemes.coloring") function colorschemes.enable() end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua index 7855ce891e0..f8fa62953dc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-epd.lua @@ -8,25 +8,26 @@ if not modules then modules = { } end modules ['grph-epd'] = { local variables = interfaces.variables local settings_to_hash = utilities.parsers.settings_to_hash +local codeinjections = backends.pdf.codeinjections --- todo: page, name, file, url +local trace = false trackers.register("figures.merging", function(v) trace = v end) --- I have some experimental code for including comments and fields but it's --- unfinished and not included as it was just a proof of concept to get some idea --- about what is needed and possible. But the placeholders are here already. - -local codeinjections = backends.codeinjections +local report = logs.reporter("backend","merging") local function mergegoodies(optionlist) local options = settings_to_hash(optionlist) - local all = options[variables.all] or options[variables.yes] - if all or options[variables.reference] then + local yes = options[variables.yes] + local all = options[variables.all] + if next(options) then + report("% t",table.sortedkeys(options)) + end + if all or yes or options[variables.reference] then codeinjections.mergereferences() end if all or options[variables.comment] then codeinjections.mergecomments() end - if all or options[variables.bookmark] then + if all or yes or options[variables.bookmark] then codeinjections.mergebookmarks() end if all or options[variables.field] then @@ -39,6 +40,7 @@ local function mergegoodies(optionlist) end function figures.mergegoodies(optionlist) + -- todo: we can use runtoks instead context.stepwise(function() -- we use stepwise because we might need to define symbols -- for stamps that have no default appearance diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua index f2d7847eb9b..1e5c30d446c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.lua @@ -6,6 +6,11 @@ if not modules then modules = { } end modules ['grph-inc'] = { license = "see context related readme files" } +-- todo: in pdfe: pdfe.copyappearance(document,objnum) +-- +-- local im = createimage { filename = fullname } +-- local on = images.flushobject(im,document.__xrefs__[AP]) + -- todo: files are sometimes located twice -- todo: empty filename or only suffix always false (not found) -- lowercase types @@ -40,17 +45,16 @@ run TeX code from within Lua. Some more functionality will move to Lua. -- todo: store loaded pages per pdf file someplace -local tonumber, tostring, next = tonumber, tostring, next +local tonumber, tostring, next, unpack = tonumber, tostring, next, unpack local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub local longtostring = string.longtostring local contains = table.contains -local sortedhash = table.sortedhash +local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys local concat, insert, remove = table.concat, table.insert, table.remove local todimen = string.todimen local collapsepath = file.collapsepath local formatters = string.formatters -local formatcolumns = utilities.formatters.formatcolumns -local max, odd = math.max, math.odd +local odd = math.odd local P, R, S, Cc, C, Cs, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cc, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.match @@ -60,7 +64,10 @@ local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex local replacetemplate = utilities.templates.replace -local images = img +local bpfactor = number.dimenfactors.bp + +images = images or { } +local images = images local hasscheme = url.hasscheme local urlhashed = url.hashed @@ -104,7 +111,7 @@ local v_local = variables["local"] local v_default = variables.default local v_auto = variables.auto -local maxdimen = 0x3FFFFFFF -- 2^30-1 +local maxdimen = tex.magicconstants.maxdimen -- 0x3FFFFFFF -- 2^30-1 local ctx_doscalefigure = context.doscalefigure local ctx_relocateexternalfigure = context.relocateexternalfigure @@ -120,11 +127,11 @@ function checkimage(figure) local width = figure.width local height = figure.height if width <= 0 or height <= 0 then - report_inclusion("image %a has bad dimensions (%p,%p), discarding",figure.filename,width,height) + report_inclusion("image %a has bad dimensions (%p,%p), discarding",figure.filename or "?",width,height) return false, "bad dimensions" end - local xres = figure.xres - local yres = figure.yres + -- local xres = figure.xres + -- local yres = figure.yres local changes = false if height > width then if height > maxdimen then @@ -150,14 +157,117 @@ function checkimage(figure) end end ---- some extra img functions --- can become luat-img.lua +--- begin of mapping / this will become graphics & code|nodeinjections but not this year + +local __img__ = type(img) == "table" and img or { } +images.__img__ =__img__ + +local imgnew = __img__.new +local imgscan = __img__.scan +local imgcopy = __img__.copy +local imgwrap = __img__.node +local imgembed = __img__.immediatewrite + +if imgnew then + -- catch (actually we should be less picky in img) + local __img__new__ = img_new + imgnew = function(t) + t.kind = nil + return __img__new__(t) + end +end + +updaters.register("backend.update",function() + local img = images.__img__ + imgnew = img.new + imgscan = img.scan + imgcopy = img.copy + imgwrap = img.wrap + imgembed = img.embed +end) + +local imagekeys = { -- only relevant ones + "width", "height", "depth", "bbox", + "colordepth", "colorspace", + "filename", "filepath", "visiblefilename", + "imagetype", "stream", + "index", "objnum", + "pagebox", "page", "pages", + "rotation", "transform", + "xsize", "ysize", "xres", "yres", +} + +local imagesizes = { + art = true, bleed = true, crop = true, + media = true, none = true, trim = true, +} + +local imagetypes = { [0] = + "none", + "pdf", "png", "jpg", "jp2", "jbig2", + "stream", "memstream", +} + +imagetypes = table.swapped(imagetypes,imagetypes) + +images.keys = imagekeys +images.types = imagetypes +images.sizes = imagesizes + +-- new interface + +local function createimage(specification) + return imgnew(specification) +end + +local function copyimage(specification) + return imgcopy(specification) +end + +local function scanimage(specification) + return imgscan(specification) +end + +local function embedimage(specification) + -- write the image to file + return imgembed(specification) +end + +local function wrapimage(specification) + -- create an image rule + return imgwrap(specification) +end + +images.create = createimage +images.scan = scanimage +images.copy = copyimage +images.wrap = wrapimage +images.embed = embedimage + +-- now we reimplement img: + +img = { + new = createimage, + scan = scanimage, + copy = copyimage, + node = wrapimage, + write = function(specification) context(wrapimage(specification)) end, + immediatewrite = embedimage, + immediatewriteobject = function() end, -- not upported, experimental anyway + boxes = function() return sortedkeys(imagesizes) end, + fields = function() return imagekeys end, + types = function() return { unpack(imagetypes,0,#imagetypes) } end, +} -local allimagekeys = images.keys() +-- end of copies / mapping local function imagetotable(imgtable) + if type(imgtable) == "table" then + return copy(imgtable) + end local result = { } - for k=1,#allimagekeys do - local key = allimagekeys[k] + for k=1,#imagekeys do + local key = imagekeys[k] result[key] = imgtable[key] end return result @@ -171,41 +281,24 @@ function images.print(i,...) return table.print(imagetotable(i),...) end -function images.clone(i,data) - i.width = data.width or i.width - i.height = data.height or i.height - -- attr etc - return i -end - -local validsizes = table.tohash(images.boxes()) -local validtypes = table.tohash(images.types()) - local function checkimagesize(size) if size then size = gsub(size,"box","") - return validsizes[size] and size or "crop" + return imagesizes[size] and size or "crop" else return "crop" end end -local newimage = images.new -local scanimage = images.scan -local copyimage = images.copy -local cloneimage = images.clone -local imagetonode = images.node - -images.check = checkimage -images.checksize = checkimagesize -images.tonode = imagetonode -images.totable = imagetotable +images.check = checkimage +images.checksize = checkimagesize +images.totable = imagetotable -local indexed = { } - -function images.ofindex(n) - return indexed[n] -end +-- local indexed = { } +-- +-- function images.ofindex(n) +-- return indexed[n] +-- end --- we can consider an grph-ini file @@ -372,22 +465,30 @@ function figures.setorder(list) -- can be table or string end end +local function guessfromstring(str) + if str then + for i=1,#figures_magics do + local pattern = figures_magics[i] + if lpegmatch(pattern.pattern,str) then + local format = pattern.format + if trace_figures then + report_inclusion("file %a has format %a",filename,format) + end + return format + end + end + end +end + +figures.guessfromstring = guessfromstring + function figures.guess(filename) local f = io.open(filename,'rb') if f then local str = f:read(100) f:close() if str then - for i=1,#figures_magics do - local pattern = figures_magics[i] - if lpegmatch(pattern.pattern,str) then - local format = pattern.format - if trace_figures then - report_inclusion("file %a has format %a",filename,format) - end - return format - end - end + return guessfromstring(str) end end end @@ -571,6 +672,7 @@ function figures.initialize(request) request.cache = request.cache ~= "" and request.cache request.prefix = request.prefix ~= "" and request.prefix request.format = request.format ~= "" and request.format + request.compact = request.compact == v_yes table.merge(figuredata.request,request) end return figuredata @@ -818,7 +920,7 @@ local function register(askedname,specification) end elseif io.exists(oldname) then report_inclusion("file %a is bugged",oldname) - if format and validtypes[format] then + if format and imagetypes[format] then specification.fullname = oldname end specification.converted = false @@ -827,13 +929,13 @@ local function register(askedname,specification) end end if format then - local found = figures_suffixes[format] -- validtypes[format] + local found = figures_suffixes[format] if not found then specification.found = false if trace_figures then report_inclusion("format %a is not supported",format) end - elseif validtypes[format] then + elseif imagetypes[format] then specification.found = true if trace_figures then report_inclusion("format %a natively supported by backend",format) @@ -1362,15 +1464,18 @@ end local pagecount = { } function checkers.generic(data) - local dr, du, ds = data.request, data.used, data.status - local name = du.fullname or "unknown generic" - local page = du.page or dr.page - local size = dr.size or "crop" - local color = dr.color or "natural" - local mask = dr.mask or "none" - local conversion = dr.conversion - local resolution = dr.resolution - local arguments = dr.arguments + local dr, du, ds = data.request, data.used, data.status + local name = du.fullname or "unknown generic" + local page = du.page or dr.page + local size = dr.size or "crop" + local color = dr.color or "natural" + local mask = dr.mask or "none" + local conversion = dr.conversion + local resolution = dr.resolution + local arguments = dr.arguments + local scanimage = dr.scanimage or scanimage + local userpassword = dr.userpassword + local ownerpassword = dr.ownerpassword if not conversion or conversion == "" then conversion = "default" end @@ -1390,22 +1495,29 @@ function checkers.generic(data) resolution, arguments ) + -- local figure = figures_loaded[hash] if figure == nil then - figure = newimage { + figure = createimage { filename = name, page = page, pagebox = dr.size, keepopen = dr.keepopen or false, + userpassword = userpassword, + ownerpassword = ownerpassword, -- visiblefilename = "", -- this prohibits the full filename ending up in the file } codeinjections.setfigurecolorspace(data,figure) codeinjections.setfiguremask(data,figure) if figure then - -- new, bonus check + -- new, bonus check (a bogus check in lmtx) if page and page > 1 then - local f = scanimage{ filename = name } - if f.page and f.pages < page then + local f = scanimage { + filename = name, + userpassword = userpassword, + ownerpassword = ownerpassword, + } + if f and f.page and f.pages < page then report_inclusion("no page %i in %a, using page 1",page,name) page = 1 figure.page = page @@ -1418,6 +1530,10 @@ function checkers.generic(data) ds.found = false ds.error = true end + if figure.attr and not f.attr then + -- tricky as img doesn't allow it + f.attr = figure.attr + end figure = f end local f, d = codeinjections.setfigurealternative(data,figure) @@ -1459,6 +1575,11 @@ function figures.getrealpage(index) return pofimages[index] or 0 end +local function updatepage(specification) + local n = specification.n + pofimages[n] = pofimages[n] or tex.count.realpageno -- so when reused we register the first one only +end + function includers.generic(data) local dr, du, ds = data.request, data.used, data.status -- here we set the 'natural dimensions' @@ -1472,10 +1593,13 @@ function includers.generic(data) -- height = dr.height, -- } if figure == nil then - figure = ds.private + figure = ds.private -- the img object if figure then - figure = copyimage(figure) - figure = figure and cloneimage(figure,data.request) or false + figure = (dr.copyimage or copyimage)(figure) + if figure then + figure.width = dr.width or figure.width + figure.height = dr.height or figure.height + end end figures_used[hash] = figure end @@ -1483,16 +1607,15 @@ function includers.generic(data) local nr = figures.boxnumber nofimages = nofimages + 1 ds.pageindex = nofimages - local image = imagetonode(figure) - local pager = new_latelua(function() - pofimages[nofimages] = pofimages[nofimages] or tex.count.realpageno -- so when reused we register the first one only - end) + local image = wrapimage(figure) + local pager = new_latelua { action = updatepage, n = nofimages } image.next = pager pager.prev = image - local box = hpack(image) -- imagetonode(figure) not longer valid - - indexed[figure.index] = figure - box.width, box.height, box.depth = figure.width, figure.height, 0 -- new, hm, tricky, we need to do that in tex (yet) + local box = hpack(image) + -- indexed[figure.index] = figure + box.width = figure.width + box.height = figure.height + box.depth = 0 texsetbox(nr,box) ds.objectnumber = figure.objnum ctx_relocateexternalfigure() @@ -1546,7 +1669,7 @@ function checkers.mov(data) nodeinjections.insertmovie { width = width, height = height, - factor = number.dimenfactors.bp, + factor = bpfactor, ["repeat"] = dr["repeat"], controls = dr.controls, preview = dr.preview, @@ -1916,8 +2039,10 @@ function figures.getinfo(name,page) end if name.name then local data = figures.push(name) - figures.identify() - figures.check() + data = figures.identify(data) + if data.status and data.status.status > 0 then + data = figures.check(data) + end figures.pop() return data end @@ -1961,8 +2086,11 @@ implement { { "arguments" }, { "repeat" }, { "transform" }, + { "compact" }, { "width", "dimen" }, { "height", "dimen" }, + { "userpassword" }, + { "ownerpassword" }, } } } diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv index 677883fbb59..20e7c11a61b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-inc.mkiv @@ -20,7 +20,15 @@ \writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion} -\registerctxluafile{grph-inc}{} +\ifcase\contextlmtxmode + \registerctxluafile{grph-inc}{} +\else + \registerctxluafile{grph-img}{} + \registerctxluafile{grph-inc}{} + \registerctxluafile{grph-bmp}{} + \registerctxluafile{grph-chk}{} +\fi + \registerctxluafile{grph-con}{} \registerctxluafile{grph-fil}{} \registerctxluafile{grph-mem}{} @@ -32,7 +40,7 @@ %D Including graphics is complicated by the fact that we need to locate them first, %D optionally manipulate them and scale then next. Lookups are to be done as efficient %D as possible and inclusion of the data might happens only once. In \MKIV\ much of this -%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's +%D is delegated to the \LUA\ end. There is not so much less code as in \MKII\ but it's %D more powerful, flexible, pluggable and some of the extended functionality has been %D moved from modules to the core. The overall functionality is rather stable and has %D not changed much over the years. @@ -105,6 +113,9 @@ \c!align =\v!none, % New, for Tacos extremely large graphics. \c!crossreference =\v!no, \c!transform =\v!auto, + \c!userpassword =, + \c!ownerpassword =, + \c!compact =, ] %D Defining figures. @@ -201,7 +212,7 @@ {\grph_include_use_indeed{#1}{#2}{#3}{#4}}}}} \def\grph_include_use_indeed#1#2#3#4% - {\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}% + {\dodoglobal\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}% \grph_include_analyze_collection[#2][#4]} % inclusion @@ -317,27 +328,30 @@ % \dostarttagged\t!image\empty \clf_figure_push { - name {\p_grph_include_name}% - label {\ifx\p_label\empty\p_grph_include_label\else\p_label\fi}% - page {\externalfigureparameter\c!page}% - file {\externalfigureparameter\c!file}% - size {\externalfigureparameter\c!size}% - object {\externalfigureparameter\c!object}% - prefix {\externalfigureparameter\c!prefix}% - cache {\externalfigureparameter\c!cache}% - format {\externalfigureparameter\c!method}% - preset {\externalfigureparameter\c!prefix}% - controls {\externalfigureparameter\c!controls}% - resources {\externalfigureparameter\c!resources}% - preview {\externalfigureparameter\c!preview}% - display {\externalfigureparameter\c!display}% - mask {\externalfigureparameter\c!mask}% - conversion {\externalfigureparameter\c!conversion}% - resolution {\externalfigureparameter\c!resolution}% - color {\externalfigureparameter\c!color}% unprocessed raw key - arguments {\externalfigureparameter\c!arguments}% used for converters - repeat {\externalfigureparameter\c!repeat}% - transform {\externalfigureparameter\c!transform}% + name {\p_grph_include_name}% + label {\ifx\p_label\empty\p_grph_include_label\else\p_label\fi}% + page {\externalfigureparameter\c!page}% + file {\externalfigureparameter\c!file}% + size {\externalfigureparameter\c!size}% + object {\externalfigureparameter\c!object}% + prefix {\externalfigureparameter\c!prefix}% + cache {\externalfigureparameter\c!cache}% + format {\externalfigureparameter\c!method}% + preset {\externalfigureparameter\c!prefix}% + controls {\externalfigureparameter\c!controls}% + resources {\externalfigureparameter\c!resources}% + preview {\externalfigureparameter\c!preview}% + display {\externalfigureparameter\c!display}% + mask {\externalfigureparameter\c!mask}% + conversion {\externalfigureparameter\c!conversion}% + resolution {\externalfigureparameter\c!resolution}% + color {\externalfigureparameter\c!color}% unprocessed raw key + arguments {\externalfigureparameter\c!arguments}% used for converters + repeat {\externalfigureparameter\c!repeat}% + transform {\externalfigureparameter\c!transform}% + compact {\externalfigureparameter\c!compact}% experiment, share fonts + userpassword {\externalfigureparameter\c!userpassword}% + ownerpassword{\externalfigureparameter\c!ownerpassword}% \ifx\p_width\empty \else width \dimexpr\p_width\relax \fi @@ -589,9 +603,9 @@ \def\grph_include_set_mode {\ifcase\figurestatus - \global\resetsystemmode\v!figure % todo, also: \v!resource + \globalresetsystemmode\v!figure % todo, also: \v!resource \else - \global\setsystemmode \v!figure % todo, also: \v!resource + \globalsetsystemmode \v!figure % todo, also: \v!resource \fi} \appendtoks @@ -641,10 +655,41 @@ \unexpanded\def\docheckfiguremps #1{\global\setbox\foundexternalfigure\vpack{\convertMPtoPDF{#1}11}} \unexpanded\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vpack{\useMPrun{#1}{#2}}} -\unexpanded\def\relocateexternalfigure % easier here than in lua +% \unexpanded\def\relocateexternalfigure % easier here than in lua +% {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup +% \vss +% \ht\foundexternalfigure\zeropoint +% \hpack to \wd\foundexternalfigure\bgroup +% \box\foundexternalfigure +% \hss +% \egroup +% \egroup} + +\unexpanded\def\relocateexternalfigure {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup - \vss + % + % The \vss can (!) introduce 1 sp excess visible in xform which in itself + % is not that important but some don't like these cosmetic side effects, for + % instance we can get: + % + % vss : \vbox(845.1575+0.0)x597.23125, glue set 845.15747fil, direction TLT + % vskip : \vbox(845.1575+0.0)x597.23125, direction TLT + % + % or + % + % 1 0 0 1 0 0.00003 cm + % 1 0 0 1 0 0 cm + % + % This is a known property of using glue and can even depend on the architecture + % (float implementation). Anyway, let's for now use a skip. Of course this can + % shift the issue elsewhere, as vss is used a lot elsewhere. + % + % \vss + \vkern\ht\foundexternalfigure + % + % \parfillskip\zeropoint \ht\foundexternalfigure\zeropoint + \dp\foundexternalfigure\zeropoint \hpack to \wd\foundexternalfigure\bgroup \box\foundexternalfigure \hss diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-mem.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-mem.lua index bb48ae8d554..ff35483505a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-mem.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-mem.lua @@ -20,67 +20,143 @@ local gsub = string.gsub local report = logs.reporter("memstream") local trace = false trackers.register ("graphics.memstreams", function(v) trace = v end) local data = { } -local opened = { } -local function setmemstream(name,stream,once) - if once and data[name] then +if pdfe then + + local function setmemstream(name,stream,once) + if once and data[name] then + if trace then + report("not overloading %a",name) -- + end + return data[name] + end + local kind = figures.guessfromstring(stream) + local identifier = false + if kind == "pdf" then + identifier = pdfe.new(stream,#stream,name) + if not identifier then + report("no valid pdf stream %a",name) + elseif trace then + report("setting %a with identifier %a",name,identifier) + end + else + identifier = "m_k_i_v_memstream_" .. name .. "." .. kind + io.savedata(identifier,stream) + end + if not identifier then + identifier = "invalid-memstream" + end + data[name] = identifier + return identifier + end + + resolvers.setmemstream = setmemstream + + function resolvers.finders.memstream(specification) + local name = specification.path + local identifier = data[name] + if identifier then + if trace then + report("reusing %a with identifier %a",name,identifier) + end + return identifier + end + local stream = io.loaddata(name) + if stream and stream ~= "" then + return setmemstream(name,stream) + end if trace then - report("not overloading %a",name) -- + report("no valid memstream %a",name) end - return data[name] + return resolvers.finders.notfound() end - local memstream, identifier = epdf.openMemStream(stream,#stream,name) - if not identifier then - report("no valid stream %a",name) - identifier = "invalid-memstream" - elseif trace then - report("setting %a with identifier %a",name,identifier) + + local flush = { } + + function resolvers.resetmemstream(name,afterpage) + if afterpage then + flush[#flush+1] = name + end end - data [name] = identifier - opened[name] = memstream - return identifier -end -resolvers.setmemstream = setmemstream + luatex.registerpageactions(function() + if #flush > 0 then + for i=1,#flush do + local identifier = data[name] + if identifier then + os.remove(identifier) + data[name] = nil + end + end + flush = { } + end + end) + +else -function resolvers.finders.memstream(specification) - local name = specification.path - local identifier = data[name] - if identifier then - if trace then - report("reusing %a with identifier %a",name,identifier) + local opened = { } + + local function setmemstream(name,stream,once) + if once and data[name] then + if trace then + report("not overloading %a",name) -- + end + return data[name] end + local memstream, identifier = epdf.openMemStream(stream,#stream,name) + if not identifier then + report("no valid stream %a",name) + identifier = "invalid-memstream" + elseif trace then + report("setting %a with identifier %a",name,identifier) + end + data [name] = identifier + opened[name] = memstream return identifier end - local stream = io.loaddata(name) - if not stream or stream == "" then - if trace then - report("no valid file %a",name) + + resolvers.setmemstream = setmemstream + + function resolvers.finders.memstream(specification) + local name = specification.path + local identifier = data[name] + if identifier then + if trace then + report("reusing %a with identifier %a",name,identifier) + end + return identifier + end + local stream = io.loaddata(name) + if not stream or stream == "" then + if trace then + report("no valid file %a",name) + end + return resolvers.finders.notfound() + else + return setmemstream(name,stream) end - return resolvers.finders.notfound() - else - return setmemstream(name,stream) end -end -local flush = { } + local flush = { } -function resolvers.resetmemstream(name,afterpage) - if afterpage then - flush[#flush+1] = name - else - opened[name] = nil + function resolvers.resetmemstream(name,afterpage) + if afterpage then + flush[#flush+1] = name + else + opened[name] = nil + end end -end -luatex.registerpageactions(function() - if #flush > 0 then - for i=1,#flush do - opened[flush[i]] = nil -- we keep of course data[name] because of reuse + luatex.registerpageactions(function() + if #flush > 0 then + for i=1,#flush do + opened[flush[i]] = nil -- we keep of course data[name] because of reuse + end + flush = { } end - flush = { } - end -end) + end) + +end figures.identifiers.list[#figures.identifiers.list+1] = function(specification) local name = specification.request.name diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-pat.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-pat.lua index 89b29906d39..e38a9a674d6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-pat.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-pat.lua @@ -15,7 +15,7 @@ local texsetbox = tex.setbox local texgetbox = tex.getbox local nodepool = nodes.pool -local new_literal = nodepool.pdforiginliteral -- really ? +local new_literal = nodepool.originliteral -- really ? local new_hlist = nodepool.hlist local names = { } @@ -37,7 +37,7 @@ interfaces.implement { if not name or name == "" then return end - nodes.handlers.finalize(box,"object") + nodes.handlers.finalizebox(number) names[name] = lpdf.registerpattern { number = number, width = specification.width or box.width, diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua index 03f678973f0..08edade1fe4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-rul.lua @@ -8,33 +8,48 @@ if not modules then modules = { } end modules ['grph-rul'] = { local tonumber, next, type = tonumber, next, type -local attributes = attributes -local nodes = nodes -local context = context +local attributes = attributes +local nodes = nodes +local context = context -local ruleactions = nodes.rules.ruleactions -local userrule = nodes.rules.userrule -local bpfactor = number.dimenfactors.bp -local pdfprint = pdf.print +local bpfactor = number.dimenfactors.bp -local current_attr = nodes.current_attr -local setfield = nodes.setfield +local nuts = nodes.nuts +local userrule = nuts.rules.userrule +local outlinerule = nuts.pool.outlinerule +local ruleactions = nuts.rules.ruleactions -local getattribute = tex.getattribute +local setattrlist = nuts.setattrlist +local setattr = nuts.setattr +local tonode = nuts.tonode -local a_color = attributes.private('color') -local a_transparency = attributes.private('transparency') -local a_colormodel = attributes.private('colormodel') +local getattribute = tex.getattribute -local mpcolor = attributes.colors.mpcolor +local lefttoright_code = nodes.dirvalues.lefttoright -local trace_mp = false trackers.register("rules.mp", function(v) trace_mp = v end) +local a_color = attributes.private('color') +local a_transparency = attributes.private('transparency') +local a_colormodel = attributes.private('colormodel') -local report_mp = logs.reporter("rules","mp") +local mpcolor = attributes.colors.mpcolor -local floor = math.floor -local getrandom = utilities.randomizer.get -local formatters = string.formatters +local trace_mp = false trackers.register("rules.mp", function(v) trace_mp = v end) + +local report_mp = logs.reporter("rules","mp") + +local floor = math.floor +local getrandom = utilities.randomizer.get +local formatters = string.formatters + +-- This is very pdf specific. Maybe move some to lpdf-rul.lua some day. + +local pdfprint + +pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end + +updaters.register("backend.update",function() + pdfprint = lpdf.print +end) do @@ -97,19 +112,18 @@ def RuleColor = %color% enddef ; ruleactions.mp = function(p,h,v,i,n) local name = p.name or "fake:rest" local code = (predefined[name] or predefined["fake:rest"]) { - data = p.data or "", - width = p.width * bpfactor, - height = p.height * bpfactor, - depth = p.depth * bpfactor, - factor = (p.factor or 0) * bpfactor, -- needs checking - offset = p.offset or 0, - line = (p.line or 65536) * bpfactor, - color = mpcolor(p.ma,p.ca,p.ta), - option = p.option or "", - direction = p.direction or "TLT", - h = h * bpfactor, - v = v * bpfactor, - + data = p.data or "", + width = p.width * bpfactor, + height = p.height * bpfactor, + depth = p.depth * bpfactor, + factor = (p.factor or 0) * bpfactor, -- needs checking + offset = p.offset or 0, + line = (p.line or 65536) * bpfactor, + color = mpcolor(p.ma,p.ca,p.ta), + option = p.option or "", + direction = p.direction or lefttoright_code, + h = h * bpfactor, + v = v * bpfactor, } if not initialized then initialized = true @@ -134,14 +148,28 @@ do local f_rectangle = formatters["%.6F w %.6F %.6F %.6F %.6F re %s"] local f_baselined = formatters["%.6F w %.6F %.6F %.6F %.6F re s %.6F %.6F m %.6F %.6F l s"] local f_dashlined = formatters["%.6F w %.6F %.6F %.6F %.6F re s [%.6F %.6F] 2 d %.6F %.6F m %.6F %.6F l s"] - local f_radtangle = formatters[ [[ - %.6F w %.6F %.6F m - %.6F %.6F l %.6F %.6F %.6F %.6F y - %.6F %.6F l %.6F %.6F %.6F %.6F y - %.6F %.6F l %.6F %.6F %.6F %.6F y - %.6F %.6F l %.6F %.6F %.6F %.6F y - h %s - ]] ] + local f_radtangle = formatters[ + [[%.6F w %.6F %.6F m +%.6F %.6F l %.6F %.6F %.6F %.6F y +%.6F %.6F l %.6F %.6F %.6F %.6F y +%.6F %.6F l %.6F %.6F %.6F %.6F y +%.6F %.6F l %.6F %.6F %.6F %.6F y +h %s]] + ] + + directives.register("metapost.stripzeros",function() -- confusing name but ok + f_rectangle = formatters["%.6N w %.6N %.6N %.6N %.6N re %s"] + f_baselined = formatters["%.6N w %.6N %.6N %.6N %.6N re s %.6N %.6N m %.6N %.6N l s"] + f_dashlined = formatters["%.6N w %.6N %.6N %.6N %.6N re s [%.6N %.6N] 2 d %.6N %.6N m %.6N %.6N l s"] + f_radtangle = formatters[ +[[%.6N w %.6N %.6N m +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +h %s]] + ] + end) ruleactions.fill = function(p,h,v,i,n) local l = (p.line or 65536)*bpfactor @@ -210,17 +238,44 @@ interfaces.implement { local ma = getattribute(a_colormodel) or 1 local ca = getattribute(a_color) local ta = getattribute(a_transparency) - setfield(rule,"attr",current_attr()) + setattrlist(rule,true) if t.type == "mp" then t.ma = ma t.ca = ca t.ta = ta else - rule[a_colormodel] = ma - rule[a_color] = ca - rule[a_transparency] = ta + setattr(rule,a_colormodel,ma) + setattr(rule,a_color,ca) + setattr(rule,a_transparency,ta) end - context(rule) + context(tonode(rule)) -- will become context.nodes.flush + end +} + +interfaces.implement { + name = "outlinerule", + public = true, + protected = true, + arguments = { { + { "width", "dimension" }, + { "height", "dimension" }, + { "depth", "dimension" }, + { "line", "dimension" }, + } } , + actions = function(t) + local rule = outlinerule(t.width,t.height,t.depth,t.line) + setattrlist(rule,true) + context(tonode(rule)) -- will become context.nodes.flush + end +} + +interfaces.implement { + name = "framedoutline", + arguments = { "dimension", "dimension", "dimension", "dimension" }, + actions = function(w,h,d,l) + local rule = outlinerule(w,h,d,l) + setattrlist(rule,true) + context(tonode(rule)) -- will become context.nodes.flush end } @@ -247,8 +302,8 @@ interfaces.implement { type = "mp", name = t.name, } - setfield(rule,"attr",current_attr()) - context(rule) + setattrlist(rule,true) + context(tonode(rule)) end } diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua index 30089cdc43c..a9297d48ddb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-swf.lua @@ -37,9 +37,10 @@ local function getheader(name) buffer = f:read(20) -- ('*a') end f:close() + -- can be done better now that we have stream readers buffer = { match(buffer,"(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)") } for i=1,9 do - buffer[i] = tobitstring(byte(buffer[i])) + buffer[i] = tobitstring(byte(buffer[i]),8,8) end local framebits = concat(buffer,"",1,9) local n = tonumber(sub(framebits,1,5),2) diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv index 6bd0e65ccec..35e812b3edb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/grph-trf.mkiv @@ -146,10 +146,10 @@ \d_grph_scale_ht\ht\nextbox \d_grph_scale_dp\dp\nextbox % - \global\let\finalscaleboxxscale \!!plusone - \global\let\finalscaleboxyscale \!!plusone - \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}% - \xdef \finalscaleboxheight{\the\d_grph_scale_ht}% + \glet\finalscaleboxxscale \!!plusone + \glet\finalscaleboxyscale \!!plusone + \xdef\finalscaleboxwidth {\the\d_grph_scale_wd}% + \xdef\finalscaleboxheight{\the\d_grph_scale_ht}% % \forgetall \dontcomplain @@ -164,11 +164,38 @@ \box\nextbox \egroup} +% \def\grph_scale_apply +% {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd +% \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht +% \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp +% \setbox\nextbox\hpack +% {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale +% \smashedbox\nextbox +% \dostopscaling}% +% \wd\nextbox\d_grph_scale_wd +% \ht\nextbox\d_grph_scale_ht +% \dp\nextbox\d_grph_scale_dp} + \def\grph_scale_apply {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp - \setbox\nextbox\hpack + \ifdim\d_grph_scale_wd=\wd\nextbox + \ifdim\d_grph_scale_ht=\ht\nextbox + \ifdim\d_grph_scale_dp=\dp\nextbox + % \grph_scale_apply_nop + \else + \grph_scale_apply_yes + \fi + \else + \grph_scale_apply_yes + \fi + \else + \grph_scale_apply_yes + \fi} + +\def\grph_scale_apply_yes + {\setbox\nextbox\hpack {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale \smashedbox\nextbox \dostopscaling}% @@ -871,7 +898,7 @@ \egroup} \def\grph_rotate_finish_indeed - {\hbox\bgroup + {\hpack\bgroup \ifx\p_rotation_rotation\empty \grph_rotate_finish_nop \else diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv deleted file mode 100644 index 584ee13512d..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/java-imp-exa.mkiv +++ /dev/null @@ -1,395 +0,0 @@ -%D \module -%D [ file=java-exa, -%D version=2002.??.??, -%D title=\CONTEXT\ JavaScript Macros, -%D subtitle=Example Support, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -% XFDF versus HTML -% localhost versus remote versus set - -% filename | filename-nr => name -% fakename | fakename-nr => file upload, unless localhost -% -% we erase the list because otherwise we end up in browser remembering -% problems; also, it is not possible to set upload fields 'manually' - -\startJSpreamble request_1 used now - - var example_method = "HTML" ; - var example_host = "" ; - var example_port = "" ; - var example_url = "" ; - var example_file = "" ; - - var example_log = true ; % false - - function stripped_exa_value( name ) { - f = this.getField(name) ; - if (f) { - str = f.value ; - if (str.indexOf(name+'-')==0) { - str = str.substr(name.length+1) ; - } - return str ; - } else { - return "" ; - } - } - - function identify_example_url ( ) { - if (example_log) { - console.clear ; - console.println("base url: "+this.baseURL) ; - console.println("this url: "+this.URL) ; - } - if (this.baseURL != "") { - example_url = this.baseURL ; - } else { - if (this.URL != "") { - example_url = this.URL - } - } - if (example_url.indexOf("file://")>=0) { - example_url = "" ; - } - str = stripped_exa_value("examplehost") ; - if (str != "auto") { - example_host = str ; - if (str == "localhost") { - example_port = "8061" - } - } - str = stripped_exa_value("exampleport") ; - if (str != "auto") { - example_port = str ; - } - if (example_log) { - console.println("example_url: "+example_url) ; - console.println("example_host: "+example_host) ; - console.println("example_port: "+example_port) ; - } - } - - function check_example_url ( url ) { - if (url.indexOf("file://")>=0) { - url = "http://localhost:8061" ; - console.println("file url replaced by: "+url) ; - } else { - if (url.indexOf("://")<0) { - url = "http://" + url ; - } - if (example_log) { - console.println("url before check: "+url) ; - } -% url = url.replace(/(http:\\\/\\\/.+)(\\\/.*$)/, "$1") ; - url = url.replace(/(https*:\\\/\\\/.+?)(\\\/.*$)/, "$1/exarequest") ; - if (example_log) { - console.println("url after check: "+url) ; - } - } - return url ; - } - - function set_example_xfdf ( method ) { - example_method = method ; - } - - function set_example_file ( file ) { - example_method = file ; - } - - function set_example_host ( host ) { - example_host = host ; - } - - function set_example_port ( port ) { - example_host = host ; - } - - function do_erase_example_file(tag) { - f = this.getField(tag) ; - if (f) { - f.value = "" ; - } - } - - function do_erase_example_list(tag) { - for (i=1;i<=100;i++) { - f = this.getField(tag+"-"+i) ; - if (f) { - f.value = "" ; - } else { - return - } - } - } - - function do_submit_example_url ( url ) { - if ((example_method == "XFDF" ) || (url.indexOf("localhost")>=0)) { - do_erase_example_file("fakename") ; - do_erase_example_list("fakename") ; - } - url = check_example_url(url) ; - if (example_log) { - console.println("submitting form to "+url+" using method "+example_method) ; - } - if (example_file != "") { - url = url + "/" + example_file ; - } - % we need the bFDF for acrobat 5 - this.submitForm({cURL : url, bFDF : false, cSubmitAs : example_method}) ; - } - - function submit_example_form ( ) { - identify_example_url() ; - if (example_host != "") { - if (example_port != "") { - do_submit_example_url(example_host+":"+example_port) ; - } else { - do_submit_example_url(example_host) ; - } - } else { - if (example_url != "") { - do_submit_example_url(example_url) ; - } else { - if (example_port != "") { - do_submit_example_url("localhost"+":"+example_port) ; - } else { - do_submit_example_url("localhost:8061") ; % local exampler - } - } - } - resetfilename () ; - } - - function submit_form ( host, port) { - set_example_host(host) ; - set_example_post(post) ; - submit_example_form ; - } - -\stopJSpreamble - -\startJSpreamble request_2 used now - - var exa_command = "" ; - var exa_option = "" ; - var exa_filename = "" ; - var exa_filelist = "" ; - var exa_registered = "" ; - - function set_request (command,option) { - exa_command = command ; - if (exa_command == "") { - exa_option = option ; - } else { if (option == "") { - exa_option = "" ; - } else { if (option.indexOf("--")<0) { - exa_option = "--action=" + option ; - } else { - exa_option = option ; - } } } - } - - function assemble_request ( ) { - v = this.getField('filename') ; - if (v) { - exa_filename = v.value ; - } - v = this.getField('filelist') ; - if (v) { - exa_filelist = v.value ; - } -% exa_filename = exa_filename.replace(/\\\\/g,'/') ; -% exa_filelist = exa_filelist.replace(/\\\\/g,'/') ; - str = "\\n" ; - str = str+"" ; - if (exa_filelist == "") { - exa_filelist = exa_registered ; - } else { if (exa_registered != "") { - exa_filelist = exa_filelist + "\\n" + exa_registered ; - } } - if (exa_command != "") { - str = str+""+exa_command+"" ; - } - if (exa_option != "") { - str = str+""+exa_option+"" ; - } - if (exa_filename != "") { - str = str+""+exa_filename+"" ; - } - var fls = "" ; - if (exa_filelist != "") { - % old method, soon obsolete - lst = exa_filelist.split(/\\s/) ; - for (i=0;i"+lst[i]+"" ; - } - } else { if (exa_multiple) { - for (i=1;i<=100;i++) { - % console.println("file field "+i) ; - f = this.getField("filename-"+ i) ; -% if (f) { if (f.value != "") { -% if (g) { if (g.value == "") { -% fls = fls+""+f.value+"" ; -% } else { -% fls = fls+""+f.value+"" ; -% } } else { -% fls = fls+""+f.value+"" ; -% } -% } } - if (f) { if (f.value != "") { - fls = fls + "" ; - } else { - % console.println("b") ; - fls = fls + " label='" + g.value + "'>" ; - } } else { - % console.println("c") ; - fls = fls + ">" ; - } - fls = fls + f.value + "" ; - } } - } - } } - if (fls != "") { - str = str + "" + fls + "" ; - } - str = str + "" ; - v = this.getField('exa:request') ; - if (v) { - v.value = str ; - } - } - -\stopJSpreamble - -\startJSpreamble request_3 used now - - var exa_multiple = false ; - - function setfilename ( suffixes ) { - if (event.targetName) { - var name = event.targetName ; - var fake = name.replace(/filename/,"fakename") ; - } else { - var name = 'filename' ; - var fake = 'fakename' ; - } - f = this.getField(fake) ; - if (f) { - f.browseForFileToSubmit() ; - if ((suffixes != "") && (f.value != "")) { - % - s = suffixes.replace(/,/g,"|") ; - r = new RegExp() ; - s = "\\\\.(" + s + ")$" ; - r.compile(s, "i") ; - if (f.value.search(r)<=0) { - f.value = "" ; - app.alert('This filetype is not permitted.') ; - % - % lst = suffixes.split(/,/) ; - % ok = false ; - % for (i=0;i=0) { -% f.value = "" ; -% } -% } - } - this.dirty = false ; - } - - function addfilename () { - if (exa_multiple) { - h = this.getField("filelist") ; - g = this.getField("filename") ; - if ((g) && (h)) { - str = g.value ; - if (h.value == "") { - h.value = str ; - } else { - h.value = h.value + "\\n" + str ; - } - g.value = "" ; - this.value = "" ; - } - } - this.dirty = false ; - } - - % this only works with client that assembles request - - function registerfilename (str) { - if (str!="") { - h = this.getField("filelist") ; - if (h) { - if (h.value != "") { - h.value = h.value + "\\n" ; - } - h.value = h.value + str ; - } else { - if (exa_registered != "") { - exa_registered = exa_registered + "\\n" ; - } - exa_registered = exa_registered + str ; - } - } - console.show ; - console.println('registered files') ; - console.println("file: "+str) ; - console.println("list: "+exa_registered) ; - this.dirty = false ; - } - - function checkfilename () { - } - - function getfilename ( suffixes ) { - setfilename(suffixes) ; - checkfilename() ; - addfilename() ; - } - - function resetfilename () { - do_erase_example_file("fakename") ; - do_erase_example_file("filename") ; - do_erase_example_file("filelist") ; - do_erase_example_list("filename") ; - do_erase_example_list("fakename") ; - } - -\stopJSpreamble - -\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-example.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-example.mkiv new file mode 100644 index 00000000000..82d5b0cb0d7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-example.mkiv @@ -0,0 +1,398 @@ +%D \module +%D [ file=java-imp-example, % was: java-exa +%D version=2002.??.??, +%D title=\CONTEXT\ JavaScript Macros, +%D subtitle=Example Support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This code is just kept as an example of dealign with forms and submitting data to +%D a server. We used this to create stepwise growing student test forms and such. + +% XFDF versus HTML +% localhost versus remote versus set + +% filename | filename-nr => name +% fakename | fakename-nr => file upload, unless localhost +% +% we erase the list because otherwise we end up in browser remembering +% problems; also, it is not possible to set upload fields 'manually' + +\startJSpreamble request_1 used now + + var example_method = "HTML" ; + var example_host = "" ; + var example_port = "" ; + var example_url = "" ; + var example_file = "" ; + + var example_log = true ; % false + + function stripped_exa_value( name ) { + f = this.getField(name) ; + if (f) { + str = f.value ; + if (str.indexOf(name+'-')==0) { + str = str.substr(name.length+1) ; + } + return str ; + } else { + return "" ; + } + } + + function identify_example_url ( ) { + if (example_log) { + console.clear ; + console.println("base url: "+this.baseURL) ; + console.println("this url: "+this.URL) ; + } + if (this.baseURL != "") { + example_url = this.baseURL ; + } else { + if (this.URL != "") { + example_url = this.URL + } + } + if (example_url.indexOf("file://")>=0) { + example_url = "" ; + } + str = stripped_exa_value("examplehost") ; + if (str != "auto") { + example_host = str ; + if (str == "localhost") { + example_port = "8061" + } + } + str = stripped_exa_value("exampleport") ; + if (str != "auto") { + example_port = str ; + } + if (example_log) { + console.println("example_url: "+example_url) ; + console.println("example_host: "+example_host) ; + console.println("example_port: "+example_port) ; + } + } + + function check_example_url ( url ) { + if (url.indexOf("file://")>=0) { + url = "http://localhost:8061" ; + console.println("file url replaced by: "+url) ; + } else { + if (url.indexOf("://")<0) { + url = "http://" + url ; + } + if (example_log) { + console.println("url before check: "+url) ; + } +% url = url.replace(/(http:\\\/\\\/.+)(\\\/.*$)/, "$1") ; + url = url.replace(/(https*:\\\/\\\/.+?)(\\\/.*$)/, "$1/exarequest") ; + if (example_log) { + console.println("url after check: "+url) ; + } + } + return url ; + } + + function set_example_xfdf ( method ) { + example_method = method ; + } + + function set_example_file ( file ) { + example_method = file ; + } + + function set_example_host ( host ) { + example_host = host ; + } + + function set_example_port ( port ) { + example_host = host ; + } + + function do_erase_example_file(tag) { + f = this.getField(tag) ; + if (f) { + f.value = "" ; + } + } + + function do_erase_example_list(tag) { + for (i=1;i<=100;i++) { + f = this.getField(tag+"-"+i) ; + if (f) { + f.value = "" ; + } else { + return + } + } + } + + function do_submit_example_url ( url ) { + if ((example_method == "XFDF" ) || (url.indexOf("localhost")>=0)) { + do_erase_example_file("fakename") ; + do_erase_example_list("fakename") ; + } + url = check_example_url(url) ; + if (example_log) { + console.println("submitting form to "+url+" using method "+example_method) ; + } + if (example_file != "") { + url = url + "/" + example_file ; + } + % we need the bFDF for acrobat 5 + this.submitForm({cURL : url, bFDF : false, cSubmitAs : example_method}) ; + } + + function submit_example_form ( ) { + identify_example_url() ; + if (example_host != "") { + if (example_port != "") { + do_submit_example_url(example_host+":"+example_port) ; + } else { + do_submit_example_url(example_host) ; + } + } else { + if (example_url != "") { + do_submit_example_url(example_url) ; + } else { + if (example_port != "") { + do_submit_example_url("localhost"+":"+example_port) ; + } else { + do_submit_example_url("localhost:8061") ; % local exampler + } + } + } + resetfilename () ; + } + + function submit_form ( host, port) { + set_example_host(host) ; + set_example_post(post) ; + submit_example_form ; + } + +\stopJSpreamble + +\startJSpreamble request_2 used now + + var exa_command = "" ; + var exa_option = "" ; + var exa_filename = "" ; + var exa_filelist = "" ; + var exa_registered = "" ; + + function set_request (command,option) { + exa_command = command ; + if (exa_command == "") { + exa_option = option ; + } else { if (option == "") { + exa_option = "" ; + } else { if (option.indexOf("--")<0) { + exa_option = "--action=" + option ; + } else { + exa_option = option ; + } } } + } + + function assemble_request ( ) { + v = this.getField('filename') ; + if (v) { + exa_filename = v.value ; + } + v = this.getField('filelist') ; + if (v) { + exa_filelist = v.value ; + } +% exa_filename = exa_filename.replace(/\\\\/g,'/') ; +% exa_filelist = exa_filelist.replace(/\\\\/g,'/') ; + str = "\\n" ; + str = str+"" ; + if (exa_filelist == "") { + exa_filelist = exa_registered ; + } else { if (exa_registered != "") { + exa_filelist = exa_filelist + "\\n" + exa_registered ; + } } + if (exa_command != "") { + str = str+""+exa_command+"" ; + } + if (exa_option != "") { + str = str+""+exa_option+"" ; + } + if (exa_filename != "") { + str = str+""+exa_filename+"" ; + } + var fls = "" ; + if (exa_filelist != "") { + % old method, soon obsolete + lst = exa_filelist.split(/\\s/) ; + for (i=0;i"+lst[i]+"" ; + } + } else { if (exa_multiple) { + for (i=1;i<=100;i++) { + % console.println("file field "+i) ; + f = this.getField("filename-"+ i) ; +% if (f) { if (f.value != "") { +% if (g) { if (g.value == "") { +% fls = fls+""+f.value+"" ; +% } else { +% fls = fls+""+f.value+"" ; +% } } else { +% fls = fls+""+f.value+"" ; +% } +% } } + if (f) { if (f.value != "") { + fls = fls + "" ; + } else { + % console.println("b") ; + fls = fls + " label='" + g.value + "'>" ; + } } else { + % console.println("c") ; + fls = fls + ">" ; + } + fls = fls + f.value + "" ; + } } + } + } } + if (fls != "") { + str = str + "" + fls + "" ; + } + str = str + "" ; + v = this.getField('exa:request') ; + if (v) { + v.value = str ; + } + } + +\stopJSpreamble + +\startJSpreamble request_3 used now + + var exa_multiple = false ; + + function setfilename ( suffixes ) { + if (event.targetName) { + var name = event.targetName ; + var fake = name.replace(/filename/,"fakename") ; + } else { + var name = 'filename' ; + var fake = 'fakename' ; + } + f = this.getField(fake) ; + if (f) { + f.browseForFileToSubmit() ; + if ((suffixes != "") && (f.value != "")) { + % + s = suffixes.replace(/,/g,"|") ; + r = new RegExp() ; + s = "\\\\.(" + s + ")$" ; + r.compile(s, "i") ; + if (f.value.search(r)<=0) { + f.value = "" ; + app.alert('This filetype is not permitted.') ; + % + % lst = suffixes.split(/,/) ; + % ok = false ; + % for (i=0;i=0) { +% f.value = "" ; +% } +% } + } + this.dirty = false ; + } + + function addfilename () { + if (exa_multiple) { + h = this.getField("filelist") ; + g = this.getField("filename") ; + if ((g) && (h)) { + str = g.value ; + if (h.value == "") { + h.value = str ; + } else { + h.value = h.value + "\\n" + str ; + } + g.value = "" ; + this.value = "" ; + } + } + this.dirty = false ; + } + + % this only works with client that assembles request + + function registerfilename (str) { + if (str!="") { + h = this.getField("filelist") ; + if (h) { + if (h.value != "") { + h.value = h.value + "\\n" ; + } + h.value = h.value + str ; + } else { + if (exa_registered != "") { + exa_registered = exa_registered + "\\n" ; + } + exa_registered = exa_registered + str ; + } + } + console.show ; + console.println('registered files') ; + console.println("file: "+str) ; + console.println("list: "+exa_registered) ; + this.dirty = false ; + } + + function checkfilename () { + } + + function getfilename ( suffixes ) { + setfilename(suffixes) ; + checkfilename() ; + addfilename() ; + } + + function resetfilename () { + do_erase_example_file("fakename") ; + do_erase_example_file("filename") ; + do_erase_example_file("filelist") ; + do_erase_example_list("filename") ; + do_erase_example_list("fakename") ; + } + +\stopJSpreamble + +\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fields.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fields.mkiv new file mode 100644 index 00000000000..5801c321636 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fields.mkiv @@ -0,0 +1,648 @@ +%D \module +%D [ file=java-imp-fields, % was java-fld +%D version=1998.05.20, +%D title=\CONTEXT\ JavaScript Macros, +%D subtitle=Field Support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In \LUATEX\ the following does not work out well: +%D +%D \starttyping +%D v = v.replace(/\\\\"e/g,"\\353") ; +%D \stoptyping +%D +%D But this does: +%D +%D \starttyping +%D v = String(v).replace(/\\\\"e/g,"\\353") ; +%D \stoptyping +%D +%D Probably a \UNICODE\ issue. Beware, in \MKIV\ we have a +%D different escaping of \type {\\}. +%D +%D Watch out: cf. the latest pdf specification we've changed On into Yes. Also, +%D we've changed the test for the on value into !Off as we dón't know what value it +%D gets in the reader. + +% Is this still okay? We can have unicode now, can't we? Anyway it's kind of +% messy and unneeded in these unicode times. + +\startluasetups javascript:pdfencoding + local ctx_verbatim = context.verbatim + local utfbyte = utf.byte + local sortedhash = table.sortedhash + + ctx_verbatim("{\n") + for accent, group in sortedhash(characters.tex.accentmapping) do + for character, mapping in sortedhash(group) do + if character == "" then + character = " " + end + if accent == '"' then + ctx_verbatim(" '\\\\%s%s' : '\\u%04X',\n",accent,character,utfbyte(mapping)) + else + ctx_verbatim(' "\\\\%s%s" : "\\u%04X",\n',accent,character,utfbyte(mapping)) + end + end + end + for command, mapping in sortedhash(characters.tex.commandmapping) do + ctx_verbatim(' "\\\\%s" : "\\u%04X",\n',command,utfbyte(mapping)) + end + -- ctx_verbatim(" '\\\\<<' : '\\u00AB',\n") + -- ctx_verbatim(" '\\\\>>' : '\\u00BB',\n") + ctx_verbatim("}\n") + +\stopluasetups + +% maybe make { } tex braces in javascript code so that we can call lua + +\def\JavaScriptTeXAccentMapping{\luasetup{javascript:pdfencoding}} + +\startJSpreamble SanitizeTeXInput used later + +var TeXAccentMapping = \JavaScriptTeXAccentMapping + +function TeX_Replacer(original,str) { + return (TeXAccentMapping[str] || str) ; +} + +function Sanitized_TeX_String(value) { + return (value.replace(/(\\..)/g, TeX_Replacer)) ; +} + +var TeX_Key_Mode = 0 ; +var TeX_Key_Char = "" ; + +function Initialize_TeX_Keystroke() { + TeX_Key_Char = "" ; + TeX_Key_Mode = 0 ; +} + +function Sanitized_TeX_Keystroke(change) { + if (!event.willCommit) { + if (change=="\\") { + TeX_Key_Mode = 1 ; + return ("") + } else if (TeX_Key_Mode == 1) { + TeX_Key_Mode = 2 ; + TeX_Key_Char = change ; + return ("") + } else if (TeX_Key_Mode == 2) { + TeX_Key_Mode = 0 ; + TeX_Key_Char = "\\"+TeX_Key_Char+change ; + return (Sanitized_TeX_String(TeX_Key_Char)) + } else { + TeX_Key_Mode = 0 ; + return (change) + } + } +} + +function Initialize_TeX_Key() { + Initialize_TeX_Keystroke() ; +} + +function Convert_TeX_Key() { + if (!event.willCommit) { + event.change = Sanitized_TeX_Keystroke(event.change) ; + } +} + +function Convert_TeX_String() { + event.value = Sanitized_TeX_String(event.value) ; +} + +\stopJSpreamble + +% \startJScode {Initialize_TeX_Key} uses {SanitizeTeXInput} +% Initialize_TeX_Keystroke() ; +% \stopJScode +% +% \startJScode {Convert_TeX_Key} uses {SanitizeTeXInput} +% if (!event.willCommit) { +% event.change = Sanitized_TeX_Keystroke(event.change) ; +% } +% \stopJScode +% +% \startJScode{Convert_TeX_String} uses {SanitizeTeXInput} +% event.value = Sanitized_TeX_String(event.value) ; +% \stopJScode + +% was used now but we autocheck anyway so lets test this for a while + +\startJSpreamble FieldsStates used later + +var visible_field = new Array() ; +var visible_fields = 0 ; + +function PresetFields() { + this.syncAnnotScan() ; +} + +function Preset_Fields() { + this.syncAnnotScan() ; +} + +function Hide_When_Down() { + event.target.hidden = true ; +} + +function Hide_Field(Name) { + var v = this.getField(Name) ; + if (v) { + v.hidden = true ; + v.readonly = true ; + this.dirty = false ; + } +} + +function Do_Vide_Field(Name, Closable) { + var v = this.getField(Name) ; + if (v) { + ++visible_fields ; + visible_field[visible_fields] = Name ; + v.hidden = false ; + if (Closable) { + v.readonly = false ; + v.value = "Yes" ; + } + this.dirty = false ; + } +} + +function Vide_Field(Name) { + Do_Vide_Field(Name,false) ; +} + +function Vide_Hide_Field(Name) { + Do_Vide_Field(Name,true) ; +} + +function Hide_Fields() { + while (visible_fields>0) { + Hide_Field(visible_field[visible_fields]) ; + --visible_fields ; + } +} + +function Vide_Fields(Name) { + Hide_Fields() ; + Vide_Field(Name) ; +} + +function Vide_Hide_Fields(Name) { + Hide_Fields() ; + Vide_Hide_Field(Name) ; +} + +function Toggle_Hide(Name) { + var v = this.getField(Name) ; + if (v) { + v.hidden = !v.hidden ; + this.dirty = false ; + } +} + +function Field_On(Name) { + v = this.getField(Name) ; + if (v) { + v.value = "Yes" ; + this.dirty = false ; + } +} + +function Field_Off(Name) { + var v = this.getField(Name) ; + if (v) { + v.value = "Off" ; + this.dirty = false ; + } +} + +function Toggle_Value(Name) { + var v = this.getField(Name) ; + if (v) { + if (v.value != "Off") { + v.value = "Off" ; + } else { + v.value = "Yes" ; + } + } + this.dirty = false ; +} + +function Toggle_Read(Name) { + var v = this.getField(Name); + if (v) { + v.readonly = !v.readonly ; + } +} + +function Flip_Fields(Name) { + var Names = Name.split(",") ; + for (var i=0; i < Names.length; i++) { + v = this.getField(Names[i]) ; + if (v) { + v.hidden = !v.hidden ; + v.value = "Yes" ; + } + } +} + +function Forget_Changes() { + this.dirty = false ; +} + +function ForgetChanges() { + this.dirty = false ; +} + +function Step_Fields (Name, First, Last) { + for (var i = Number(First) ; i <= Number(Last) ; i++) { + var s = Name + ":" + i ; + var v = this.getField(s) ; + if (v) { + ++visible_fields ; + visible_field[visible_fields] = s ; + if (v.hidden) { + v.hidden = false ; + this.dirty = false ; + return ; + } + } + } +} +\stopJSpreamble + +\definereference[VideFields] [JS(Vide_Fields)] +\definereference[HideFields] [JS(Hide_Fields)] +\definereference[ForgetChanges][JS(Forget_Changes)] +\definereference[StepFields] [JS(Step_Fields)] + +% This can be done more efficient, by keeping track of the +% current top of the stack. + +\startJSpreamble FieldStack used later + +function Field_Name(FieldSet,i) { + return this.getField(FieldSet + ":" + i) +} + +function Reset_Fields(FieldSet) { + var i = 1 ; + while (true) { + var v = Field_Name(FieldSet,i) ; + if (!v) { + break ; + } else { + v.value = "Off" ; + } + i++ ; + } + this.dirty = false ; +} + +function Set_Fields(FieldSet) { + var i = 1 ; + while (true) { + var v = Field_Name(FieldSet,i) ; + if (!v) { + break ; + } else { + v.value = "Yes" ; + } + i++ ; + } + this.dirty = false ; +} + +function Set_Field(FieldSet, FieldName) { + Reset_Fields(FieldSet) ; + var v = Field_Name(FieldSet,FieldName) ; + if (v) { + v.value = "Yes" ; + this.dirty = false ; + } +} + +function Reset_Field(FieldSet, FieldName) { + Set_Fields(FieldSet) ; + var v = Field_Name(FieldSet,FieldName) ; + if (v) { + v.value = "Off" ; + this.dirty = false ; + } +} + +function Walk_Field(FieldSet) { + var i = 1 ; + this.syncAnnotScan(); + while (true) { + var v = Field_Name(FieldSet,i) ; + if (v) { + if (v.value != "Off") { + v.value = "Off" ; + v = Field_Name(FieldSet,i + 1) ; + if (! v) { + v = Field_Name(FieldSet,1) ; + } else { + } + if (v) { + v.value = "Yes" ; + } + break ; + } + i++ ; + } else { + v = Field_Name(FieldSet,1) ; + if (v) { + v.value = "Yes" ; + } + break ; + } + } + this.dirty = false ; +} + +var FieldSets = new Array() ; + +function Do_Get_Check_Walk_Field(FieldSet) { + var f = FieldSets[FieldSet] + if (! f) { + f = new Array() ; + f.number = 0 ; + f.delay = 500 ; + f.paused = false ; + f.running = false ; + f.name = FieldSet ; + f.timeout = null ; + f.repeat = true ; + f.total = 0 ; + f.pauseset = new Array() ; + FieldSets[FieldSet] = f ; + for (var i=1; i>0; i++) { + var v = Field_Name(FieldSet,i) ; + if (! v) { + f.total = i - 1 ; + break ; + } + } + f.start = 0 ; + f.stop = f.total ; + f.pause = 0 ; + } + this.dirty = false ; + return f +} + +function Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,n) { + var v = Field_Name(FieldSet,fieldset.number) ; + if (v) { + if (v.value != "Off") { + v.value = "Off" ; + } + } + v = Field_Name(FieldSet,n) ; + if (v) { + fieldset.number = n ; + v.value = "Yes" ; + if (fieldset.pauseset[n]) { + // fieldset.pause = n ; + // Do_Stop_Auto_Walk_Field(Fieldset) ; + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.paused = true ; + } + } + this.dirty = false ; +} + +function Do_Next_Auto_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + if (fieldset.number >= fieldset.stop) { + if (fieldset.repeat == false) { + fieldset.running = false ; + Do_Stop_Auto_Walk_Field(fieldset) ; + } else { + Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.start) ; + } + } else { + Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.number+1) ; + } + this.dirty = false ; + } +} + +function Do_Stop_Auto_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + try { + app.clearInterval(fieldset.timeout) ; + app.clearTimeOut(fieldset.timeout) ; + } catch (e) { + } + this.dirty = false ; + } +} + +function Do_Start_Auto_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + Do_Next_Auto_Walk_Field(FieldSet) ; + fieldset.timeout = app.setInterval("Do_Next_Auto_Walk_Field('"+FieldSet+"')", fieldset.delay) ; + this.dirty = false ; + } +} + +function Start_Walk_Field(FieldSet, Delay) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + fieldset.number = 0 ; + if (Delay) { + fieldset.delay = Delay ; + } + Reset_Fields(FieldSet) ; + Do_Start_Auto_Walk_Field(FieldSet) ; + fieldset.running = true ; + fieldset.paused = false ; + } +} + +function Pause_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + if (fieldset.running) { + if (fieldset.paused) { + Do_Start_Auto_Walk_Field(FieldSet) ; + fieldset.paused = false ; + } else { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.paused = true ; + } + } + } +} + +function Start_Pause_Walk_Field(FieldSet, Delay, Option) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + if (Option == "once") { + fieldset.repeat = false ; + } else if (Option == "pause") { + fieldset.repeat = false ; + } else { + fieldset.repeat = true ; + } + if (Option == "pause") { + for (i=3; i 1) { + fieldset.start = fieldset.pause - 1 ; + } else { + fieldset.start = 1 ; + } + fieldset.stop = fieldset.total ; + } else { + var Start = arguments[3] ; + var Stop = arguments[4] ; + if (typeof Start == "string") { + fieldset.start = parseInt(Start) ; + } else if (typeof Start == "number") { + fieldset.start = Start ; + } else { + fieldset.start = 1 ; + } + if (typeof Stop == "string") { + fieldset.stop = parseInt(Stop) ; + } else if (typeof Stop == "number") { + fieldset.stop = Stop ; + } else { + fieldset.stop = fieldset.total ; + } + fieldset.pause = 0 ; + } + if (fieldset.running) { + if (fieldset.paused) { + Do_Start_Auto_Walk_Field(FieldSet) ; + fieldset.paused = false ; + } else { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.paused = true ; + } + } else { + fieldset.number = fieldset.start - 1 ; + if (Delay) { + fieldset.delay = Delay ; + } + Reset_Fields(FieldSet) ; + Do_Start_Auto_Walk_Field(FieldSet) ; + fieldset.running = true ; + fieldset.paused = false ; + } + } +} + +function Stop_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.running = false ; + fieldset.paused = false ; + } +} + +function Reset_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.number = 0 ; + fieldset.running = false ; + fieldset.paused = false ; + Reset_Fields(FieldSet) ; + } +} + +function Previous_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.running = false ; + fieldset.paused = false ; + if (fieldset.number>0) { + var v = Field_Name(FieldSet,fieldset.number) ; + if (v) { + if (v.value != "Off") { + v.value = "Off" ; + } + } + fieldset.number-- ; + v = Field_Name(FieldSet,fieldset.number) ; + if (v) { + v.value = "Yes" ; + } + this.dirty = false ; + } + } +} + +function Next_Walk_Field(FieldSet) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + fieldset.running = false ; + fieldset.paused = false ; + var f = fieldset.number + 1 ; + var v = Field_Name(FieldSet,f) ; + if (v) { + var v = Field_Name(FieldSet,fieldset.number) ; + if (v) { + if (v.value != "Off") { + v.value = "Off" ; + } + } + fieldset.number++ ; + v = Field_Name(FieldSet,fieldset.number) ; + if (v) { + v.value = "Yes" ; + } + this.dirty = false ; + } + } +} + +function Set_Walk_Field_Delay(FieldSet, Delay) { + var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; + if (fieldset) { + if (Delay) { + fieldset.delay = Delay ; + if (fieldset.running) { + Do_Stop_Auto_Walk_Field(FieldSet) ; + Do_Start_Auto_Walk_Field(FieldSet) ; + } + } + } +} + +\stopJSpreamble + +\definereference[Walk] [JS(Walk_Field)] +\definereference[StartWalk] [JS(Start_Walk_Field)] +\definereference[StopWalk] [JS(Stop_Walk_Field)] +\definereference[PauseWalk] [JS(Pause_Walk_Field)] +\definereference[ResetWalk] [JS(Reset_Walk_Field)] +\definereference[PreviousWalk][JS(Previous_Walk_Field)] +\definereference[NextWalk] [JS(Next_Walk_Field)] +\definereference[SetWalkDelay][JS(Set_Walk_Field_Delay)] + +\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv deleted file mode 100644 index 808950f2807..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fil.mkiv +++ /dev/null @@ -1,52 +0,0 @@ -%D \module -%D [ file=java-fil, -%D version=1998.06.01, -%D title=\CONTEXT\ JavaScript Macros, -%D subtitle=Filing and Printing, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\startJSpreamble Auxiliary used now - - function DocumentFileName() { - var Paths = this.path.split("/") ; - Paths = Paths[Paths.length-1].split(".") ; - return(Paths[0]) - } - - function Print_Page_Range(From,To) { - if ((Number(From)>0) && (Number(To) >= Number(From))) { - var myFrom = Number(From)-1 ; - var myTo = Number(To)-1 ; - this.print(false,myFrom,myTo,true) ; - } - } - - function Print_This_Page() { - this.print(false,this.pageNum,this.pageNum,true) ; - } - -\stopJSpreamble - -\definereference - [PrintSubPaginas] - [JS(Print_Page_Range{\firstsubpage,\lastsubpage})] - -\definereference - [PrintSubPages] - [JS(Print_Page_Range{\firstsubpage,\lastsubpage})] - -\definereference - [PrintDezePagina] - [JS(Print_This_Page)] - -\definereference - [PrintThisPage] - [JS(Print_This_Page)] - -\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv deleted file mode 100644 index cbd53fffb4a..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/java-imp-fld.mkiv +++ /dev/null @@ -1,625 +0,0 @@ -%D \module -%D [ file=java-fld, -%D version=1998.05.20, -%D title=\CONTEXT\ JavaScript Macros, -%D subtitle=Field Support, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D In \LUATEX\ the following does not work out well: -%D -%D \starttyping -%D v = v.replace(/\\\\"e/g,"\\353") ; -%D \stoptyping -%D -%D But this does: -%D -%D \starttyping -%D v = String(v).replace(/\\\\"e/g,"\\353") ; -%D \stoptyping -%D -%D Probably a \UNICODE\ issue. Beware, in \MKIV\ we have a -%D different escaping of \type {\\}. -%D -%D Watch out: cf. the latest pdf specification we've changed -%D On into Yes. Also, we've changed the test for the on value -%D into !Off as we dón't know what value it gets in the reader. - -% Is this still okay? We can have unicode now, can't we? Anyway it's kind of -% messy and unneeded in these unicode times. - -\startluasetups javascript:pdfencoding - local ctx_verbatim = context.verbatim - local utfbyte = utf.byte - local sortedhash = table.sortedhash - - ctx_verbatim("{\n") - for accent, group in sortedhash(characters.tex.accentmapping) do - for character, mapping in sortedhash(group) do - if character == "" then - character = " " - end - if accent == '"' then - ctx_verbatim(" '\\\\%s%s' : '\\u%04X',\n",accent,character,utfbyte(mapping)) - else - ctx_verbatim(' "\\\\%s%s" : "\\u%04X",\n',accent,character,utfbyte(mapping)) - end - end - end - for command, mapping in sortedhash(characters.tex.commandmapping) do - ctx_verbatim(' "\\\\%s" : "\\u%04X",\n',command,utfbyte(mapping)) - end - -- ctx_verbatim(" '\\\\<<' : '\\u00AB',\n") - -- ctx_verbatim(" '\\\\>>' : '\\u00BB',\n") - ctx_verbatim("}\n") - -\stopluasetups - -% maybe make { } tex braces in javascript code so that we can call lua - -\def\JavaScriptTeXAccentMapping{\luasetup{javascript:pdfencoding}} - -\startJSpreamble SanitizeTeXInput used later - -var TeXAccentMapping = \JavaScriptTeXAccentMapping - -function TeX_Replacer(original,str) { - return (TeXAccentMapping[str] || str) ; -} - -function Sanitized_TeX_String(value) { - return (value.replace(/(\\..)/g, TeX_Replacer)) ; -} - -var TeX_Key_Mode = 0 ; -var TeX_Key_Char = "" ; - -function Initialize_TeX_Keystroke() { - TeX_Key_Char = "" ; - TeX_Key_Mode = 0 ; -} - -function Sanitized_TeX_Keystroke(change) { - if (!event.willCommit) { - if (change=="\\") { - TeX_Key_Mode = 1 ; - return ("") - } else if (TeX_Key_Mode == 1) { - TeX_Key_Mode = 2 ; - TeX_Key_Char = change ; - return ("") - } else if (TeX_Key_Mode == 2) { - TeX_Key_Mode = 0 ; - TeX_Key_Char = "\\"+TeX_Key_Char+change ; - return (Sanitized_TeX_String(TeX_Key_Char)) - } else { - TeX_Key_Mode = 0 ; - return (change) - } - } -} - -function Initialize_TeX_Key() { - Initialize_TeX_Keystroke() ; -} - -function Convert_TeX_Key() { - if (!event.willCommit) { - event.change = Sanitized_TeX_Keystroke(event.change) ; - } -} - -function Convert_TeX_String() { - event.value = Sanitized_TeX_String(event.value) ; -} - -\stopJSpreamble - -% \startJScode {Initialize_TeX_Key} uses {SanitizeTeXInput} -% Initialize_TeX_Keystroke() ; -% \stopJScode -% -% \startJScode {Convert_TeX_Key} uses {SanitizeTeXInput} -% if (!event.willCommit) { -% event.change = Sanitized_TeX_Keystroke(event.change) ; -% } -% \stopJScode -% -% \startJScode{Convert_TeX_String} uses {SanitizeTeXInput} -% event.value = Sanitized_TeX_String(event.value) ; -% \stopJScode - -% was used now but we autocheck anyway so lets test this for a while - -\startJSpreamble FieldsStates used later - -var visible_field = new Array() ; -var visible_fields = 0 ; - -function PresetFields() { - this.syncAnnotScan() ; -} - -function Preset_Fields() { - this.syncAnnotScan() ; -} - -function Hide_When_Down() { - event.target.hidden = true ; -} - -function Hide_Field(Name) { - var v = this.getField(Name) ; - if (v) { - v.hidden = true ; - v.readonly = true ; - this.dirty = false ; - } -} - -function Do_Vide_Field(Name, Closable) { - var v = this.getField(Name) ; - if (v) { - ++visible_fields ; - visible_field[visible_fields] = Name ; - v.hidden = false ; - if (Closable) { - v.readonly = false ; - v.value = "Yes" ; - } - this.dirty = false ; - } -} - -function Vide_Field(Name) { - Do_Vide_Field(Name,false) ; -} - -function Vide_Hide_Field(Name) { - Do_Vide_Field(Name,true) ; -} - -function Hide_Fields() { - while (visible_fields>0) { - Hide_Field(visible_field[visible_fields]) ; - --visible_fields ; - } -} - -function Vide_Fields(Name) { - Hide_Fields() ; - Vide_Field(Name) ; -} - -function Vide_Hide_Fields(Name) { - Hide_Fields() ; - Vide_Hide_Field(Name) ; -} - -function Toggle_Hide(Name) { - var v = this.getField(Name) ; - if (v) { - v.hidden = !v.hidden ; - this.dirty = false ; - } -} - -function Field_On(Name) { - v = this.getField(Name) ; - if (v) { - v.value = "Yes" ; - this.dirty = false ; - } -} - -function Field_Off(Name) { - var v = this.getField(Name) ; - if (v) { - v.value = "Off" ; - this.dirty = false ; - } -} - -function Toggle_Value(Name) { - var v = this.getField(Name) ; - if (v) { - if (v.value != "Off") { - v.value = "Off" ; - } else { - v.value = "Yes" ; - } - } - this.dirty = false ; -} - -function Toggle_Read(Name) { - var v = this.getField(Name); - if (v) { - v.readonly = !v.readonly ; - } -} - -function Flip_Fields(Name) { - var Names = Name.split(",") ; - for (var i=0; i < Names.length; i++) { - v = this.getField(Names[i]) ; - if (v) { - v.hidden = !v.hidden ; - v.value = "Yes" ; - } - } -} - -function Forget_Changes() { - this.dirty = false ; -} - -function ForgetChanges() { - this.dirty = false ; -} -\stopJSpreamble - -\definereference[ForgetChanges][JS(Forget_Changes)] - -% This can be done more efficient, by keeping track of the -% current top of the stack. - -\startJSpreamble FieldStack used later - -function Field_Name(FieldSet,i) { - return this.getField(FieldSet + ":" + i) -} - -function Reset_Fields(FieldSet) { - var i = 1 ; - while (true) { - v = Field_Name(FieldSet,i) ; - if (!v) { - break ; - } else { - v.value = "Off" ; - } - i++ ; - } - this.dirty = false ; -} - -function Set_Fields(FieldSet) { - var i = 1 ; - while (true) { - v = Field_Name(FieldSet,i) ; - if (!v) { - break ; - } else { - v.value = "Yes" ; - } - i++ ; - } - this.dirty = false ; -} - -function Set_Field(FieldSet, FieldName) { - Reset_Fields(FieldSet) ; - v = Field_Name(FieldSet,FieldName) ; - if (v) { - v.value = "Yes" ; - this.dirty = false ; - } -} - -function Reset_Field(FieldSet, FieldName) { - Set_Fields(FieldSet) ; - v = Field_Name(FieldSet,FieldName) ; - if (v) { - v.value = "Off" ; - this.dirty = false ; - } -} - -function Walk_Field(FieldSet) { - var i = 1 ; - while (true) { - v = Field_Name(FieldSet,i) ; - if (v) { - if (v.value != "Off") { - v.value = "Off" ; - var ii = i ; - ii++ ; - v = Field_Name(FieldSet,ii) ; - if (! v) { - v = Field_Name(FieldSet,1) ; - } - if (v) { - v.value = "Yes" ; - } - break ; - } - i++ ; - } else { - break ; - } - } - this.dirty = false ; -} - -var FieldSets = new Array() ; - -function Do_Get_Check_Walk_Field(FieldSet) { - var f = FieldSets[FieldSet] - if (! f) { - f = new Array() ; - f.number = 0 ; - f.delay = 500 ; - f.paused = false ; - f.running = false ; - f.name = FieldSet ; - f.timeout = null ; - f.repeat = true ; - f.total = 0 ; - f.pauseset = new Array() ; - FieldSets[FieldSet] = f ; - for (var i=1; i>0; i++) { - var v = Field_Name(FieldSet,i) ; - if (! v) { - f.total = i - 1 ; - break ; - } - } - f.start = 0 ; - f.stop = f.total ; - f.pause = 0 ; - } - this.dirty = false ; - return f -} - -function Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,n) { - var v = Field_Name(FieldSet,fieldset.number) ; - if (v) { - if (v.value != "Off") { - v.value = "Off" ; - } - } - v = Field_Name(FieldSet,n) ; - if (v) { - fieldset.number = n ; - v.value = "Yes" ; - if (fieldset.pauseset[n]) { - // fieldset.pause = n ; - // Do_Stop_Auto_Walk_Field(Fieldset) ; - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.paused = true ; - } - } - this.dirty = false ; -} - -function Do_Next_Auto_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - if (fieldset.number >= fieldset.stop) { - if (fieldset.repeat == false) { - fieldset.running = false ; - Do_Stop_Auto_Walk_Field(fieldset) ; - } else { - Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.start) ; - } - } else { - Do_Next_Auto_Walk_Field_Step(FieldSet,fieldset,fieldset.number+1) ; - } - this.dirty = false ; - } -} - -function Do_Stop_Auto_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - try { - app.clearInterval(fieldset.timeout) ; - app.clearTimeOut(fieldset.timeout) ; - } catch (e) { - } - this.dirty = false ; - } -} - -function Do_Start_Auto_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - Do_Next_Auto_Walk_Field(FieldSet) ; - fieldset.timeout = app.setInterval("Do_Next_Auto_Walk_Field('"+FieldSet+"')", fieldset.delay) ; - this.dirty = false ; - } -} - -function Start_Walk_Field(FieldSet, Delay) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - fieldset.number = 0 ; - if (Delay) { - fieldset.delay = Delay ; - } - Reset_Fields(FieldSet) ; - Do_Start_Auto_Walk_Field(FieldSet) ; - fieldset.running = true ; - fieldset.paused = false ; - } -} - -function Pause_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - if (fieldset.running) { - if (fieldset.paused) { - Do_Start_Auto_Walk_Field(FieldSet) ; - fieldset.paused = false ; - } else { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.paused = true ; - } - } - } -} - -function Start_Pause_Walk_Field(FieldSet, Delay, Option) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - if (Option == "once") { - fieldset.repeat = false ; - } else if (Option == "pause") { - fieldset.repeat = false ; - } else { - fieldset.repeat = true ; - } - if (Option == "pause") { - for (i=3; i 1) { - fieldset.start = fieldset.pause - 1 ; - } else { - fieldset.start = 1 ; - } - fieldset.stop = fieldset.total ; - } else { - var Start = arguments[3] ; - var Stop = arguments[4] ; - if (typeof Start == "string") { - fieldset.start = parseInt(Start) ; - } else if (typeof Start == "number") { - fieldset.start = Start ; - } else { - fieldset.start = 1 ; - } - if (typeof Stop == "string") { - fieldset.stop = parseInt(Stop) ; - } else if (typeof Stop == "number") { - fieldset.stop = Stop ; - } else { - fieldset.stop = fieldset.total ; - } - fieldset.pause = 0 ; - } - if (fieldset.running) { - if (fieldset.paused) { - Do_Start_Auto_Walk_Field(FieldSet) ; - fieldset.paused = false ; - } else { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.paused = true ; - } - } else { - fieldset.number = fieldset.start - 1 ; - if (Delay) { - fieldset.delay = Delay ; - } - Reset_Fields(FieldSet) ; - Do_Start_Auto_Walk_Field(FieldSet) ; - fieldset.running = true ; - fieldset.paused = false ; - } - } -} - -function Stop_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.running = false ; - fieldset.paused = false ; - } -} - -function Reset_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.number = 0 ; - fieldset.running = false ; - fieldset.paused = false ; - Reset_Fields(FieldSet) ; - } -} - -function Previous_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.running = false ; - fieldset.paused = false ; - if (fieldset.number>0) { - var v = Field_Name(FieldSet,fieldset.number) ; - if (v) { - if (v.value != "Off") { - v.value = "Off" ; - } - } - fieldset.number-- ; - v = Field_Name(FieldSet,fieldset.number) ; - if (v) { - v.value = "Yes" ; - } - this.dirty = false ; - } - } -} - -function Next_Walk_Field(FieldSet) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - fieldset.running = false ; - fieldset.paused = false ; - var f = fieldset.number + 1 ; - var v = Field_Name(FieldSet,f) ; - if (v) { - var v = Field_Name(FieldSet,fieldset.number) ; - if (v) { - if (v.value != "Off") { - v.value = "Off" ; - } - } - fieldset.number++ ; - v = Field_Name(FieldSet,fieldset.number) ; - if (v) { - v.value = "Yes" ; - } - this.dirty = false ; - } - } -} - -function Set_Walk_Field_Delay(FieldSet, Delay) { - var fieldset = Do_Get_Check_Walk_Field(FieldSet) ; - if (fieldset) { - if (Delay) { - fieldset.delay = Delay ; - if (fieldset.running) { - Do_Stop_Auto_Walk_Field(FieldSet) ; - Do_Start_Auto_Walk_Field(FieldSet) ; - } - } - } -} - -\stopJSpreamble - -\definereference[Walk] [JS(Walk_Field)] -\definereference[StartWalk] [JS(Start_Walk_Field)] -\definereference[StopWalk] [JS(Stop_Walk_Field)] -\definereference[PauseWalk] [JS(Pause_Walk_Field)] -\definereference[ResetWalk] [JS(Reset_Walk_Field)] -\definereference[PreviousWalk][JS(Previous_Walk_Field)] -\definereference[NextWalk] [JS(Next_Walk_Field)] -\definereference[SetWalkDelay][JS(Set_Walk_Field_Delay)] - -\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-highlight.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-highlight.mkiv new file mode 100644 index 00000000000..b55628f4b70 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-highlight.mkiv @@ -0,0 +1,34 @@ +%D \module +%D [ file=java-imp-highlightm, % was: java-rhh +%D version=2010.02.01, +%D title=\CONTEXT\ JavaScript Macros, +%D subtitle=Runtime Highlight Hack, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D As hightlighting is rather intrusive it makes sense to turn it off when +%D using nice appearances. + +% app.runtimeHighlightColor = [ "T" ] ; +% +% var SavedAlwaysShowFocus = app.alwaysShowFocus ; +% app.alwaysShowFocus = true ; +% "app.alwaysShowFocus = SavedAlwaysShowFocus ; " + +\startJSpreamble RuntimeHighlightHack used now + var SavedHighlightState = app.runtimeHighlight ; + var SavedFocusRectState = app.focusRect ; + app.runtimeHighlight = false ; + app.focusRect = true ; + this.setAction("WillClose", + "app.runtimeHighlight = SavedHighlightState ; " + + "app.focusRect = SavedFocusRectState ; " + ) ; +\stopJSpreamble + +\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-print.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-print.mkiv new file mode 100644 index 00000000000..3d5325ff057 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-print.mkiv @@ -0,0 +1,52 @@ +%D \module +%D [ file=java-imp-print, % was: java-fil +%D version=1998.06.01, +%D title=\CONTEXT\ JavaScript Macros, +%D subtitle=Filing and Printing, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\startJSpreamble auxiliary used now + + function DocumentFileName() { + var Paths = this.path.split("/") ; + Paths = Paths[Paths.length-1].split(".") ; + return(Paths[0]) + } + + function Print_Page_Range(From,To) { + if ((Number(From)>0) && (Number(To) >= Number(From))) { + var myFrom = Number(From)-1 ; + var myTo = Number(To)-1 ; + this.print(false,myFrom,myTo,true) ; + } + } + + function Print_This_Page() { + this.print(false,this.pageNum,this.pageNum,true) ; + } + +\stopJSpreamble + +\definereference + [PrintSubPaginas] + [JS(Print_Page_Range{\firstsubpage,\lastsubpage})] + +\definereference + [PrintSubPages] + [JS(Print_Page_Range{\firstsubpage,\lastsubpage})] + +\definereference + [PrintDezePagina] + [JS(Print_This_Page)] + +\definereference + [PrintThisPage] + [JS(Print_This_Page)] + +\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv deleted file mode 100644 index 5f057f55070..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/java-imp-rhh.mkiv +++ /dev/null @@ -1,34 +0,0 @@ -%D \module -%D [ file=java-rhh, -%D version=2010.02.01, -%D title=\CONTEXT\ JavaScript Macros, -%D subtitle=Runtime Highlight Hack, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D As hightlighting is rather intrusive it makes sense to turn it off when -%D using nice appearances. - -% app.runtimeHighlightColor = [ "T" ] ; -% -% var SavedAlwaysShowFocus = app.alwaysShowFocus ; -% app.alwaysShowFocus = true ; -% "app.alwaysShowFocus = SavedAlwaysShowFocus ; " - -\startJSpreamble RuntimeHighlightHack used now - var SavedHighlightState = app.runtimeHighlight ; - var SavedFocusRectState = app.focusRect ; - app.runtimeHighlight = false ; - app.focusRect = true ; - this.setAction("WillClose", - "app.runtimeHighlight = SavedHighlightState ; " + - "app.focusRect = SavedFocusRectState ; " - ) ; -\stopJSpreamble - -\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/java-imp-steps.mkiv b/Master/texmf-dist/tex/context/base/mkiv/java-imp-steps.mkiv new file mode 100644 index 00000000000..3990e4d7ac4 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/java-imp-steps.mkiv @@ -0,0 +1,123 @@ +%D \module +%D [ file=java-imp-steps, % was: java-stp +%D version=2004.03.15, +%D title=\CONTEXT\ JavaScript Macros, +%D subtitle=Stepping, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% we define ocglist global, otherwise we quickly run into a memory hog (even +% out of memory in a 512 Meg machine) + +% we cannot use doc_visited[this.pageNum] instead of doc_currentstep because +% of some funny side effect (i.e. dup or so) + +% todo: test with later as we do autoinsert now + +\startJSpreamble Steps used now + +var doc_ocglist = this.getOCGs() ; +var doc_stepname = "step" ; +var doc_currentstep = 0 ; +var doc_maxstep = 50 ; +var doc_visited = new Array() ; +var doc_busy = new Array() ; + +function SetupStepper(layername,laststep) { + doc_stepname = layername ; + doc_maxstep = laststep ; + for (var i=0; i<=this.numPages; i++) { + doc_visited[i] = 0 ; + doc_busy[i] = 0 ; + } +} + +for (var i=0; i<=this.numPages; i++) { + doc_visited[i] = 0 ; + doc_busy[i] = 0 ; +} + +function GetOCG(name) { + for (var i=0; i < doc_ocglist.length; i++) { + if (doc_ocglist[i].name == name) { + return doc_ocglist[i] ; + } + } + return null ; +} + +function CheckBusy() { + var ocg = GetOCG("step:busy") ; + if (ocg != null) { + if (doc_visited[this.pageNum]==0) { + ocg.state = true ; + } else { + if (doc_visited[this.pageNum]= first and b <= last - end - -- tricky, these nested captures - return utf8byte / f -- nil when invalid range - end -end - --- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) - -- lpeg.print(lpeg.R("ab","cd","gh")) -- lpeg.print(lpeg.P("a","b","c")) -- lpeg.print(lpeg.S("a","b","c")) @@ -944,7 +888,7 @@ local function make2(t,rest) -- only ascii return p end -function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg +local function utfchartabletopattern(list,insensitive) -- goes to util-lpg local tree = { } local n = #list if n == 0 then @@ -1022,6 +966,15 @@ function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg return (insensitive and make2 or make1)(tree) end +lpeg.utfchartabletopattern = utfchartabletopattern + +function lpeg.utfreplacer(list,insensitive) + local pattern = Cs((utfchartabletopattern(list,insensitive)/list + utf8character)^0) + return function(str) + return lpegmatch(pattern,str) or str + end +end + -- local t = { "start", "stoep", "staart", "paard" } -- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) @@ -1119,25 +1072,38 @@ end -- moved here (before util-str) ------ digit = R("09") ------ period = P(".") ------ zero = P("0") -local trailingzeros = zero^0 * -digit -- suggested by Roberto R -local case_1 = period * trailingzeros / "" -local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") -local number = digits * (case_1 + case_2) -local stripper = Cs((number + 1)^0) +do + + local trailingzeros = zero^0 * -digit -- suggested by Roberto + local stripper = Cs(( + digits * ( + period * trailingzeros / "" + + period * (digit - trailingzeros)^1 * (trailingzeros / "") + ) + 1 + )^0) -lpeg.patterns.stripzeros = stripper + lpeg.patterns.stripzeros = stripper -- multiple in string --- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" --- collectgarbage("collect") --- str = string.rep(sample,10000) --- local ts = os.clock() --- lpegmatch(stripper,str) --- print(#str, os.clock()-ts, lpegmatch(stripper,sample)) + local nonzero = digit - zero + local trailingzeros = zero^1 * endofstring + local stripper = Cs( (1-period)^0 * ( + period * trailingzeros/"" + + period * (nonzero^1 + (trailingzeros/"") + zero^1)^0 + + endofstring + )) + + lpeg.patterns.stripzero = stripper -- slightly more efficient but expects a float ! + + -- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" + -- collectgarbage("collect") + -- str = string.rep(sample,10000) + -- local ts = os.clock() + -- lpegmatch(stripper,str) + -- print(#str, os.clock()-ts, lpegmatch(stripper,sample)) + +end --- for practical reasone we keep this here: +-- for practical reasons we keep this here: local byte_to_HEX = { } local byte_to_hex = { } @@ -1209,3 +1175,22 @@ end -- local h = "ADFE0345" -- local b = lpegmatch(patterns.hextobytes,h) -- print(h,b,string.tohex(b),string.toHEX(b)) + +local patterns = { } -- can be made weak + +local function containsws(what) + local p = patterns[what] + if not p then + local p1 = P(what) * (whitespace + endofstring) * Cc(true) + local p2 = whitespace * P(p1) + p = P(p1) + P(1-p2)^0 * p2 + Cc(false) + patterns[what] = p + end + return p +end + +lpeg.containsws = containsws + +function string.containsws(str,what) + return lpegmatch(patterns[what] or containsws(what),str) +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua index 426706f06d6..d8989364ed5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-lua.lua @@ -35,8 +35,6 @@ if LUAVERSION < 5.2 and jit then LUAVERSION = 5.2 end -_LUAVERSION = LUAVERSION -- for old times sake, will go away - -- lpeg if not lpeg then @@ -230,23 +228,27 @@ elseif not ffi.number then ffi.number = tonumber end -if not bit32 then -- and utf8 then - -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] ) - bit32 = require("l-bit32") -end +-- if not bit32 then -- and utf8 then +-- -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] ) +-- bit32 = require("l-bit32") +-- end -- We need this due a bug in luatex socket loading: -local loaded = package.loaded - -if not loaded["socket"] then loaded["socket"] = loaded["socket.core"] end -if not loaded["mime"] then loaded["mime"] = loaded["mime.core"] end - -if not socket.mime then socket.mime = package.loaded["mime"] end - -if not loaded["socket.mime"] then loaded["socket.mime"] = socket.mime end -if not loaded["socket.http"] then loaded["socket.http"] = socket.http end -if not loaded["socket.ftp"] then loaded["socket.ftp"] = socket.ftp end -if not loaded["socket.smtp"] then loaded["socket.smtp"] = socket.smtp end -if not loaded["socket.tp"] then loaded["socket.tp"] = socket.tp end -if not loaded["socket.url"] then loaded["socket.url"] = socket.url end +-- local loaded = package.loaded +-- +-- if not loaded["socket"] then loaded["socket"] = loaded["socket.core"] end +-- if not loaded["mime"] then loaded["mime"] = loaded["mime.core"] end +-- +-- if not socket.mime then socket.mime = package.loaded["mime"] end +-- +-- if not loaded["socket.mime"] then loaded["socket.mime"] = socket.mime end +-- if not loaded["socket.http"] then loaded["socket.http"] = socket.http end +-- if not loaded["socket.ftp"] then loaded["socket.ftp"] = socket.ftp end +-- if not loaded["socket.smtp"] then loaded["socket.smtp"] = socket.smtp end +-- if not loaded["socket.tp"] then loaded["socket.tp"] = socket.tp end +-- if not loaded["socket.url"] then loaded["socket.url"] = socket.url end + +if LUAVERSION > 5.3 then + collectgarbage("generational") +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-macro-imp-optimize.lua b/Master/texmf-dist/tex/context/base/mkiv/l-macro-imp-optimize.lua index e04b37eab3c..7d7fafefde2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-macro-imp-optimize.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-macro-imp-optimize.lua @@ -46,17 +46,22 @@ if LUAVERSION >= 5.3 and lua.macros then -- #define rshift(a,b) ((a >> b) & 0xFFFFFFFF) -- ]] - lua.macros.resolvestring [[ - #define band(a,b) (a&b) - #define bnot(a) (~a&0xFFFFFFFF) - #define bor(a,b) ((a|b)&0xFFFFFFFF) - #define btest(a,b) ((a&b)~=0) - #define bxor(a,b) ((a~b)&0xFFFFFFFF) - #define rshift(a,b) ((a&b)~=0) - #define extract(a,b,c) ((a>>b)&~(-1<>b)&0x1)) - #define lshift(a,b) ((a<>b)&0xFFFFFFFF) - ]] +lua.macros.resolvestring [[ +#define band(a,b) ((a)&(b)) +#define bnot(a) (~(a)&0xFFFFFFFF) +#define bor(a,b) (((a)|(b))&0xFFFFFFFF) +#define btest(a,b) (((a)&(b))~=0) +#define bxor(a,b) (((a)~(b))&0xFFFFFFFF) +#define rshift(a,b) (((a)&(b))~=0) +#define extract(a,b,c) (((a)>>(b))&~(-1<<(c))) +#define extract(a,b) (((a)>>(b))&0x1) +#define extract1(a,b) ((a >> b) & 0x01) +#define extract2(a,b) ((a >> b) & 0x03) +#define extract4(a,b) ((a >> b) & 0x0F) +#define lshift(a,b) (((a)<<(b))&0xFFFFFFFF) +#define rshift(a,b) (((a)>>(b))&0xFFFFFFFF) +#define intdiv(a,b) ((a)//(b)) +#define idiv(a,b) ((a)//(b)) +]] end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-macro.lua b/Master/texmf-dist/tex/context/base/mkiv/l-macro.lua index 30c7cbec618..24a3d07bc23 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-macro.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-macro.lua @@ -14,14 +14,16 @@ if not modules then modules = { } end modules ['l-macros'] = { local S, P, R, V, C, Cs, Cc, Ct, Carg = lpeg.S, lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg local lpegmatch = lpeg.match local concat = table.concat -local format, sub = string.format, string.sub +local format, sub, match = string.format, string.sub, string.match local next, load, type = next, load, type local newline = S("\n\r")^1 local continue = P("\\") * newline +local whitespace = S(" \t\n\r") local spaces = S(" \t") + continue -local name = R("az","AZ","__","09")^1 -local body = ((1+continue/"")-newline)^1 +local nametoken = R("az","AZ","__","09") +local name = nametoken^1 +local body = ((continue/"" + 1) - newline)^1 local lparent = P("(") local rparent = P(")") local noparent = 1 - (lparent + rparent) @@ -53,7 +55,9 @@ end -- todo: zero case -resolve = C(C(name) * arguments^-1) / function(raw,s,a) +local safeguard = P("local") * whitespace^1 * name * (whitespace + P("=")) + +resolve = safeguard + C(C(name) * (arguments^-1)) / function(raw,s,a) local d = definitions[s] if d then if a then @@ -85,7 +89,7 @@ subparser = Cs((resolve + P(1))^1) local enddefine = P("#enddefine") / "" -local beginregister = (C(name) * spaces^0 * (arguments + Cc(false)) * C((1-enddefine)^1) * enddefine) / function(k,a,v) +local beginregister = (C(name) * (arguments + Cc(false)) * C((1-enddefine)^1) * enddefine) / function(k,a,v) local n = 0 if a then n = #a @@ -103,14 +107,14 @@ local beginregister = (C(name) * spaces^0 * (arguments + Cc(false)) * C((1-endde end local d = definitions[k] if not d then - d = { [0] = false, false, false, false, false, false, false, false, false } + d = { a = a, [0] = false, false, false, false, false, false, false, false, false } definitions[k] = d end d[n] = lpegmatch(subparser,v) or v return "" end -local register = (C(name) * spaces^0 * (arguments + Cc(false)) * spaces^0 * C(body)) / function(k,a,v) +local register = (Cs(name) * (arguments + Cc(false)) * spaces^0 * Cs(body)) / function(k,a,v) local n = 0 if a then n = #a @@ -128,7 +132,7 @@ local register = (C(name) * spaces^0 * (arguments + Cc(false)) * spaces^0 * C(bo end local d = definitions[k] if not d then - d = { [0] = false, false, false, false, false, false, false, false, false } + d = { a = a, [0] = false, false, false, false, false, false, false, false, false } definitions[k] = d end d[n] = lpegmatch(subparser,v) or v @@ -162,6 +166,25 @@ function macros.reset() patterns = { } end +function macros.showdefinitions() + -- no helpers loaded but not called early + for name, list in table.sortedhash(definitions) do + local arguments = list.a + if arguments then + arguments = "(" .. concat(arguments,",") .. ")" + else + arguments = "" + end + print("macro: " .. name .. arguments) + for i=0,#list do + local l = list[i] + if l then + print(" " .. l) + end + end + end +end + function macros.resolvestring(str) return lpegmatch(parser,str) or str end @@ -170,6 +193,51 @@ function macros.resolving() return next(patterns) end +local function reload(path,name,data) + local only = match(name,".-([^/]+)%.lua") + if only and only ~= "" then + local name = path .. "/" .. only + local f = io.open(name,"wb") + f:write(data) + f:close() + local f = loadfile(name) + os.remove(name) + return f + end +end + +-- local function reload(path,name,data) +-- if path and path ~= "" then +-- local only = file.nameonly(name) .. "-macro.lua" +-- local name = file.join(path,only) +-- io.savedata(name,data) +-- local l = loadfile(name) +-- os.remove(name) +-- return l +-- end +-- return load(data,name) +-- end +-- +-- assumes no helpers + +local function reload(path,name,data) + if path and path ~= "" then + local only = string.match(name,".-([^/]+)%.lua") + if only and only ~= "" then + local name = path .. "/" .. only .. "-macro.lua" + local f = io.open(name,"wb") + if f then + f:write(data) + f:close() + local l = loadfile(name) + os.remove(name) + return l + end + end + end + return load(data,name) +end + local function loaded(name,trace,detail) -- local c = io.loaddata(fullname) -- not yet available local f = io.open(name,"rb") @@ -194,12 +262,11 @@ local function loaded(name,trace,detail) report_lua("no macros expanded in '%s'",name) end end - if #name > 30 then - n = "--[[" .. sub(name,-30) .. "]] " .. n - else - n = "--[[" .. name .. "]] " .. n - end - return load(n) + -- if #name > 30 then + -- name = sub(name,-30) + -- end + -- n = "--[[" .. name .. "]]\n" .. n + return reload(lfs and lfs.currentdir(),name,n) end macros.loaded = loaded diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-number.lua b/Master/texmf-dist/tex/context/base/mkiv/l-number.lua index a83e8f8f94a..9fd2f82f785 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-number.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-number.lua @@ -81,13 +81,14 @@ if bit32 then "0", "0", "0", "0", "0", "0", "0", "0", } - function number.tobitstring(b,m) - -- if really needed we can speed this one up - -- because small numbers need less extraction - local n = 32 - for i=0,31 do + function number.tobitstring(b,m,w) + if not w then + w = 32 + end + local n = w + for i=0,w-1 do local v = bextract(b,i) - local k = 32 - i + local k = w - i if v == 1 then n = k t[k] = "1" @@ -95,12 +96,14 @@ if bit32 then t[k] = "0" end end - if m then + if w then + return concat(t,"",1,w) + elseif m then m = 33 - m * 8 if m < 1 then m = 1 end - return concat(t,"",m) + return concat(t,"",1,m) elseif n < 8 then return concat(t) elseif n < 16 then @@ -232,3 +235,7 @@ function number.decimaltobyte(d) return b end end + +function number.idiv(i,d) + return floor(i/d) -- i//d in 5.3 +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-os.lua b/Master/texmf-dist/tex/context/base/mkiv/l-os.lua index 9b54c9840c4..cf469f79d32 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-os.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-os.lua @@ -32,11 +32,78 @@ local concat = table.concat local random, ceil, randomseed = math.random, math.ceil, math.randomseed local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring --- The following code permits traversing the environment table, at least --- in luatex. Internally all environment names are uppercase. +-- This check needs to happen real early on. Todo: we can pick it up from the commandline +-- if we pass --binpath= (which is useful anyway) + +do + local selfdir = os.selfdir + if selfdir == "" then + selfdir = nil + end + if not selfdir then + -- We need a fallback plan so let's see what we get. + if arg then + -- passed by mtx-context ... saves network access + for i=1,#arg do + local a = arg[i] + if find(a,"^%-%-[c:]*texmfbinpath=") then + selfdir = gsub(a,"^.-=","") + break + end + end + end + if not selfdir then + selfdir = os.selfbin or "luatex" + if find(selfdir,"[/\\]") then + selfdir = gsub(selfdir,"[/\\][^/\\]*$","") + elseif os.getenv then + local path = os.getenv("PATH") + local name = gsub(selfdir,"^.*[/\\][^/\\]","") + local patt = "[^:]+" + if os.type == "windows" then + patt = "[^;]+" + name = name .. ".exe" + end + local isfile + if lfs then + -- we're okay as lfs is assumed present + local attributes = lfs.attributes + isfile = function(name) + local a = attributes(name,"mode") + return a == "file" or a == "link" or nil + end + else + -- we're not okay and much will not work as we miss lfs + local open = io.open + isfile = function(name) + local f = open(name) + if f then + f:close() + return true + end + end + end + for p in gmatch(path,patt) do + -- possible speedup: there must be tex in 'p' + if isfile(p .. "/" .. name) then + selfdir = p + break + end + end + end + end + -- let's hope we're okay now + os.selfdir = selfdir or "." + end +end +-- print(os.selfdir) os.exit() + +-- The following code permits traversing the environment table, at least in luatex. Internally all +-- environment names are uppercase. -- The randomseed in Lua is not that random, although this depends on the operating system as well --- as the binary (Luatex is normally okay). But to be sure we set the seed anyway. +-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway. It will be better +-- in Lua 5.4 (according to the announcements.) math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) @@ -156,7 +223,7 @@ end local launchers = { windows = "start %s", macosx = "open %s", - unix = "$BROWSER %s &> /dev/null &", + unix = "xdg-open %s &> /dev/null &", } function os.launch(str) @@ -223,6 +290,13 @@ local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or "" -- os.bits = 32 | 64 +-- os.uname() +-- sysname +-- machine +-- release +-- version +-- nodename + if platform ~= "" then os.platform = platform @@ -234,10 +308,12 @@ elseif os.type == "windows" then -- PROCESSOR_ARCHITECTURE : binary platform -- PROCESSOR_ARCHITEW6432 : OS platform + -- mswin-64 is now win64 + function resolvers.platform(t,k) - local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or "" + local architecture = os.getenv("PROCESSOR_ARCHITECTURE") or "" + local platform = "" if find(architecture,"AMD64",1,true) then - -- platform = "mswin-64" platform = "win64" else platform = "mswin" @@ -251,13 +327,17 @@ elseif name == "linux" then function resolvers.platform(t,k) -- we sometimes have HOSTTYPE set so let's check that first - local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or "" - if find(architecture,"x86_64",1,true) then - platform = "linux-64" + local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or "" + local platform = os.getenv("MTX_PLATFORM") or "" + local musl = find(os.selfdir or "","linuxmusl") + if platform ~= "" then + -- we're done + elseif find(architecture,"x86_64",1,true) then + platform = musl and "linuxmusl" or "linux-64" elseif find(architecture,"ppc",1,true) then platform = "linux-ppc" else - platform = "linux" + platform = musl and "linuxmusl" or "linux" end os.setenv("MTX_PLATFORM",platform) os.platform = platform @@ -277,11 +357,13 @@ elseif name == "macosx" then ]]-- function resolvers.platform(t,k) - -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" + -- local platform = "" + -- local architecture = os.getenv("HOSTTYPE") or "" -- if architecture == "" then -- architecture = resultof("echo $HOSTTYPE") or "" -- end - local platform, architecture = "", resultof("echo $HOSTTYPE") or "" + local architecture = resultof("echo $HOSTTYPE") or "" + local platform = "" if architecture == "" then -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") platform = "osx-intel" @@ -300,7 +382,8 @@ elseif name == "macosx" then elseif name == "sunos" then function resolvers.platform(t,k) - local platform, architecture = "", resultof("uname -m") or "" + local architecture = resultof("uname -m") or "" + local platform = "" if find(architecture,"sparc",1,true) then platform = "solaris-sparc" else -- if architecture == 'i86pc' @@ -314,7 +397,8 @@ elseif name == "sunos" then elseif name == "freebsd" then function resolvers.platform(t,k) - local platform, architecture = "", resultof("uname -m") or "" + local architecture = resultof("uname -m") or "" + local platform = "" if find(architecture,"amd64",1,true) then platform = "freebsd-amd64" else @@ -329,7 +413,8 @@ elseif name == "kfreebsd" then function resolvers.platform(t,k) -- we sometimes have HOSTTYPE set so let's check that first - local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or "" + local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or "" + local platform = "" if find(architecture,"x86_64",1,true) then platform = "kfreebsd-amd64" else @@ -564,3 +649,20 @@ function os.validdate(year,month,day) end return year, month, day end + +local osexit = os.exit +local exitcode = nil + +function os.setexitcode(code) + exitcode = code +end + +function os.exit(c) + if exitcode ~= nil then + return osexit(exitcode) + end + if c ~= nil then + return osexit(c) + end + return osexit() +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-package.lua b/Master/texmf-dist/tex/context/base/mkiv/l-package.lua index 4faee76bfbf..0dd71e5eca8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-package.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-package.lua @@ -394,3 +394,7 @@ end -- front .. table.insert(searchers,1,helpers.loaded) + +if context then + package.path = "" +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua b/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua index 2ecec0023fd..c2e1753d3ab 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-sandbox.lua @@ -190,6 +190,9 @@ end function sandbox.enable() if not sandboxed then + debug = { + traceback = debug.traceback, + } for i=1,#initializers do initializers[i].action() end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-sha.lua b/Master/texmf-dist/tex/context/base/mkiv/l-sha.lua new file mode 100644 index 00000000000..8481f7f45e8 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/l-sha.lua @@ -0,0 +1,27 @@ +if not modules then modules = { } end modules ['l-sha'] = { + 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" +} + +if sha2 then + + local lpegmatch = lpeg.match + local lpegpatterns = lpeg.patterns + local bytestohex = lpegpatterns.bytestohex + local bytestoHEX = lpegpatterns.bytestoHEX + + local digest256 = sha2.digest256 + local digest384 = sha2.digest384 + local digest512 = sha2.digest512 + + sha2.hash256 = function(str) return lpegmatch(bytestohex,digest256(str)) end + sha2.hash384 = function(str) return lpegmatch(bytestohex,digest384(str)) end + sha2.hash512 = function(str) return lpegmatch(bytestohex,digest512(str)) end + sha2.HASH256 = function(str) return lpegmatch(bytestoHEX,digest256(str)) end + sha2.HASH384 = function(str) return lpegmatch(bytestoHEX,digest384(str)) end + sha2.HASH512 = function(str) return lpegmatch(bytestoHEX,digest512(str)) end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-table.lua b/Master/texmf-dist/tex/context/base/mkiv/l-table.lua index 5cd65dd679f..57130a50d82 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-table.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-table.lua @@ -8,10 +8,9 @@ if not modules then modules = { } end modules ['l-table'] = { local type, next, tostring, tonumber, select = type, next, tostring, tonumber, select local table, string = table, string -local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove +local concat, sort = table.concat, table.sort local format, lower, dump = string.format, string.lower, string.dump local getmetatable, setmetatable = getmetatable, setmetatable -local getinfo = debug.getinfo local lpegmatch, patterns = lpeg.match, lpeg.patterns local floor = math.floor @@ -27,7 +26,8 @@ function table.getn(t) end function table.strip(tab) - local lst, l = { }, 0 + local lst = { } + local l = 0 for i=1,#tab do local s = lpegmatch(stripper,tab[i]) or "" if s == "" then @@ -42,7 +42,8 @@ end function table.keys(t) if t then - local keys, k = { }, 0 + local keys = { } + local k = 0 for key in next, t do k = k + 1 keys[k] = key @@ -146,7 +147,9 @@ end local function sortedkeys(tab) if tab then - local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed + local srt = { } + local category = 0 -- 0=unknown 1=string, 2=number 3=mixed + local s = 0 for key in next, tab do s = s + 1 srt[s] = key @@ -186,7 +189,8 @@ end local function sortedhashonly(tab) if tab then - local srt, s = { }, 0 + local srt = { } + local s = 0 for key in next, tab do if type(key) == "string" then s = s + 1 @@ -204,7 +208,8 @@ end local function sortedindexonly(tab) if tab then - local srt, s = { }, 0 + local srt = { } + local s = 0 for key in next, tab do if type(key) == "number" then s = s + 1 @@ -222,7 +227,8 @@ end local function sortedhashkeys(tab,cmp) -- fast one if tab then - local srt, s = { }, 0 + local srt = { } + local s = 0 for key in next, tab do if key then s= s + 1 @@ -318,7 +324,9 @@ end -- end function table.merge(t, ...) -- first one is target - t = t or { } + if not t then + t = { } + end for i=1,select("#",...) do for k, v in next, (select(i,...)) do t[k] = v @@ -384,7 +392,8 @@ end -- end function table.imerged(...) - local tmp, ntmp = { }, 0 + local tmp = { } + local ntmp = 0 for i=1,select("#",...) do local nst = select(i,...) for j=1,#nst do @@ -421,7 +430,9 @@ end -- todo : copy without metatable local function copy(t,tables) -- taken from lua wiki, slightly adapted - tables = tables or { } + if not tables then + tables = { } + end local tcopy = { } if not tables[t] then tables[t] = tcopy @@ -472,7 +483,8 @@ function table.tohash(t,value) end function table.fromhash(t) - local hsh, h = { }, 0 + local hsh = { } + local h = 0 for k, v in next, t do if v then h = h + 1 @@ -670,7 +682,8 @@ local function do_serialize(root,name,depth,level,indexed) end -- we could check for k (index) being number (cardinal) if root and next(root) ~= nil then - local first, last = nil, 0 + local first = nil + local last = 0 if compact then last = #root for k=1,last do @@ -830,22 +843,25 @@ local function do_serialize(root,name,depth,level,indexed) end elseif tv == "function" then if functions then - local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip - -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip - if tk == "number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) + local getinfo = debug and debug.getinfo + if getinfo then + local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip + -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip + if tk == "number" then + if hexify then + handle(format("%s [0x%X]=load(%q),",depth,k,f)) + else + handle(format("%s [%s]=load(%q),",depth,k,f)) + end + elseif tk == "boolean" then + handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) + elseif tk ~= "string" then + -- ignore + elseif noquotes and not reserved[k] and lpegmatch(propername,k) then + handle(format("%s %s=load(%q),",depth,k,f)) else - handle(format("%s [%s]=load(%q),",depth,k,f)) + handle(format("%s [%q]=load(%q),",depth,k,f)) end - elseif tk == "boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif tk ~= "string" then - -- ignore - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) end end else @@ -958,7 +974,8 @@ end -- number : [number] = { } function table.serialize(root,name,specification) - local t, n = { }, 0 + local t = { } + local n = 0 local function flush(s) n = n + 1 t[n] = s @@ -982,13 +999,15 @@ function table.tofile(filename,root,name,specification) local f = io.open(filename,'w') if f then if maxtab > 1 then - local t, n = { }, 0 + local t = { } + local n = 0 local function flush(s) n = n + 1 t[n] = s if n > maxtab then f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice - t, n = { }, 0 -- we could recycle t if needed + t = { } -- we could recycle t if needed + n = 0 end end serialize(flush,root,name,specification) @@ -1006,12 +1025,12 @@ end local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 } if f == nil then - f = { } + f = { } depth = 0xFFFF elseif tonumber(f) then -- assume that only two arguments are given depth = f - f = { } + f = { } elseif not depth then depth = 0xFFFF end @@ -1099,8 +1118,12 @@ local function are_equal(a,b,n,m) -- indexed if a == b then return true elseif a and b and #a == #b then - n = n or 1 - m = m or #a + if not n then + n = 1 + end + if not m then + m = #a + end for i=n,m do local ai, bi = a[i], b[i] if ai==bi then @@ -1213,7 +1236,8 @@ end function table.reversed(t) if t then - local tt, tn = { }, #t + local tt = { } + local tn = #t if tn > 0 then local ttn = 0 for i=tn,1,-1 do @@ -1228,24 +1252,32 @@ end function table.reverse(t) -- check with 5.3 ? if t then local n = #t + local m = n + 1 for i=1,floor(n/2) do -- maybe just n//2 - local j = n - i + 1 + local j = m - i t[i], t[j] = t[j], t[i] end return t end end -function table.sequenced(t,sep,simple) -- hash only +local function sequenced(t,sep,simple) if not t then return "" + elseif type(t) == "string" then + return t -- handy fallback end local n = #t local s = { } if n > 0 then -- indexed for i=1,n do - s[i] = tostring(t[i]) + local v = t[i] + if type(v) == "table" then + s[i] = "{" .. sequenced(v,sep,simple) .. "}" + else + s[i] = tostring(t[i]) + end end else -- hashed @@ -1257,17 +1289,27 @@ function table.sequenced(t,sep,simple) -- hash only s[n] = k elseif v and v~= "" then n = n + 1 - s[n] = k .. "=" .. tostring(v) + if type(v) == "table" then + s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}" + else + s[n] = k .. "=" .. tostring(v) + end end else n = n + 1 - s[n] = k .. "=" .. tostring(v) + if type(v) == "table" then + s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}" + else + s[n] = k .. "=" .. tostring(v) + end end end end return concat(s,sep or " | ") end +table.sequenced = sequenced + function table.print(t,...) if type(t) ~= "table" then print(tostring(t)) @@ -1312,8 +1354,8 @@ end function table.unique(old) local hash = { } - local new = { } - local n = 0 + local new = { } + local n = 0 for i=1,#old do local oi = old[i] if not hash[oi] then @@ -1334,12 +1376,14 @@ end function table.values(t,s) -- optional sort flag if t then - local values, keys, v = { }, { }, 0 + local values = { } + local keys = { } + local v = 0 for key, value in next, t do if not keys[value] then v = v + 1 values[v] = value - keys[k] = key + keys[k] = key end end if s then diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua b/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua index b5f52d3127c..13e0a3fa1c1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/l-unicode.lua @@ -21,13 +21,33 @@ if not modules then modules = { } end modules ['l-unicode'] = { -- todo: utf.sub replacement (used in syst-aux) -- we put these in the utf namespace: --- used : byte char gmatch len lower sub upper --- not used : dump find format gfind gsub match rep reverse +-- used : byte char len lower sub upper +-- not used : dump find format gmatch gfind gsub match rep reverse -utf = utf or (unicode and unicode.utf8) or { } +-- utf = utf or (unicode and unicode.utf8) or { } + +-- not supported: +-- +-- dump, find, format, gfind, gmatch, gsub, lower, match, rep, reverse, upper + +utf = utf or { } +unicode = nil + +if not string.utfcharacters then + + -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower + -- than the built-in string.utfcharacters. + + local gmatch = string.gmatch + + function string.characters(str) + return gmatch(str,".[\128-\191]*") + end -utf.characters = utf.characters or string.utfcharacters -utf.values = utf.values or string.utfvalues + +end + +utf.characters = string.utfcharacters -- string.utfvalues -- string.utfcharacters @@ -53,23 +73,19 @@ local bytepairs = string.bytepairs local finder = lpeg.finder local replacer = lpeg.replacer -local utfvalues = utf.values -local utfgmatch = utf.gmatch -- not always present - local p_utftype = patterns.utftype local p_utfstricttype = patterns.utfstricttype local p_utfoffset = patterns.utfoffset -local p_utf8char = patterns.utf8character +local p_utf8character = patterns.utf8character +local p_utf8char = patterns.utf8char local p_utf8byte = patterns.utf8byte local p_utfbom = patterns.utfbom local p_newline = patterns.newline local p_whitespace = patterns.whitespace -if not unicode then - - unicode = { utf = utf } -- for a while - -end +-- if not unicode then +-- unicode = { utf = utf } -- for a while +-- end if not utf.char then @@ -164,10 +180,8 @@ if not utf.byte then if not utf.byte then - local utf8byte = patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) + return lpegmatch(p_utf8byte,c) end end @@ -281,7 +295,7 @@ if not utf.len then -- -- alternative 1: 0.77 -- - -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0) + -- local utfcharcounter = utfbom^-1 * Cs((p_utf8character/'!')^0) -- -- function utf.len(str) -- return #lpegmatch(utfcharcounter,str or "") @@ -291,7 +305,7 @@ if not utf.len then -- -- local n = 0 -- - -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow + -- local utfcharcounter = utfbom^-1 * (p_utf8character/function() n = n + 1 end)^0 -- slow -- -- function utf.length(str) -- n = 0 @@ -368,7 +382,7 @@ if not utf.sub then -- inefficient as lpeg just copies ^n -- local function sub(str,start,stop) - -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1)) + -- local pattern = p_utf8character^-(start-1) * C(p_utf8character^-(stop-start+1)) -- inspect(pattern) -- return lpegmatch(pattern,str) or "" -- end @@ -391,7 +405,7 @@ if not utf.sub then -- end -- end -- - -- local pattern = Cmt(p_utf8char,slide)^0 + -- local pattern = Cmt(p_utf8character,slide)^0 -- -- function utf.sub(str,start,stop) -- todo: from the end -- if not start then @@ -446,11 +460,11 @@ if not utf.sub then end end - local pattern_zero = Cmt(p_utf8char,slide_zero)^0 - local pattern_one = Cmt(p_utf8char,slide_one )^0 - local pattern_two = Cmt(p_utf8char,slide_two )^0 + local pattern_zero = Cmt(p_utf8character,slide_zero)^0 + local pattern_one = Cmt(p_utf8character,slide_one )^0 + local pattern_two = Cmt(p_utf8character,slide_two )^0 - local pattern_first = C(patterns.utf8character) + local pattern_first = C(p_utf8character) function utf.sub(str,start,stop) if not start then @@ -546,7 +560,7 @@ end -- a replacement for simple gsubs: -- function utf.remapper(mapping) --- local pattern = Cs((p_utf8char/mapping)^0) +-- local pattern = Cs((p_utf8character/mapping)^0) -- return function(str) -- if not str or str == "" then -- return "" @@ -568,16 +582,16 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern return "" else if not pattern then - pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) + pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0) end return lpegmatch(pattern,str) end end elseif option == "pattern" then - return Cs((tabletopattern(mapping)/action + p_utf8char)^0) + return Cs((tabletopattern(mapping)/action + p_utf8character)^0) -- elseif option == "static" then else - local pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0) + local pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0) return function(str) if not str or str == "" then return "" @@ -588,9 +602,9 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern end elseif variant == "function" then if option == "pattern" then - return Cs((p_utf8char/mapping + p_utf8char)^0) + return Cs((p_utf8character/mapping + p_utf8character)^0) else - local pattern = Cs((p_utf8char/mapping + p_utf8char)^0) + local pattern = Cs((p_utf8character/mapping + p_utf8character)^0) return function(str) if not str or str == "" then return "" @@ -637,9 +651,9 @@ end -- inspect(utf.split("a b c d",true)) local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline) -local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0) -local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0) -local utfcharsplitter_raw = Ct(C(p_utf8char)^0) +local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8character)^0) +local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8character))^0) +local utfcharsplitter_raw = Ct(C(p_utf8character)^0) patterns.utflinesplitter = utflinesplitter @@ -775,7 +789,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*left + right -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -804,7 +818,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*right + left -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -834,7 +848,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_ -- if right then -- local now = 256*right + left -- if more > 0 then --- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong +-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- more = 0 -- r = r + 1 -- result[r] = utfchar(now) @@ -911,7 +925,7 @@ local more = 0 local p_utf16_to_utf8_be = C(1) * C(1) /function(left,right) local now = 256*byte(left) + byte(right) if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 more = 0 return utfchar(now) elseif now >= 0xD800 and now <= 0xDBFF then @@ -925,7 +939,7 @@ end local p_utf16_to_utf8_le = C(1) * C(1) /function(right,left) local now = 256*byte(left) + byte(right) if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 more = 0 return utfchar(now) elseif now >= 0xD800 and now <= 0xDBFF then @@ -1119,15 +1133,6 @@ function utf.utf8_to_utf16(str,littleendian,nobom) end end --- function utf.tocodes(str,separator) -- can be sped up with an lpeg --- local t, n = { }, 0 --- for u in utfvalues(str) do --- n = n + 1 --- t[n] = format("0x%04X",u) --- end --- return concat(t,separator or " ") --- end - local pattern = Cs ( (p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) * (p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 @@ -1163,25 +1168,10 @@ end -- -local p_nany = p_utf8char / "" - -if utfgmatch then - - function utf.count(str,what) - if type(what) == "string" then - local n = 0 - for _ in utfgmatch(str,what) do - n = n + 1 - end - return n - else -- 4 times slower but still faster than / function - return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str) - end - end - -else +do - local cache = { } + local p_nany = p_utf8character / "" + local cache = { } function utf.count(str,what) if type(what) == "string" then @@ -1198,23 +1188,7 @@ else end --- maybe also register as string.utf* - - -if not utf.characters then - - -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower - -- than the built-in string.utfcharacters. - - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - - string.utfcharacters = utf.characters - -end - -if not utf.values then +if not string.utfvalues then -- So, a logical next step is to check for the values variant. It over five times -- slower than the built-in string.utfvalues. I optimized it a bit for n=0,1. @@ -1226,7 +1200,7 @@ if not utf.values then -- we share this one end - -- function utf.values(str) + -- function string.utfvalues(str) -- local n = #str -- if n == 0 then -- return wrap(dummy) @@ -1241,7 +1215,7 @@ if not utf.values then -- -- faster: - function utf.values(str) + function string.utfvalues(str) local n = #str if n == 0 then return dummy @@ -1264,11 +1238,11 @@ if not utf.values then -- slower: -- - -- local pattern = C(patterns.utf8character) * Cp() - -- ----- pattern = patterns.utf8character/utfbyte * Cp() - -- ----- pattern = patterns.utf8byte * Cp() + -- local pattern = C(p_utf8character) * Cp() + -- ----- pattern = p_utf8character/utfbyte * Cp() + -- ----- pattern = p_utf8byte * Cp() -- - -- function utf.values(str) -- one of the cases where a find is faster than an lpeg + -- function string.utfvalues(str) -- one of the cases where a find is faster than an lpeg -- local n = #str -- if n == 0 then -- return dummy @@ -1287,10 +1261,10 @@ if not utf.values then -- end -- end - string.utfvalues = utf.values - end +utf.values = string.utfvalues + function utf.chrlen(u) -- u is number return (u < 0x80 and 1) or @@ -1310,7 +1284,7 @@ if bit32 then local extract = bit32.extract local char = string.char - function unicode.toutf32string(n) + function utf.toutf32string(n) if n <= 0xFF then return char(n) .. @@ -1359,3 +1333,73 @@ function string.utfpadd(s,n) end return s end + +-- goodies + +do + + local utfcharacters = utf.characters or string.utfcharacters + local utfchar = utf.char or string.utfcharacter + + lpeg.UP = P + + if utfcharacters then + + function lpeg.US(str) + local p = P(false) + for uc in utfcharacters(str) do + p = p + P(uc) + end + return p + end + + else + + function lpeg.US(str) + local p = P(false) + local f = function(uc) + p = p + P(uc) + end + lpegmatch((p_utf8char/f)^0,str) + return p + end + + end + + local range = p_utf8byte * p_utf8byte + Cc(false) -- utf8byte is already a capture + + function lpeg.UR(str,more) + local first, last + if type(str) == "number" then + first = str + last = more or first + else + first, last = lpegmatch(range,str) + if not last then + return P(str) + end + end + if first == last then + return P(str) + end + if not utfchar then + utfchar = utf.char -- maybe delayed + end + if utfchar and (last - first < 8) then -- a somewhat arbitrary criterium + local p = P(false) + for i=first,last do + p = p + P(utfchar(i)) + end + return p -- nil when invalid range + else + local f = function(b) + return b >= first and b <= last + end + -- tricky, these nested captures + return p_utf8byte / f -- nil when invalid range + end + end + + -- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω")) + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua index c0c3981f7df..3f04bed0d82 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-def.lua @@ -224,6 +224,15 @@ local specifications = allocate { ["opentype"] = "fin", ["variant"] = "fi", }, + { + ["description"] = "Estonian", + ["script"] = "latn", + ["bibliographical"] = "est", + ["terminological"] = "est", + ["context"] = "et", + ["opentype"] = "est", + ["variant"] = "et", + }, { ["description"] = "French", ["script"] = "latn", diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv index 28245e591fe..7f3e85f0812 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-def.mkiv @@ -21,19 +21,6 @@ % Swedish, German, Yiddish, Afrikaans, Dutch, English, Flemush, % Frisian, Plattdeutsch -\installlanguage - [\s!nl] - [\c!spacing=\v!packed, - \c!leftsentence=\emdash, - \c!rightsentence=\emdash, - \c!leftsubsentence=\emdash, - \c!rightsubsentence=\emdash, - \c!leftquote=\lowerleftsingleninequote, - \c!rightquote=\upperrightsingleninequote, - \c!leftquotation=\lowerleftdoubleninequote, - \c!rightquotation=\upperrightdoubleninequote, - \c!date={\v!day,\space,\v!month,\space,\v!year}] - \installlanguage [\s!en] [\c!spacing=\v!broad, @@ -50,6 +37,19 @@ \s!lefthyphenmin=2, \s!righthyphenmin=3] +\installlanguage + [\s!nl] + [\c!spacing=\v!packed, + \c!leftsentence=\emdash, + \c!rightsentence=\emdash, + \c!leftsubsentence=\emdash, + \c!rightsubsentence=\emdash, + \c!leftquote=\lowerleftsingleninequote, + \c!rightquote=\upperrightsingleninequote, + \c!leftquotation=\lowerleftdoubleninequote, + \c!rightquotation=\upperrightdoubleninequote, + \c!date={\v!day,\space,\v!month,\space,\v!year}] + \installlanguage [\s!de] [\c!spacing=\v!packed, @@ -327,6 +327,22 @@ \c!rightquotation=\upperrightdoubleninequote, \c!date={\v!year,\space,\v!month,\space,\v!day}] +\installlanguage + [\s!et] + [\c!default=\s!en, + \c!spacing=\v!packed, + \c!leftsentence=\emdash, + \c!rightsentence=\emdash, + \c!leftsubsentence=\emdash, + \c!rightsubsentence=\emdash, + \c!leftquote=\leftguillemot, + \c!rightquote=\rightguillemot, + \c!leftquotation=\lowerrightdoubleninequote, + \c!rightquotation=\upperrightdoublesixquote, + \c!time={h,{.},m}, + \c!date={\v!day,.,\space,\v!month,\space,\v!year}, + \s!patterns=\s!et] + \installlanguage [\s!hu] [\c!spacing=\v!packed, @@ -341,6 +357,7 @@ \c!date={\v!year,.,\space,\v!month,\space,\v!day,.}] \installlanguage [\s!finnish] [\s!fi] +\installlanguage [\s!estonian] [\s!et] \installlanguage [\s!hungarian] [\s!hu] % Altaic Languages: Uigur, Uzbek, Azeri/Azerbaijani, Chuvash, @@ -580,6 +597,7 @@ \c!rightquote=\rightguillemot, \c!leftquotation=\leftguillemot, \c!rightquotation=\rightguillemot, + \c!time={h,{\Uchar104 },m},% we need to cheat in order to get the h \c!date={\v!day:mnem,\v!space,\v!month,\v!space,\v!year}] \installlanguage diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua index 65a53a702fb..5603d119342 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-dis.lua @@ -17,14 +17,10 @@ local nuts = nodes.nuts local enableaction = tasks.enableaction local setaction = tasks.setaction -local tonode = nuts.tonode -local tonut = nuts.tonut - local setfield = nuts.setfield local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid -local getfont = nuts.getfont local getattr = nuts.getattr local getsubtype = nuts.getsubtype local setsubtype = nuts.setsubtype @@ -40,10 +36,11 @@ local isglyph = nuts.isglyph local copy_node = nuts.copy local remove_node = nuts.remove -local traverse_id = nuts.traverse_id local flush_list = nuts.flush_list local flush_node = nuts.flush_node +local nextdisc = nuts.traversers.disc + local new_disc = nuts.pool.disc local nodecodes = nodes.nodecodes @@ -52,10 +49,7 @@ local disccodes = nodes.disccodes local disc_code = nodecodes.disc local glyph_code = nodecodes.glyph -local discretionary_code = disccodes.discretionary -local explicit_code = disccodes.explicit -local automatic_code = disccodes.automatic -local regular_code = disccodes.regular +local explicitdisc_code = disccodes.explicit local a_visualize = attributes.private("visualizediscretionary") local setattribute = tex.setattribute @@ -69,7 +63,7 @@ local check_regular = true local setlistcolor = nodes.tracers.colors.setlist function languages.visualizediscretionaries(head) - for d in traverse_id(disc_code,tonut(head)) do + for d in nextdisc, head do if getattr(d,a_visualize) then local pre, post, replace = getdisc(d) if pre then @@ -83,6 +77,7 @@ function languages.visualizediscretionaries(head) end end end + return head end local enabled = false @@ -129,13 +124,9 @@ end local wiped = 0 -local flatten_discretionaries = node.flatten_discretionaries -- todo in nodes +local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes -if flatten_discretionaries then - - -- This is not that much faster than the lua variant simply because there is - -- seldom a replace list but it fits in the picture. See luatex-todo.w for the - -- code. +-- if flatten_discretionaries then function languages.flatten(head) local h, n = flatten_discretionaries(head) @@ -143,51 +134,50 @@ if flatten_discretionaries then return h, n > 0 end -else - - local function wipe(head,delayed) - local p, n = getboth(delayed) - local _, _, h, _, _, t = getdisc(delayed,true) - if p or n then - if h then - setlink(p,h) - setlink(t,n) - setfield(delayed,"replace") - else - setlink(p,n) - end - end - if head == delayed then - head = h - end - wiped = wiped + 1 - flush_node(delayed) - return head - end - - function languages.flatten(head) - local nuthead = tonut(head) - local delayed = nil - for d in traverse_id(disc_code,nuthead) do - if delayed then - nuthead = wipe(nuthead,delayed) - end - delayed = d - end - if delayed then - return tonode(wipe(nuthead,delayed)), true - else - return head, false - end - end - -end +-- else +-- +-- local function wipe(head,delayed) +-- local p, n = getboth(delayed) +-- local _, _, h, _, _, t = getdisc(delayed,true) +-- if p or n then +-- if h then +-- setlink(p,h) +-- setlink(t,n) +-- setfield(delayed,"replace") +-- else +-- setlink(p,n) +-- end +-- end +-- if head == delayed then +-- head = h +-- end +-- wiped = wiped + 1 +-- flush_node(delayed) +-- return head +-- end +-- +-- function languages.flatten(head) +-- local delayed = nil +-- for d in nextdisc, head do +-- if delayed then +-- head = wipe(head,delayed) +-- end +-- delayed = d +-- end +-- if delayed then +-- return wipe(head,delayed), true +-- else +-- return head, false +-- end +-- end +-- +-- end function languages.nofflattened() return wiped -- handy for testing end --- experiment +-- experiment: for now not in not in export mode! local flatten = languages.flatten local getlist = nodes.getlist @@ -198,10 +188,11 @@ function nodes.handlers.flatten(head,where) if head and (where == "box" or where == "adjusted_hbox") then return flatten(head) end - return true + return head end directives.register("hyphenator.flatten",function(v) + -- use with care setaction("processors","nodes.handlers.flatten",v) setaction("contributers","nodes.handlers.flattenline",v) end) @@ -227,6 +218,6 @@ function languages.explicithyphen(template) end end end - setdisc(disc,pre,post,nil,explicit_code,tex.exhyphenpenalty) + setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty) return disc end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-exp.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-exp.lua index 70fad48b0fe..254961ee6f9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-exp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-exp.lua @@ -31,6 +31,8 @@ local expanders -- this will go away if LUATEXVERSION < 1.005 then -- not loaded any more + -- some shortcuts go here + expanders = { [discretionary_code] = function(d,template) -- \discretionary @@ -172,23 +174,23 @@ languages.expanders = expanders ----- expand_explicit = expanders and expanders[explicit_code] ----- expand_automatic = expanders and expanders[automatic_code] -if LUATEXVERSION < 1.005 then -- not loaded any more - - expanded = function(head) - local done = hyphenate(head) - if done then - for d in traverse_id(disc_code,tonut(head)) do - local s = getsubtype(d) - if s ~= discretionary_code then - expanders[s](d,template) - done = true - end - end - end - return head, done - end - -end +-- if LUATEXVERSION < 1.005 then -- not loaded any more +-- +-- expanded = function(head) +-- local done = hyphenate(head) +-- if done then +-- for d in traverse_id(disc_code,head) do +-- local s = getsubtype(d) +-- if s ~= discretionary_code then +-- expanders[s](d,template) +-- done = true +-- end +-- end +-- end +-- return head, done +-- end +-- +-- end -- if id == disc_code then -- if expanded then diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua index e29446b65ac..92b400d4f53 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.lua @@ -626,13 +626,10 @@ if context then local math_code = nodecodes.math local hlist_code = nodecodes.hlist - local discretionary_code = disccodes.discretionary - local explicit_code = disccodes.explicit - local automatic_code = disccodes.automatic - local regular_code = disccodes.regular + local automaticdisc_code = disccodes.automatic + local regulardisc_code = disccodes.regular local nuts = nodes.nuts - local tonut = nodes.tonut local tonode = nodes.tonode local nodepool = nuts.pool @@ -666,7 +663,9 @@ if context then local remove_node = nuts.remove local end_of_math = nuts.end_of_math local node_tail = nuts.tail - local traverse_id = nuts.traverse_id + + local nexthlist = nuts.traversers.hlist + local nextdisc = nuts.traversers.disc local setcolor = nodes.tracers.colors.set @@ -1028,9 +1027,7 @@ featureset.hyphenonly = hyphenonly == v_yes function traditional.hyphenate(head) - local first = tonut(head) - - + local first = head local tail = nil local last = nil local current = first @@ -1289,7 +1286,7 @@ featureset.hyphenonly = hyphenonly == v_yes if leftchar then post = serialize(true,leftchar) end - setdisc(disc,pre,post,nil,regular_code,hyphenpenalty) + setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty) if attrnode then setattrlist(disc,attrnode) end @@ -1324,7 +1321,7 @@ featureset.hyphenonly = hyphenonly == v_yes end end -- maybe regular code - setdisc(disc,pre,post,replace,regular_code,hyphenpenalty) + setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty) if attrnode then setattrlist(disc,attrnode) end @@ -1364,7 +1361,7 @@ featureset.hyphenonly = hyphenonly == v_yes end pre = copy_node(glyph) setchar(pre,rightchar and rightchar > 0 and rightchar or code) - setdisc(disc,pre,post,replace,automatic_code,hyphenpenalty) -- ex ? + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? if attrnode then setattrlist(disc,attrnode) end @@ -1386,7 +1383,7 @@ featureset.hyphenonly = hyphenonly == v_yes local pre = copy_list(start) local post = nil local replace = start - setdisc(disc,pre,post,replace,automatic_code,hyphenpenalty) -- ex ? + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? if attrnode then setattrlist(disc,attrnode) end @@ -1585,7 +1582,7 @@ featureset.hyphenonly = hyphenonly == v_yes stoptiming(traditional) - return head, true + return head end statistics.register("hyphenation",function() @@ -1613,15 +1610,31 @@ featureset.hyphenonly = hyphenonly == v_yes -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches) - local hyphenate = lang.hyphenate - local methods = { } - local usedmethod = false - local stack = { } + local hyphenate = lang.hyphenate + local hyphenating = nuts.hyphenating + local methods = { } + local usedmethod = false + local stack = { } - local function original(head) - local done = hyphenate(head) - return head, done - end + local original = hyphenating and + function(head) + return (hyphenating(head)) + end + or + function(head) + hyphenate(tonode(head)) + return head -- a nut + end + + -- local has_language = lang.has_language + -- + -- local function original(head) -- kernel.hyphenation(head) + -- local h = tonode(head) + -- if has_language(h) then + -- hyphenate(h) + -- end + -- return head + -- end local getcount = tex.getcount @@ -1637,13 +1650,13 @@ featureset.hyphenonly = hyphenonly == v_yes forced = false return usedmethod(head) else - return head, false + return head end else return usedmethod(head) end else - return head, false + return head end end @@ -1729,13 +1742,12 @@ featureset.hyphenonly = hyphenonly == v_yes } function nodes.stripdiscretionaries(head) - local h = tonut(head) - for l in traverse_id(hlist_code,h) do - for d in traverse_id(disc_code,getlist(l)) do + for l in nexthlist, head do + for d in nextdisc, getlist(l) do remove_node(h,false,true) end end - return tonode(h) + return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv index feec82659b5..9301fd1d873 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-hyp.mkiv @@ -48,10 +48,11 @@ \automatichyphenmode \plusone \hyphenpenaltymode \plusfour -\hyphenpenalty 50 % hyphenator -\automatichyphenpenalty 50 % - -\explicithyphenpenalty 50 % \- -\compoundhyphenpenalty 50 +\hyphenpenalty 50 % hyphenator +\automatichyphenpenalty 50 % - +\explicithyphenpenalty 50 % \- +\compoundhyphenpenalty 50 +\exceptionpenalty 1000 %D This command can change! At some point we will keep the setting with the %D paragraph and then the \type {\par} can go. diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv index 7c83ae38fb8..296cf7f1c86 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-ini.mkiv @@ -15,10 +15,10 @@ % \cldcontext{languages.numbers[tex.count.mainlanguagenumber]} -%D This module implements the (for the moment still simple) -%D multi||language support of \CONTEXT, which should not be -%D confused with the multi||lingual interface. This support -%D will be extended when needed. +%D This module implements multi||language support of \CONTEXT, which should not be +%D confused with the multi||lingual interface. This support will be extended when +%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\ +%D files. \writestatus{loading}{ConTeXt Language Macros / Initialization} @@ -28,41 +28,27 @@ \unprotect -% \def\testlanguage[#1]% -% {\start -% \language[#1] -% \number\normallanguage/\the\lefthyphenmin/\the\righthyphenmin: -% \input tufte -% \hyphenatedword{effetestenofditwerkt} -% \par -% \stop} -% -% \testlanguage[de] \testlanguage[de-de] \testlanguage[de-at] \testlanguage[de-ch] \page -% \testlanguage[en] \testlanguage[us] \testlanguage[en-us] \testlanguage[uk] \testlanguage[en-gb] \page - \ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi \ifdefined\frenchspacing \else \let\frenchspacing \relax \fi -%D When loading hyphenation patterns, \TEX\ assign a number to -%D each loaded table, starting with~0. Switching to a specific -%D table is done by assigning the relevant number to the -%D predefined \COUNTER\ \type{\language}. +%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table, +%D starting with~0. Switching to a specific table is done by assigning the relevant +%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot +%D of management is delegated to \LUA. -%D We keep track of the last loaded patterns by means of a -%D pseudo \COUNTER. This just one of those situations in which -%D we don't want to spent a real one. Language zero has no -%D patterns, first of all because I like to start numbering -%D at one. It may come in handy for special purposes as well. +%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This +%D just one of those situations in which we don't want to spent a real one. Language +%D zero has no patterns, first of all because I like to start numbering at one. It +%D may come in handy for special purposes as well. \normallanguage\zerocount \def\loadedlanguage{1} %D \macros %D {currentlanguage, setupcurrentlanguage} %D -%D Instead of numbers,we are going to use symbolic names for -%D the languages. The current langage is saved in the macro -%D \type {\currentlanguage}. The setup macro is mainly used -%D for cosmetic purposes. +%D Instead of numbers,we are going to use symbolic names for the languages. The +%D current langage is saved in the macro \type {\currentlanguage}. The setup macro +%D is mainly used for cosmetic purposes. %D %D \starttyping %D \dorecurse{3} @@ -79,10 +65,9 @@ %D \macros %D {defaultlanguage,languageparameter,specificlanguageparameter} - -%D We don't use the commandhandler here (yet) because we have -%D a rather special fallback mechanism so quite some compatibility -%D testing is needed. +%D +%D We don't use the commandhandler here (yet) because we have a rather special +%D fallback mechanism so quite some compatibility testing is needed. \installcorenamespace{language} \installcorenamespace{languagelinked} @@ -96,33 +81,6 @@ #1% \fi} -% \def\languageparameter#1% -% {\ifcsname\??language\currentlanguage#1\endcsname -% \csname\??language\currentlanguage#1\endcsname -% \else\ifcsname\??language\currentlanguage\s!default\endcsname -% \expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}% -% \else\ifcsname\??language\s!default#1\endcsname -% \csname\??language\s!default#1\endcsname -% \fi\fi\fi} -% -% \def\specificlanguageparameter#1#2% -% {\ifcsname\??language#1#2\endcsname -% \csname\??language#1#2\endcsname -% \else\ifcsname\??language#1\s!default\endcsname -% \expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}% -% \else\ifcsname\??language\s!default#2\endcsname -% \csname\??language\s!default#2\endcsname -% \fi\fi\fi} -% -% \def\mainlanguageparameter#1% -% {\ifcsname\??language\currentmainlanguage#1\endcsname -% \csname\??language\currentmainlanguage#1\endcsname -% \else\ifcsname\??language\currentmainlanguage\s!default\endcsname -% \expandafter\specificlanguageparameter\csname\??language\currentmainlanguage\s!default\endcsname{#1}% -% \else\ifcsname\??language\s!default#1\endcsname -% \csname\??language\s!default#1\endcsname -% \fi\fi\fi} - \def\languageparameter#1% {\ifcsname\??language\currentlanguage#1\endcsname \lastnamedcs @@ -152,15 +110,6 @@ \let\usedlanguageparameter\languageparameter -% \def\askedlanguageparameter#1% assumes \currentusedlanguage being set -% {\ifcsname\??language\currentusedlanguage#1\endcsname -% \csname\??language\currentusedlanguage#1\endcsname -% \else\ifcsname\??language\currentusedlanguage\s!default\endcsname -% \expandafter\specificlanguageparameter\csname\??language\currentusedlanguage\s!default\endcsname{#1}% -% \else\ifcsname\??language\s!default#1\endcsname -% \csname\??language\s!default#1\endcsname -% \fi\fi\fi} - \def\askedlanguageparameter#1% assumes \currentusedlanguage being set {\ifcsname\??language\currentusedlanguage#1\endcsname \lastnamedcs @@ -171,7 +120,6 @@ \fi\fi\fi} \unexpanded\def\setusedlanguage#1% -% {\edef\currentusedlanguage{\reallanguagetag{#1\c!language}}% {\edef\currentusedlanguage{\reallanguagetag{#1}}% \ifx\currentusedlanguage\empty \let\currentusedlanguage \currentlanguage @@ -208,43 +156,23 @@ %D \macros %D {installlanguage} %D -%D Hyphenation patterns can only be loaded when the format file -%D is prepared. The next macro takes care of this loading. A -%D language is specified with +%D Hyphenation patterns can only be loaded when the format file is prepared. The +%D next macro takes care of this loading. A language is specified with %D %D \showsetup{installlanguage} %D -%D When \type {state} equals \type {start}, both patterns -%D and additional hyphenation specifications are loaded. These -%D files are seached for on the system path and are to be -%D named: -%D -%D \starttyping -%D lang-identifier.\f!patternsextension -%D lang-identifier.\f!hyhensextension -%D \stoptyping +%D When \type {state} equals \type {start}, both patterns and additional hyphenation +%D specifications are loaded. These files are seached for in the patterns path +%D have names like \type {lang-nl.lua}. %D -%D The \type{spacing} variable specifies how the spaces after -%D punctuation has to be handled. English is by tradition more -%D tolerant to inter||sentence spacing than other languages. -%D -%D This macro also defines \type {\identifier} as a shortcut -%D switch to the language. Furthermore the command defined as -%D being language specific, are executed. With -%D \type {default} we can default to another language -%D (patterns) at format generation time. This default language -%D is overruled when the appropriate patterns are loaded (some -%D implementations support run time addition of patterns to a -%D preloaded format). - -%D \macros -%D {preloadlanguages} +%D The \type {spacing} variable specifies how the spaces after punctuation has to be +%D handled. English is by tradition more tolerant to inter||sentence spacing than +%D other languages. %D -%D We first try to load the files defined as file synonym -%D for \type {lang-*.pat} and \type {lang-*.hyp}. After that we -%D fall back on those files. The macro \type {\preloadpatterns} -%D reports which patterns are loaded and what hyphenmin -%D values are set. +%D This macro also defines \type {\identifier} as a shortcut switch to the language. +%D Furthermore the command defined as being language specific, are executed. With +%D \type {default} we can default to another language (patterns) at format +%D generation time. Patterns are loaded at runtime. \newtoks \everysetuplanguage @@ -260,7 +188,6 @@ \let\doiflanguageelse\doifelselanguage \def\reallanguagetag#1% - %{\ifcsname\??languagelinked#1\endcsname\csname\??languagelinked#1\endcsname\else#1\fi} {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi} % \language[#1] gave unwanted side effect of loading language specifics @@ -285,10 +212,9 @@ \def\lang_basics_install_indeed#1#2% {\ifcsname#1\endcsname\else\setuvalue{#1}{\lang_basics_set_current[#2]}\fi} -%D When the second argument is a language identifier, a -%D synonym is created. This feature is present because we -%D used dutch mnemonics in the dutch version, but nowadays -%D conform a standard. +%D When the second argument is a language identifier, a synonym is created. This +%D feature is present because we used dutch mnemonics in the dutch version, but +%D nowadays conform a standard. \unexpanded\def\doifelsepatterns#1% {\begingroup % will change @@ -317,13 +243,15 @@ \let\lang_basics_synchronize\relax % be nice for setups till we have one \fi +\installmacrostack\currentlanguage + \def\lang_basics_setup[#1][#2]% {\ifsecondargument - \pushmacro\currentlanguage % can be default + \push_macro_currentlanguage % can be default \edef\currentsetuplanguage{\reallanguagetag{#1}}% \getparameters[\??language\currentsetuplanguage][#2]% \the\everysetuplanguage - \popmacro\currentlanguage + \pop_macro_currentlanguage %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default) \else \let\currentsetuplanguage\currentlanguage @@ -364,6 +292,7 @@ \c!middlespeech=, \c!rightspeech=\languageparameter\c!rightquotation, \c!limittext=\unknown, + \c!time={h,:,m}, \c!date={\v!year,\ ,\v!month,\ ,\v!day}, \c!text=Ag, \s!font=] % \v!auto : experimental ! @@ -374,26 +303,21 @@ % [\s!default] % [\c!righthyphenchar="AD] -%D The values \type {leftsentence} and \type -%D {rightsentence} can be (and are) used to implement -%D automatic subsentence boundary glyphs, like in {\fr -%D |<|french guillemots|>|} or {\de |<|german guillemots|>|} or -%D {\nl |<|dutch dashes|>|} like situations. Furthermore \type -%D {leftquotation} and \type {leftquote} come into view -%D \quotation {when we quote} or \quote {quote} something. +%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used +%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french +%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like +%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into +%D view \quotation {when we quote} or \quote {quote} something. %D \macros -%D {currentdatespecification} +%D {currentdatespecification, currenttimespecification} %D -%D Just to make things easy we can ask for the current date -%D specification by saying: +%D Just to make things easy we can ask for the current date specification by saying: \def\currentdatespecification{\languageparameter\c!date} +\def\currenttimespecification{\languageparameter\c!time} -%D This command is not meant for users. - -%D Carefull reading of these macros shows that it's legal to -%D say +%D Carefull reading of these macros shows that it's legal to say %D %D \starttyping %D \installlanguage [du] [de] @@ -402,54 +326,39 @@ %D \macros %D {language,mainlanguage} %D -%D Switching to another language (actually another hyphenation -%D pattern) is done with: +%D Switching to another language (actually another hyphenation pattern) is done +%D with: %D %D \starttyping %D \language[identifier] %D \stoptyping %D -%D or with \type{\identifier}. Just to be compatible with -%D \PLAIN\ \TEX, we still support the original meaning, so +%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still +%D support the original meaning, so %D %D \starttyping %D \language=1 %D \stoptyping %D -%D is a valid operation, where the relation between number -%D and language depends on the order in installing languages. +%D is a valid operation, where the relation between number and language depends on +%D the order in installing languages. %D %D \showsetup{language} %D \showsetup{mainlanguage} %D -%D Both commands take a predefined language identifier as -%D argument. We can use \type{\mainlanguage[identifier]} for -%D setting the (indeed) main language. This is the language -%D used for translating labels like {\em figure} and {\em -%D table}. The main language defaults to the current language. -%D -%D We take care of local as well as standardized language -%D switching (fr and fa, de and du, but nl and nl). +%D Both commands take a predefined language identifier as argument. We can use \type +%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the +%D language used for translating labels like {\em figure} and {\em table}. The main +%D language defaults to the current language. \newtoks \everylanguage -% \def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex -% {\normallanguage\ctxcommand{languagenumber(% -% "\currentlanguage",% -% "\defaultlanguage\currentlanguage",% -% "\languageparameter\s!patterns"% -% )}\relax -% \the\everylanguage\relax} - -% (some 20%) faster but code jungle (the publication code can have excessive -% switching - \installcorenamespace{languagenumbers} \appendtoks % we need to reassign the number because new patterns can be defined later on % so let's hope not that many \setups happen during a run - \global\expandafter\let\csname\??languagenumbers\currentlanguage\endcsname\undefined + \expandafter\glet\csname\??languagenumbers\currentlanguage\endcsname\undefined \to \everysetuplanguage \def\lang_basics_synchronize_yes @@ -471,7 +380,7 @@ \letvalue{\??languagenumbers}\lang_basics_synchronize_yes % runtime \to \everydump -\def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex +\def\lang_basics_synchronize {\normallanguage\csname\??languagenumbers \ifcsname\??languagenumbers\currentlanguage\endcsname \currentlanguage @@ -481,12 +390,7 @@ \the\everylanguage \relax} -% experimental - \newcount\hyphenstate - -% so far - \newcount\hyphenminoffset \unexpanded\def\lesshyphens @@ -530,7 +434,7 @@ % \setups[\languageparameter\c!setups]% % \to \everylanguage -%D You can setup the 'default' language to reset settings. +%D You can setup the default language to reset settings. \appendtoks \edef\currentlanguagesetups{\languageparameter\c!setups}% @@ -548,7 +452,12 @@ % this will move to core-spa ! \appendtoks - \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing + \edef\p_spacing{\languageparameter\c!spacing}% + \ifx\p_spacing\v!broad + \nonfrenchspacing + \else + \frenchspacing + \fi \to \everylanguage % \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?] @@ -576,11 +485,6 @@ \fi \to \everylanguage -% The following may be a solution for the fact that one cannot -% change catcodes of characters like : and ; inside an environment. - -% we will also permit access by the other names - %D Fast switcher \def\lang_basics_switch_asked @@ -613,23 +517,13 @@ \newcount\mainlanguagenumber -% \unexpanded\def\mainlanguage[#1]% -% {\edef\askedlanguage{#1}% -% \ifx\askedlanguage\empty \else -% \ifcsname\??languagelinked\askedlanguage\endcsname -% \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}% -% \ifx\currentlanguage\askedlanguage -% \ifx\currentmainlanguage\askedlanguage \else -% \setcurrentlanguage\askedlanguage\askedlanguage -% \lang_basics_synchronize -% \fi -% \else -% \setcurrentlanguage\askedlanguage\askedlanguage -% \lang_basics_synchronize -% \fi -% \fi -% \fi -% \mainlanguagenumber\normallanguage} +%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par} +%D inside the group! + +\unexpanded\def\startlanguage + {\begingroup\language} + +\let\stoplanguage\endgroup \unexpanded\def\mainlanguage[#1]% {\edef\askedlanguage{#1}% @@ -662,9 +556,8 @@ \def\splitsymbol#1% {\splitsequence{#1}{\languageparameter\c!limittext}} -%D Just like with subsentence boundary symbols, quotes -%D placement depends on the current language, therefore we show -%D the defaults here. +%D Just like with subsentence boundary symbols, quotes placement depends on the +%D current language, therefore we show the defaults here. %D %D \def\ShowLanguageValues [#1] [#2] #3 #4 %D {\blank @@ -686,6 +579,7 @@ %D \ShowLanguageValues [da] [danish] deense ... %D \ShowLanguageValues [de] [german] duitse degelijkheid %D \ShowLanguageValues [en] [english] engelse humor +%D \ShowLanguageValues [et] [estonian] ... %D \ShowLanguageValues [fi] [finnish] finse ... %D \ShowLanguageValues [fr] [french] franse slag %D \ShowLanguageValues [it] [italian] italiaanse ... @@ -699,10 +593,9 @@ %D \ShowLanguageValues [sv] [swedish] zweedse ... %D \ShowLanguageValues [tr] [turkish] turks fruit -%D We support a lot of languages. These are specified and -%D loaded in separate files, according to their roots. Here -%D we only take care of (postponed) setting of the current -%D language. +%D We support a lot of languages. These are specified and loaded in separate files, +%D according to their roots. Here we only take care of (postponed) setting of the +%D current language. %D %D \unprotect %D \placetable{The germanic languages (\type{lang-ger})} @@ -773,9 +666,8 @@ \unexpanded\def\nopatterns{\normallanguage\minusone} -%D We default to the language belonging to the interface. This -%D is one of the few places outside the interface modules where -%D \type{\startinterface} is used. +%D We default to the language belonging to the interface. This is one of the few +%D places outside the interface modules where \type {\startinterface} is used. \setupcurrentlanguage[\s!en] diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv index 73637753d64..9d73d96e589 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-lab.mkiv @@ -277,10 +277,16 @@ \def\lang_labels_text_prefix_copy_pair[#1=#2]% {\lang_labels_text_prefix_copy_pair_indeed{#1}[#2,,]} +% \def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]% +% {\expandafter\let +% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname +% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname} +% +% this delays the aliasing so that we can switch maillanguage in between + \def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]% - {\expandafter\let - \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname - \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname} + {\expandafter\edef\csname\??label\currenttextprefixclass:#1\endcsname + {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#2\endcsname}{}}} \definelabelclass [head] [0] % titles \definelabelclass [label] [0] % texts diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv index eb7dc7d808b..3ec29a782f8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-mis.mkiv @@ -145,7 +145,11 @@ %D modules these can be tuned by a setup command. Watch the (maybe) better looking %D compound hyphen. -\ifx\compoundhyphen \undefined \unexpanded\def\compoundhyphen {\hbox{-\kern-.25ex-}} \fi +% hm why ex + +\ifx\compoundhyphen \undefined + \unexpanded\def\compoundhyphen {\hbox{-\kern-.10775\emwidth-}} % .25\exheight +\fi %D The last two variables are needed for subsentences |<|like this one|>| which we %D did not yet mention. We want to enable breaking but at the same time don't want @@ -156,7 +160,8 @@ \ifx\postwordbreak\undefined \unexpanded\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi \ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % language specific -\unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces +%unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces +\unexpanded\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces %D \macros %D {beginofsubsentence,endofsubsentence, @@ -202,22 +207,21 @@ \setnewconstant\discretionarymode\plusone -\unexpanded\def\ignorediscretionaries - {\discretionarymode\zerocount} +\unexpanded\def\ignorediscretionaries{\discretionarymode\zerocount} +\unexpanded\def\obeydiscretionaries {\discretionarymode\plusone} \def\lang_discretionaries_command {% if direct if, we need \relax for lookahead in math mode \csname\??discretionarymode \ifcase\discretionarymode - n% \csstring\lang_discretionaries_process_none + n% \else\ifmmode - m% \csstring\lang_discretionaries_process_math + m% \else - t% \csstring\lang_discretionaries_process_text + t% \fi\fi \endcsname} -% \def\lang_discretionaries_process_none#1% \setvalue{\??discretionarymode n}#1% {\detokenize{#1}} @@ -230,19 +234,22 @@ \newconditional\punctafterdiscretionary \newconditional\spaceafterdiscretionary -\def\lang_discretionaries_check_before +\def\lang_discretionaries_check_before %i sused grouped {\ifvmode \dontleavehmode \fi \ifhmode - \begingroup - \setbox\scratchbox\lastbox - \ifzeropt\wd\scratchbox - \let\postwordbreak\prewordbreak - \fi - \box\scratchbox\relax - \endgroup - \fi} + %\begingroup + %\setbox\scratchbox\lastbox + %\ifzeropt\wd\scratchbox + % \box\scratchbox\relax + % \endgroup + % \let\postwordbreak\prewordbreak + %\else + % \box\scratchbox\relax + % \endgroup + %\fi + \fi} \def\lang_discretionaries_check_after {\setfalse\punctafterdiscretionary @@ -254,10 +261,8 @@ \ifx :\nextnext \settrue \punctafterdiscretionary \else \ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi} -%let\lang_discretionaries_process_math\handlemathmodediscretionary \letvalue{\??discretionarymode m}\handlemathmodediscretionary -% \def\lang_discretionaries_process_text#1% grouped ! \setvalue{\??discretionarymode t}#1% {\bgroup \let\nextnextnext\egroup @@ -278,39 +283,47 @@ \ifcsname\??discretionaryaction\string#1\endcsname \lastnamedcs \else\ifconditional\spaceafterdiscretionary - \prewordbreak\hbox{\string#1}\relax + %\prewordbreak\hbox{\string#1}\relax + \wordboundary\hbox{\string#1}\relax \else\ifconditional\punctafterdiscretionary - \prewordbreak\hbox{\string#1}\relax + %\prewordbreak\hbox{\string#1}\relax + \wordboundary\hbox{\string#1}\wordboundary \else - \prewordbreak\hbox{\string#1}\prewordbreak + %\prewordbreak\hbox{\string#1}\prewordbreak + \wordboundary\hbox{\string#1}\wordboundary \fi\fi\fi \def\nextnextnext{\afterassignment\egroup\let\next=}% \else \lang_discretionaries_check_before % the next line has been changed (20050203) - % \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak + % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak % but an hbox blocks a possible \discretionary \ifcsname\??discretionaryaction\endcsname \lastnamedcs \else\ifconditional\spaceafterdiscretionary - \prewordbreak\textmodediscretionary\relax + %\prewordbreak\textmodediscretionary\relax + \wordboundary\textmodediscretionary\relax \else\ifconditional\punctafterdiscretionary - \prewordbreak\textmodediscretionary\relax + %\prewordbreak\textmodediscretionary\relax + \wordboundary\textmodediscretionary\relax \else - \prewordbreak\textmodediscretionary\prewordbreak + %\prewordbreak\textmodediscretionary\prewordbreak + \wordboundary\textmodediscretionary\wordboundary \fi\fi\fi - % \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak \fi \else\ifcsname\??discretionaryaction\discretionarytoken\endcsname \lastnamedcs \else \lang_discretionaries_check_before \ifconditional\spaceafterdiscretionary - \prewordbreak\hbox{#2}\relax + %\prewordbreak\hbox{#2}\relax + \wordboundary\hbox{#2}\relax \else\ifconditional\punctafterdiscretionary - \prewordbreak\hbox{#2}\relax + %\prewordbreak\hbox{#2}\relax + \wordboundary\hbox{#2}\relax \else - \prewordbreak\discretionary{\hbox{#2}}{}{\hbox{#2}}\allowbreak\postwordbreak + %\prewordbreak\discretionary{\hbox{#2}}{}{\hbox{#2}}\postwordbreak + \wordboundary\discretionary{\hbox{#2}}{}{\hbox{#2}}\wordboundary \fi\fi \fi\fi \nextnextnext} @@ -324,35 +337,33 @@ \unexpanded\def\directdiscretionary {\csname\??discretionarymode \ifcase\discretionarymode - n% \csstring\lang_discretionaries_process_none + n% \else - d% \csstring\lang_discretionaries_process_direct + d% \fi \endcsname} \unexpanded\def\indirectdiscretionary {\csname\??discretionarymode \ifcase\discretionarymode - n% \csstring\lang_discretionaries_process_none + n% \else - i% \csstring\lang_discretionaries_process_indirect + i% \fi \endcsname} -% \unexpanded\def\lang_discretionaries_process_direct#1% \setuvalue{\??discretionarymode d}#1% {\edef\discretionarytoken{\detokenize{#1}}% \let\textmodediscretionary\compoundhyphen - %\executeifdefined{\??discretionaryaction\discretionarytoken}{\indirectdiscretionary{#1}}} \ifcsname\??discretionaryaction\discretionarytoken\endcsname \expandafter\lastnamedcs \else \expandafter\indirectdiscretionary \fi{#1}} -% \unexpanded\unexpanded\def\lang_discretionaries_process_indirect#1% \setuvalue{\??discretionarymode i}#1% - {\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\allowbreak\postwordbreak} + %{\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\postwordbreak} + {\wordboundary\discretionary{\hbox{#1}}{}{\hbox{#1}}\wordboundary} \unexpanded\def\definetextmodediscretionary #1 {\setvalue{\??discretionaryaction\detokenize{#1}}} @@ -376,11 +387,14 @@ \def\lang_discretionaries_hyphen_like#1#2% {\ifconditional\spaceafterdiscretionary - \prewordbreak\hbox{#1}\relax + %prewordbreak\hbox{#1}\relax + \wordboundary\hbox{#1}\relax \else\ifconditional\punctafterdiscretionary - \prewordbreak\hbox{#1}\relax + %prewordbreak\hbox{#1}\relax + \wordboundary\hbox{#1}\relax \else - \prewordbreak#2\postwordbreak % was prewordbreak + %\prewordbreak#2\postwordbreak % was prewordbreak + \wordboundary#2\wordboundary \fi\fi} \definetextmodediscretionary {} @@ -397,59 +411,65 @@ \definetextmodediscretionary ( {\ifdim\lastskip>\zeropoint - (\prewordbreak + %(\prewordbreak + (\wordboundary \else - \prewordbreak\discretionary{}{(-}{(}\prewordbreak + %\prewordbreak\discretionary{}{(-}{(}\prewordbreak + \wordboundary\discretionary{}{(-}{(}\wordboundary \fi} \definetextmodediscretionary ~ - {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak} + %{\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak} + {\wordboundary\discretionary{-}{}{\thinspace}\wordboundary} \definetextmodediscretionary ' - {\prewordbreak\discretionary{-}{}{'}\postwordbreak} + %{\prewordbreak\discretionary{-}{}{'}\postwordbreak} + {\wordboundary\discretionary{-}{}{'}\wordboundary} \definetextmodediscretionary ^ - {\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% - \allowbreak\postwordbreak} % bugged - -% \definetextmodediscretionary < -% {\beginofsubsentence\prewordbreak\beginofsubsentencespacing} -% -% \definetextmodediscretionary > -% {\endofsubsentencespacing\prewordbreak\endofsubsentence} -% -% \definetextmodediscretionary = -% {\prewordbreak\midsentence\prewordbreak} + %{\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% + % \postwordbreak} % bugged + {\wordboundary\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}% + \wordboundary} % bugged \definetextmodediscretionary < - {\beginofsubsentence\prewordbreak\beginofsubsentencespacing + %{\beginofsubsentence\prewordbreak\beginofsubsentencespacing + {\beginofsubsentence\wordboundary\beginofsubsentencespacing \aftergroup\ignorespaces} % tricky, we need to go over the \nextnextnext \definetextmodediscretionary > {\removeunwantedspaces - \endofsubsentencespacing\prewordbreak\endofsubsentence} + %\endofsubsentencespacing\prewordbreak\endofsubsentence} + \endofsubsentencespacing\wordboundary\endofsubsentence} \definetextmodediscretionary = {\removeunwantedspaces - \prewordbreak\midsentence\prewordbreak + %\prewordbreak\midsentence\prewordbreak + \wordboundary\midsentence\wordboundary \aftergroup\ignorespaces} % french -\definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:} -\definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};} -\definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?} -\definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!} +%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:} +%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};} +%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?} +%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!} + +\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{:}:} +\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{;};} +\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{?}?} +\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{!}!} -\definetextmodediscretionary * - {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak} +%definetextmodediscretionary * {\prewordbreak\discretionary{-}{}{\kern.05\emwidth}\prewordbreak} +\definetextmodediscretionary * {\wordboundary\discretionary{-}{}{\kern.05\emwidth}\wordboundary} % spanish -\definetextmodediscretionary ?? {\prewordbreak\questiondown} -\definetextmodediscretionary !! {\prewordbreak\exclamdown} +%definetextmodediscretionary ?? {\prewordbreak\questiondown} +%definetextmodediscretionary !! {\prewordbreak\exclamdown} -% \ifx\normalcompound\undefined \let\normalcompound=| \fi +\definetextmodediscretionary ?? {\wordboundary\questiondown} +\definetextmodediscretionary !! {\wordboundary\exclamdown} %D \installdiscretionary | + %D \installdiscretionary + = diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua index a5c4d97c826..93509d82a3e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-rep.lua @@ -42,8 +42,6 @@ local report_replacement = logs.reporter("languages","replacements") local glyph_code = nodes.nodecodes.glyph local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -217,9 +215,7 @@ local function tonodes(list,template) end function replacements.handler(head) - head = tonut(head) local current = head - local done = false local overload = attributes.applyoverloads while current do if getid(current) == glyph_code then @@ -327,14 +323,13 @@ function replacements.handler(head) if overload then overload(final,getnext(precurrent),getprev(current)) end - done = true end end end -- we're one ahead now but we need to because we handle words current = getnext(current) end - return tonode(head), done + return head end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv index e7cb0025fd6..7109ad0511a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-spa.mkiv @@ -41,17 +41,15 @@ %D Alternative discretionary handlers: -\definetextmodediscretionary : - {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{:}:} +%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{:}:} +%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{;};} +%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{?}?} +%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{!}!} -\definetextmodediscretionary ; - {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{;};} - -\definetextmodediscretionary ? - {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{?}?} - -\definetextmodediscretionary ! - {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{!}!} +\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{:}:} +\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{;};} +\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{?}?} +\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{!}!} %D \startbuffer %D \mainlanguage[en] \quotation{test \quotation{test} test}\par diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua index b1f50bc804e..d287f7e6d6c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua @@ -25,6 +25,7 @@ if not modules then modules = { } end modules ['lang-txt'] = { -- de German Tobias Burnus, ... -- en English Hans Hagen, ... -- es Spanish Andrés Montoya, ... +-- et Estonian Clyde Johnston -- fi Finish ... -- fr French Daniel Flipo, Arthur Reutenauer -- gr Greek Apostolos Syropoulos, Thomas Schmitz @@ -86,6 +87,7 @@ data.labels={ ["labels"]={ ["de"]="Band", ["en"]="Volume", + ["et"]="Köide", ["nl"]="Deel", ["pe"]="جلد", }, @@ -95,6 +97,7 @@ data.labels={ ["de"]="und", ["en"]="and", ["es"]="y", + ["et"]="ja", ["fr"]="et", ["it"]="e", ["nl"]="en", @@ -106,6 +109,7 @@ data.labels={ ["de"]="Auflage", ["en"]="edition", ["es"]="edición", + ["et"]="väljaanne", ["fr"]="édition", ["it"]="edizione", ["nl"]="editie", @@ -116,6 +120,7 @@ data.labels={ ["labels"]={ ["de"]="Herausgeber", ["en"]="editor", + ["et"]="toimetaja", ["fr"]="éditeur", ["it"]="a cura di", ["pe"]="ویراستار", @@ -126,6 +131,7 @@ data.labels={ ["de"]="Herausgeber", ["en"]="editors", ["es"]="editores", + ["et"]="toimetajad", ["fr"]="éditeurs", ["it"]="a cura di", }, @@ -143,6 +149,7 @@ data.labels={ ["de"]="Masterarbeit", ["en"]="Master's thesis", ["es"]="Tesis de maestría", + ["et"]="magistritöö", ["fr"]="Thèse de master (DEA, DESS, master)", ["it"]="Tesi di laurea", ["nl"]="Masterproef", @@ -169,12 +176,14 @@ data.labels={ ["others"]={ ["labels"]={ ["en"]="et al.", + ["et"]="jt", }, }, ["p"]={ ["labels"]={ ["de"]="S.", ["en"]="p.", + ["et"]="lk", ["pe"]="ص", }, }, @@ -182,6 +191,7 @@ data.labels={ ["labels"]={ ["de"]="Seiten", ["en"]="pages", + ["et"]="leheküljed", ["nl"]="paginas", ["pe"]="صفحات", }, @@ -191,6 +201,7 @@ data.labels={ ["de"]="Patent", ["en"]="Patent", ["es"]="Patente", + ["et"]="Patent", ["fr"]="Brevet", ["it"]="Brevetto", ["nl"]="Octrooi", @@ -201,6 +212,7 @@ data.labels={ ["de"]="Dissertation", ["en"]="PhD thesis", ["es"]="Tesis doctoral", + ["et"]="doktoritöö", ["fr"]="Thèse de doctorat", ["it"]="Tesi di dottorato", ["nl"]="Proefschrift", @@ -211,6 +223,7 @@ data.labels={ ["labels"]={ ["de"]="S.", ["en"]="pp.", + ["et"]="lk-d", ["pe"]="صص", }, }, @@ -219,6 +232,7 @@ data.labels={ ["de"]="Technischer Bericht", ["en"]="Technical report", ["es"]="Informe técnico", + ["et"]="tehniline raport", ["fr"]="Rapport technique", ["it"]="Relazione tecnica", ["nl"]="Technisch rapport", @@ -229,6 +243,7 @@ data.labels={ ["labels"]={ ["de"]="Band", ["en"]="volume", + ["et"]="köide", ["nl"]="deel", ["pe"]="جلد", }, @@ -238,6 +253,7 @@ data.labels={ ["de"]="mit", ["en"]="with", ["es"]="con", + ["et"]="koos", ["fr"]="avec", ["it"]="con", ["nl"]="met", @@ -615,28 +631,29 @@ data.labels={ ["labels"]={ ["af"]="", ["ca"]="", - ["cs"]="a", + ["cs"]=" a ", ["da"]="", - ["de"]="und", - ["en"]="and", - ["es"]="y", + ["de"]=" und ", + ["en"]=" and ", + ["es"]=" y ", + ["et"]=" ja ", ["fi"]="", ["fr"]="", ["gr"]="", - ["hr"]="i", - ["hu"]="és", + ["hr"]=" i ", + ["hu"]=" és ", ["it"]="", ["la"]="", ["lt"]="", ["nb"]="", - ["nl"]="en", + ["nl"]=" en ", ["nn"]="", - ["pe"]="و", - ["pl"]="i", + ["pe"]=" و ", + ["pl"]=" i ", ["pt"]="", ["ro"]="", ["ru"]="", - ["sk"]="a", + ["sk"]=" a ", ["sl"]="", ["sv"]="", ["tk"]="", @@ -657,6 +674,7 @@ data.labels={ ["de"]="Anhang ", ["en"]="Appendix ", ["es"]="Apéndice ", + ["et"]="Lisa ", ["fi"]="", ["fr"]="Annexe ", ["gr"]="Παράρτημα", @@ -697,6 +715,7 @@ data.labels={ ["de"]="April", ["en"]="April", ["es"]="abril", + ["et"]="aprill", ["fi"]="huhtikuu", ["fr"]="avril", ["gr"]="Απρίλιος", @@ -739,6 +758,7 @@ data.labels={ ["de"]="", ["en"]="apr", ["es"]="abr.", + ["et"]="apr", ["fi"]="", ["fr"]="", ["gr"]="", @@ -773,6 +793,7 @@ data.labels={ ["de"]="auf Seite ", ["en"]="at page ", ["es"]="en la página ", + ["et"]="leheküljel ", ["fi"]="", ["fr"]="à la page ", ["gr"]="", @@ -812,6 +833,7 @@ data.labels={ ["de"]="August", ["en"]="August", ["es"]="agosto", + ["et"]="august", ["fi"]="elokuu", ["fr"]="août", ["gr"]="Αύγουστος", @@ -854,6 +876,7 @@ data.labels={ ["de"]="", ["en"]="aug", ["es"]="ago.", + ["et"]="aug", ["fi"]="", ["fr"]="", ["gr"]="", @@ -890,6 +913,7 @@ data.labels={ ["de"]="Kapitel ", ["en"]="Chapter ", ["es"]="Capítulo ", + ["et"]="Peatükk ", ["fi"]="", ["fr"]="Chapitre ", ["gr"]="Κεφάλαιο", @@ -926,6 +950,7 @@ data.labels={ ["de"]="", ["en"]=" (continued)", ["es"]=" (continúa)", + ["et"]=" (jätkub)", ["fi"]="", ["fr"]="", ["gr"]="", @@ -954,6 +979,7 @@ data.labels={ ["day"]={ ["labels"]={ ["en"]="day", + ["et"]="päev", ["kr"]="일", ["nl"]="dag", ["pe"]="روز", @@ -972,6 +998,7 @@ data.labels={ ["de"]="Dezember", ["en"]="December", ["es"]="diciembre", + ["et"]="detsember", ["fi"]="joulukuu", ["fr"]="décembre", ["gr"]="Δεκέμβριος", @@ -1014,6 +1041,7 @@ data.labels={ ["de"]="", ["en"]="dec", ["es"]="dic.", + ["et"]="dets", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1051,6 +1079,7 @@ data.labels={ ["de"]="Februar", ["en"]="February", ["es"]="febrero", + ["et"]="veebruar", ["fi"]="helmikuu", ["fr"]="février", ["gr"]="Φεβρουάριος", @@ -1093,6 +1122,7 @@ data.labels={ ["de"]="", ["en"]="feb", ["es"]="feb.", + ["et"]="veebr", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1128,6 +1158,7 @@ data.labels={ ["de"]="Abbildung ", ["en"]="Figure ", ["es"]="Figura ", + ["et"]="Joonis ", ["fi"]="Kuva ", ["fr"]="Figure ", ["gr"]="Σχήμα", @@ -1158,6 +1189,7 @@ data.labels={ ["followingpage"]={ ["labels"]={ ["en"]="on a following page", + ["et"]="järgmisel leheküljel", ["nl"]="op een volgende bladzijde", ["pe"]="در صفحات آینده", }, @@ -1173,6 +1205,7 @@ data.labels={ ["de"]="Freitag", ["en"]="Friday", ["es"]="viernes", + ["et"]="reede", ["fi"]="perjantai", ["fr"]="vendredi", ["gr"]="Παρασκευή", @@ -1211,6 +1244,7 @@ data.labels={ ["de"]="Graphik ", ["en"]="Graphic ", ["es"]="Gráfico ", + ["et"]="Pilt ", ["fi"]="Grafiikka ", ["fr"]="Illustration ", ["gr"]="Γραφικό", @@ -1247,6 +1281,7 @@ data.labels={ ["de"]="siehe oben", ["en"]="as we show above", ["es"]="como se muestra arriba", + ["et"]="nii nagu üleval näidatud", ["fi"]="", ["fr"]="ci-dessus", ["gr"]="", @@ -1283,6 +1318,7 @@ data.labels={ ["de"]="siehe unten", ["en"]="as we show below", ["es"]="como se muestra abajo", + ["et"]="nii nagu all näidatud", ["fi"]="", ["fr"]="ci-dessous", ["gr"]="", @@ -1320,6 +1356,7 @@ data.labels={ ["de"]="Intermezzo ", ["en"]="Intermezzo ", ["es"]="Intermedio ", + ["et"]="Vahemäng ", ["fi"]="Intermezzo ", ["fr"]="Intermède ", ["gr"]="Παύση", @@ -1359,6 +1396,7 @@ data.labels={ ["de"]="Januar", ["en"]="January", ["es"]="enero", + ["et"]="jaanuar", ["fi"]="tammikuu", ["fr"]="janvier", ["gr"]="Ιανουάριος", @@ -1401,6 +1439,7 @@ data.labels={ ["de"]="", ["en"]="jan", ["es"]="ene.", + ["et"]="jaan", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1439,6 +1478,7 @@ data.labels={ ["de"]="Juli", ["en"]="July", ["es"]="julio", + ["et"]="juuli", ["fi"]="heinäkuu", ["fr"]="juillet", ["gr"]="Ιούλιος", @@ -1481,6 +1521,7 @@ data.labels={ ["de"]="", ["en"]="jul", ["es"]="jul.", + ["et"]="juuli", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1518,6 +1559,7 @@ data.labels={ ["de"]="Juni", ["en"]="June", ["es"]="junio", + ["et"]="juuni", ["fi"]="kesäkuu", ["fr"]="juin", ["gr"]="Ιούνιος", @@ -1560,6 +1602,7 @@ data.labels={ ["de"]="", ["en"]="jun", ["es"]="jun.", + ["et"]="juuni", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1595,6 +1638,7 @@ data.labels={ ["de"]="Zeile ", ["en"]="line ", ["es"]="línea ", + ["et"]="joon ", ["fi"]="rivi ", ["fr"]="ligne ", ["gr"]="Γραμμή", @@ -1633,6 +1677,7 @@ data.labels={ ["de"]="Zeilen ", ["en"]="lines ", ["es"]="líneas ", + ["et"]="jooned ", ["fi"]="rivie ", ["fr"]="lignes ", ["gr"]="Γραμμές", @@ -1672,6 +1717,7 @@ data.labels={ ["de"]="März", ["en"]="March", ["es"]="marzo", + ["et"]="märts", ["fi"]="maaliskuu", ["fr"]="mars", ["gr"]="Μάρτιος", @@ -1714,6 +1760,7 @@ data.labels={ ["de"]="", ["en"]="mar", ["es"]="mar.", + ["et"]="märts", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1752,6 +1799,7 @@ data.labels={ ["de"]="Mai", ["en"]="May", ["es"]="mayo", + ["et"]="mai", ["fi"]="toukokuu", ["fr"]="mai", ["gr"]="Μάιος", @@ -1794,6 +1842,7 @@ data.labels={ ["de"]="", ["en"]="may", ["es"]="may.", + ["et"]="mai", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1829,6 +1878,7 @@ data.labels={ ["de"]="Montag", ["en"]="Monday", ["es"]="lunes", + ["et"]="esmaspäev", ["fi"]="maanantai", ["fr"]="lundi", ["gr"]="Δευτέρα", @@ -1859,6 +1909,7 @@ data.labels={ ["month"]={ ["labels"]={ ["en"]="month", + ["et"]="kuu", ["kr"]="월", ["nl"]="maand", ["pe"]="ماه", @@ -1877,6 +1928,7 @@ data.labels={ ["de"]="November", ["en"]="November", ["es"]="noviembre", + ["et"]="november", ["fi"]="marraskuu", ["fr"]="novembre", ["gr"]="Νοέμβριος", @@ -1919,6 +1971,7 @@ data.labels={ ["de"]="", ["en"]="nov", ["es"]="nov.", + ["et"]="nov", ["fi"]="", ["fr"]="", ["gr"]="", @@ -1955,6 +2008,7 @@ data.labels={ ["de"]="Oktober", ["en"]="October", ["es"]="octubre", + ["et"]="oktoober", ["fi"]="lokakuu", ["fr"]="octobre", ["gr"]="Οκτώβριος", @@ -1997,6 +2051,7 @@ data.labels={ ["de"]="", ["en"]="oct", ["es"]="oct.", + ["et"]="okt", ["fi"]="", ["fr"]="", ["gr"]="", @@ -2031,6 +2086,7 @@ data.labels={ ["de"]="Seite ", ["en"]="page ", ["es"]="página ", + ["et"]="lehekülg ", ["fi"]="", ["fr"]="page ", ["gr"]="", @@ -2068,6 +2124,7 @@ data.labels={ ["de"]="Teil ", ["en"]="Part ", ["es"]="Parte ", + ["et"]="Osa ", ["fi"]="Osa ", ["fr"]="Partie ", ["gr"]="Μέρος", @@ -2098,6 +2155,7 @@ data.labels={ ["precedingpage"]={ ["labels"]={ ["en"]="on a preceding page", + ["et"]="eelmisel lehel", ["nl"]="op een voorgaande bladzijde", ["pe"]="در صفحات گذشته", }, @@ -2113,6 +2171,7 @@ data.labels={ ["de"]="Samstag", ["en"]="Saturday", ["es"]="sábado", + ["et"]="laupäev", ["fi"]="lauantai", ["fr"]="samedi", ["gr"]="Σάββατο", @@ -2152,6 +2211,7 @@ data.labels={ ["de"]="", ["en"]="", ["es"]="Sección ", + ["et"]="jaos ", ["fi"]="", ["fr"]="Section ", ["gr"]="Ενότητα", @@ -2189,6 +2249,7 @@ data.labels={ ["de"]="siehe ", ["en"]="see ", ["es"]="ver: ", + ["et"]="vaadake ", ["fi"]="", ["fr"]="cf. ", ["gr"]="", @@ -2228,6 +2289,7 @@ data.labels={ ["de"]="September", ["en"]="September", ["es"]="septiembre", + ["et"]="september", ["fi"]="syyskuu", ["fr"]="septembre", ["gr"]="Σεπτέμβριος", @@ -2270,6 +2332,7 @@ data.labels={ ["de"]="", ["en"]="sep", ["es"]="sep.", + ["et"]="sept", ["fi"]="", ["fr"]="", ["gr"]="", @@ -2306,6 +2369,7 @@ data.labels={ ["de"]="", ["en"]="", ["es"]="Subsección ", + ["et"]="alajaotis ", ["fi"]="", ["fr"]="Soussection ", ["gr"]="Υπόενότητα", @@ -2344,6 +2408,7 @@ data.labels={ ["de"]="", ["en"]="", ["es"]="Subsubsección ", + ["et"]="alamjaotis ", ["fi"]="", ["fr"]="Soussoussection ", ["gr"]="", @@ -2382,6 +2447,7 @@ data.labels={ ["de"]="", ["en"]="", ["es"]="Subsubsubsección ", + ["et"]="", ["fi"]="", ["fr"]="Soussoussoussection ", ["gr"]="", @@ -2419,6 +2485,7 @@ data.labels={ ["de"]="Sonntag", ["en"]="Sunday", ["es"]="domingo", + ["et"]="pühapäev", ["fi"]="sunnuntai", ["fr"]="dimanche", ["gr"]="Κυριακή", @@ -2457,6 +2524,7 @@ data.labels={ ["de"]="Tabelle ", ["en"]="Table ", ["es"]="Tabla ", + ["et"]="Tabel ", ["fi"]="Taulukko ", ["fr"]="Tableau ", ["gr"]="Πίνακας", @@ -2495,6 +2563,7 @@ data.labels={ ["de"]="Donnerstag", ["en"]="Thursday", ["es"]="jueves", + ["et"]="neljapäev", ["fi"]="torstai", ["fr"]="jeudi", ["gr"]="Πέμπτη", @@ -2533,6 +2602,7 @@ data.labels={ ["de"]="Dienstag", ["en"]="Tuesday", ["es"]="martes", + ["et"]="teisipäev", ["fi"]="tiistai", ["fr"]="mardi", ["gr"]="Τρίτη", @@ -2571,6 +2641,7 @@ data.labels={ ["de"]="Mittwoch", ["en"]="Wednesday", ["es"]="miércoles", + ["et"]="kolmapäev", ["fi"]="keskiviikko", ["fr"]="mercredi", ["gr"]="Τετάρτη", @@ -2601,6 +2672,7 @@ data.labels={ ["year"]={ ["labels"]={ ["en"]="year", + ["et"]="aasta", ["kr"]="년", ["nl"]="jaar", ["pe"]="سال", @@ -2619,6 +2691,7 @@ data.labels={ ["de"]="Abkürzungen", ["en"]="Abbreviations", ["es"]="Abreviaturas", + ["et"]="Lühend", ["fi"]="Lyhennyksi", ["fr"]="Abréviations", ["gr"]="Συντομογραφίες", @@ -2657,6 +2730,7 @@ data.labels={ ["de"]="Inhalt", ["en"]="Contents", ["es"]="Contenido", + ["et"]="Sisu", ["fi"]="Sisällys", ["fr"]="Table des matières", ["gr"]="Περιεχόμενα", @@ -2695,6 +2769,7 @@ data.labels={ ["de"]="Abbildungen", ["en"]="Figures", ["es"]="Figuras", + ["et"]="Arvandmed", ["fi"]="Kuvi", ["fr"]="Figures", ["gr"]="Σχήματα", @@ -2733,6 +2808,7 @@ data.labels={ ["de"]="Graphiken", ["en"]="Graphics", ["es"]="Gráficos", + ["et"]="Graafika", ["fi"]="Grafiikkaoi", ["fr"]="Graphiques", ["gr"]="Γραφικά", @@ -2771,6 +2847,7 @@ data.labels={ ["de"]="Index", ["en"]="Index", ["es"]="Índice", + ["et"]="Indeks", ["fi"]="Indeksiluku", ["fr"]="Index", ["gr"]="Ευρετήριο", @@ -2809,6 +2886,7 @@ data.labels={ ["de"]="Intermezzi", ["en"]="Intermezzos", ["es"]="Intermedios", + ["et"]="Vahemängud", ["fi"]="Intermezzos", ["fr"]="Intermèdes", ["gr"]="Παύσεις", @@ -2846,6 +2924,7 @@ data.labels={ ["de"]="Logos", ["en"]="Logos", ["es"]="Logotipos", + ["et"]="Logos", ["fi"]="Vertauskuva", ["fr"]="Logos", ["gr"]="Λογότυπα", @@ -2882,6 +2961,7 @@ data.labels={ ["de"]="Literatur", ["en"]="References", ["es"]="Bibliografía", + ["et"]="Viited", ["fi"]="", ["fr"]="Bibliographie", ["gr"]="", @@ -2919,6 +2999,7 @@ data.labels={ ["de"]="Tabellen", ["en"]="Tables", ["es"]="Tablas", + ["et"]="Tabelid", ["fi"]="Taulukkoj", ["fr"]="Tableaux", ["gr"]="Πίνακες", @@ -2957,6 +3038,7 @@ data.labels={ ["de"]="Einheiten", ["en"]="Units", ["es"]="Unidades", + ["et"]="Ühikud", ["fi"]="Yksiköt", ["fr"]="Unités", ["gr"]="Μονάδες", diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua index 95d9592067d..17ad15cd890 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-url.lua @@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['lang-url'] = { local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char local min, max = math.min, math.max -local concat = table.concat local context = context @@ -77,9 +76,10 @@ urls.righthyphenmin = 3 urls.discretionary = nil urls.packslashes = false -directives.register("hyphenators.urls.packslashes",function(v) - urls.packslashes = v -end) +directives.register("hyphenators.urls.packslashes",function(v) urls.packslashes = v end) + +local trace = false trackers.register("hyphenators.urls",function(v) trace = v end) +local report = logs.reporter("hyphenators","urls") -- local ctx_a = context.a -- local ctx_b = context.b @@ -153,8 +153,10 @@ local function action(hyphenatedurl,str,left,right,disc) local pack = urls.packslashes local length = 0 local list = utf.split(str) + local size = #list + local prev = nil - for i=1,#list do + for i=1,size do local what = nil local dodi = false local char = list[i] @@ -162,7 +164,7 @@ local function action(hyphenatedurl,str,left,right,disc) char = mapping[char] or char if char == disc then dodi = true - elseif pack and char == "/" and list[i+1] == "/" then + elseif pack and char == "/" and (list[i+1] == "/" or prev == "/") then what = "c" else local how = characters[char] @@ -192,9 +194,13 @@ local function action(hyphenatedurl,str,left,right,disc) else list[i] = "\\" .. what .. "{" .. utfbyte(char) .. "}" end + prev = char + end + if trace then + report("old : %s",str) + report("new : %t",list) end - list = concat(list) - context(list) + context("%t",list) end -- urls.action = function(_,...) action(...) end -- sort of obsolete diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua index 7363dbb3168..9fbced2ce95 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lang-wrd.lua @@ -31,7 +31,6 @@ local numbers = languages.numbers local registered = languages.registered local nuts = nodes.nuts -local tonut = nuts.tonut ----- getfield = nuts.getfield local getnext = nuts.getnext @@ -43,8 +42,8 @@ local setattr = nuts.setattr local getlang = nuts.getlang local ischar = nuts.ischar -local traverse_nodes = nuts.traverse ------ traverse_ids = nuts.traverse_id +local nextnode = nuts.traversers.node +----- nextglyph = nuts.traversers.glyph local wordsdata = words.data local chardata = characters.data @@ -145,14 +144,13 @@ end -- there is an n=1 problem somewhere in nested boxes local function mark_words(head,whenfound) -- can be optimized and shared - local current, language, done = tonut(head), nil, nil, 0, false + local current, language = head, nil, nil, 0 local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls local function action() if s > 0 then local word = concat(str,"",1,s) local mark = whenfound(language,word) if mark then - done = true for i=1,n do mark(nds[i]) end @@ -198,7 +196,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared -- n = n + 1 -- nds[n] = current -- -- - -- for current in traverse_ids(glyph_code,r) do + -- for current in nextglyph, r do -- local code = getchar(current) -- n = n + 1 -- nds[n] = current @@ -217,7 +215,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared if s > 0 then action() end - return head, done + return head end local methods = { } @@ -285,7 +283,7 @@ local function sweep(language,str) end methods[1] = function(head) - for n in traverse_nodes(head) do + for n in nextnode, head do setattr(n,a_color,unsetvalue) -- hm, not that selective (reset color) end return mark_words(head,sweep) @@ -380,7 +378,7 @@ local function sweep(language,str) end methods[3] = function(head) - for n in traverse_nodes(head) do + for n in nextnode, head do setattr(n,a_color,unsetvalue) end return mark_words(head,sweep) diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua index 01f015b7284..49bf973c9f8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua @@ -18,6 +18,7 @@ local rep, format, find = string.rep, string.format, string.find local min = math.min local lpegmatch = lpeg.match local formatters = string.formatters +local sortedkeys = table.sortedkeys local backends, lpdf = backends, lpdf @@ -48,10 +49,6 @@ local nodeinjections = backends.pdf.nodeinjections local codeinjections = backends.pdf.codeinjections local registrations = backends.pdf.registrations -local getpos = codeinjections.getpos -local gethpos = codeinjections.gethpos -local getvpos = codeinjections.getvpos - local javascriptcode = interactions.javascripts.code local references = structures.references @@ -68,12 +65,15 @@ local executers = references.executers local nodepool = nodes.pool ------ pdfannotation_node = nodepool.pdfannotation ------ pdfdestination_node = nodepool.pdfdestination local new_latelua = nodepool.latelua local texgetcount = tex.getcount +local jobpositions = job.positions +local getpos = jobpositions.getpos +local gethpos = jobpositions.gethpos +local getvpos = jobpositions.getvpos + local pdfdictionary = lpdf.dictionary local pdfarray = lpdf.array local pdfreference = lpdf.reference @@ -106,6 +106,32 @@ local pdf_fit = pdfconstant("Fit") local pdf_named = pdfconstant("Named") local autoprefix = "#" +local usedautoprefixes = { } + +local function registerautoprefix(name) + local internal = autoprefix .. name + if usedautoprefixes[internal] == nil then + usedautoprefixes[internal] = false + end + return internal +end + +local function useautoprefix(name) + local internal = autoprefix .. name + usedautoprefixes[internal] = true + return internal +end + +local function checkautoprefixes(destinations) + for k, v in next, usedautoprefixes do + if not v then + if trace_destinations then + report_destinations("flushing unused autoprefix %a",k) + end + destinations[k] = nil + end + end +end -- Bah, I hate this kind of features .. anyway, as we have delayed resolving we -- only support a document-wide setup and it has to be set before the first one @@ -113,9 +139,9 @@ local autoprefix = "#" -- thin without dashing lines. This is as far as I'm prepared to go. This way -- it can also be used as a debug feature. -local pdf_border_style = pdfarray { 0, 0, 0 } -- radius radius linewidth -local pdf_border_color = nil -local set_border = false +local pdf_border_style = pdfarray { 0, 0, 0 } -- radius radius linewidth +local pdf_border_color = nil +local set_border = false local function pdfborder() set_border = true @@ -131,7 +157,9 @@ directives.register("references.border",function(v) local c = m and m[v] local v = c and attributes.colors.value(c) if v then - local r, g, b = v[3], v[4], v[5] + local r = v[3] + local g = v[4] + local b = v[5] -- if r == g and g == b then -- pdf_border_color = pdfarray { r } -- reduced, not not ... bugged viewers -- else @@ -192,12 +220,16 @@ local defaultdestination = pdfarray { 0, pdf_fit } -- fit is default (see lpdf-nod) -local destinations = { } -- to be used soon +local destinations = { } +local reported = setmetatableindex("table") local function pdfregisterdestination(name,reference) local d = destinations[name] if d then - report_destinations("ignoring duplicate destination %a with reference %a",name,reference) + if not reported[name][reference] then + report_destinations("ignoring duplicate destination %a with reference %a",name,reference) + reported[name][reference] = true + end else destinations[name] = reference end @@ -222,7 +254,11 @@ end) local function pdfnametree(destinations) local slices = { } - local sorted = table.sortedkeys(destinations) + checkautoprefixes(destinations) + if not next(destinations) then + return + end + local sorted = sortedkeys(destinations) local size = #sorted if size <= 1.5*maxslice then @@ -232,11 +268,12 @@ local function pdfnametree(destinations) for i=1,size,maxslice do local amount = min(i+maxslice-1,size) local names = pdfarray { } + local n = 0 for j=i,amount do local destination = sorted[j] local pagenumber = destinations[destination] - names[#names+1] = tostring(destination) -- tostring is a safeguard - names[#names+1] = pdfreference(pagenumber) + n = n + 1 ; names[n] = tostring(destination) -- tostring is a safeguard + n = n + 1 ; names[n] = pdfreference(pagenumber) end local first = sorted[i] local last = sorted[amount] @@ -254,18 +291,23 @@ local function pdfnametree(destinations) } end local function collectkids(slices,first,last) - local k = pdfarray() - local d = pdfdictionary { - Kids = k, - Limits = pdfarray { - slices[first].limits[1], - slices[last ].limits[2], - }, - } - for i=first,last do - k[#k+1] = slices[i].reference + local f = slices[first] + local l = slices[last] + if f and l then + local k = pdfarray() + local n = 0 + local d = pdfdictionary { + Kids = k, + Limits = pdfarray { + f.limits[1], + l.limits[2], + }, + } + for i=first,last do + n = n + 1 ; k[n] = slices[i].reference + end + return d end - return d end if #slices == 1 then return slices[1].reference @@ -276,14 +318,24 @@ local function pdfnametree(destinations) local size = #slices for i=1,size,maxslice do local kids = collectkids(slices,i,min(i+maxslice-1,size)) - temp[#temp+1] = { - reference = pdfreference(pdfflushobject(kids)), - limits = kids.Limits, - } + if kids then + temp[#temp+1] = { + reference = pdfreference(pdfflushobject(kids)), + limits = kids.Limits, + } + else + -- error + end end slices = temp else - return pdfreference(pdfflushobject(collectkids(slices,1,#slices))) + local kids = collectkids(slices,1,#slices) + if kids then + return pdfreference(pdfflushobject(kids)) + else + -- error + return + end end end end @@ -292,8 +344,9 @@ end local function pdfdestinationspecification() if next(destinations) then -- safeguard local r = pdfnametree(destinations) - -- pdfaddtocatalog("Dests",r) - pdfaddtonames("Dests",r) + if r then + pdfaddtonames("Dests",r) + end if not log_destinations then destinations = nil end @@ -309,14 +362,25 @@ lpdf.registerdocumentfinalizer(pdfdestinationspecification,"collect destinations local destinations = { } -local f_xyz = formatters["<< /D [ %i 0 R /XYZ %0.3F %0.3F null ] >>"] +local f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6F %.6F null ] >>"] local f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"] local f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"] -local f_fith = formatters["<< /D [ %i 0 R /FitH %0.3F ] >>"] -local f_fitv = formatters["<< /D [ %i 0 R /FitV %0.3F ] >>"] -local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %0.3F ] >>"] -local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %0.3F ] >>"] -local f_fitr = formatters["<< /D [ %i 0 R /FitR %0.3F %0.3F %0.3F %0.3F ] >>"] +local f_fith = formatters["<< /D [ %i 0 R /FitH %.6F ] >>"] +local f_fitv = formatters["<< /D [ %i 0 R /FitV %.6F ] >>"] +local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6F ] >>"] +local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6F ] >>"] +local f_fitr = formatters["<< /D [ %i 0 R /FitR %.6F %.6F %.6F %.6F ] >>"] + +directives.register("pdf.stripzeros",function() + f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6N %.6N null ] >>"] + f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"] + f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"] + f_fith = formatters["<< /D [ %i 0 R /FitH %.6N ] >>"] + f_fitv = formatters["<< /D [ %i 0 R /FitV %.6N ] >>"] + f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6N ] >>"] + f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6N ] >>"] + f_fitr = formatters["<< /D [ %i 0 R /FitR %.6N %.6N %.6N %.6N ] >>"] +end) local v_standard = variables.standard local v_frame = variables.frame @@ -404,13 +468,15 @@ local pagedestinations = setmetatableindex(function(t,k) -- not the same as the return v end) -local function flushdestination(width,height,depth,names,view) - local r = pdfpagereference(texgetcount("realpageno")) +local function flushdestination(specification) + local names = specification.names + local view = specification.view + local r = pdfpagereference(texgetcount("realpageno")) if (references.innermethod ~= v_name) and (view == defaultview or not view or view == "") then r = pagedestinations[r] else local action = view and destinationactions[view] or defaultaction - r = pdfdelayedobject(action(r,width,height,depth,offset)) + r = pdfdelayedobject(action(r,specification.width,specification.height,specification.depth,offset)) end for n=1,#names do local name = names[n] @@ -459,7 +525,7 @@ function nodeinjections.destination(width,height,depth,names,view) elseif type(name) == "number" then local used = usedinternals[name] usedviews[name] = view - names[n] = autoprefix .. name + names[n] = registerautoprefix(name) doview = true else usedviews[name] = view @@ -479,10 +545,9 @@ function nodeinjections.destination(width,height,depth,names,view) local used = usedinternals[name] if used and used ~= defaultview then usedviews[name] = view - names[n] = autoprefix .. name + names[n] = registerautoprefix(name) doview = true else - -- names[n] = autoprefix .. name names[n] = false end end @@ -493,7 +558,14 @@ function nodeinjections.destination(width,height,depth,names,view) end end if doview then - return new_latelua(function() flushdestination(width,height,depth,names,view) end) + return new_latelua { + action = flushdestination, + width = width, + height = height, + depth = depth, + names = names, + view = view, + } end end @@ -504,7 +576,7 @@ local function pdflinkpage(page) end local function pdflinkinternal(internal,page) - local method = references.innermethod + -- local method = references.innermethod if internal then flaginternals[internal] = true -- for bookmarks and so local used = usedinternals[internal] @@ -512,7 +584,7 @@ local function pdflinkinternal(internal,page) return pagereferences[page] else if type(internal) ~= "string" then - internal = autoprefix .. internal + internal = useautoprefix(internal) end return pdfdictionary { S = pdf_goto, @@ -559,7 +631,7 @@ local function pdffilelink(filename,destination,page,actions) end filename = file.addsuffix(filename,"pdf") if (not destination or destination == "") or (references.outermethod == v_page) then - destination = pdfarray { (page or 0) - 1, pdf_fit } + destination = pdfarray { (page or 1) - 1, pdf_fit } end return pdfdictionary { S = pdf_gotor, -- can also be pdf_launch @@ -635,7 +707,7 @@ local function pdfaction(actions) return nil end end - return first, actions.n + return first, actions.n or #actions end end end @@ -686,9 +758,15 @@ local nofused = 0 local nofspecial = 0 local share = true -local f_annot = formatters["<< /Type /Annot %s /Rect [ %0.3F %0.3F %0.3F %0.3F ] >>"] +local f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6F %0.6F %0.6F %0.6F ] >>"] -directives.register("references.sharelinks", function(v) share = v end) +directives.register("pdf.stripzeros",function() + f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6N %0.6N %0.6N %0.6N ] >>"] +end) + +directives.register("references.sharelinks", function(v) + share = v +end) setmetatableindex(hashed,function(t,k) local v = pdfdelayedobject(k) @@ -699,24 +777,26 @@ setmetatableindex(hashed,function(t,k) return v end) -local function finishreference(width,height,depth,prerolled) -- %0.2f looks okay enough (no scaling anyway) - local annot = hashed[f_annot(prerolled,pdfrectangle(width,height,depth))] +local function finishreference(specification) -- %0.2f looks okay enough (no scaling anyway) + local annot = hashed[f_annot(specification.prerolled,pdfrectangle(specification.width,specification.height,specification.depth))] nofused = nofused + 1 return pdfregisterannotation(annot) end -local function finishannotation(width,height,depth,prerolled,r) +local function finishannotation(specification) + local prerolled = specification.prerolled + local objref = specification.objref if type(prerolled) == "function" then prerolled = prerolled() end - local annot = f_annot(prerolled,pdfrectangle(width,height,depth)) - if r then - pdfdelayedobject(annot,r) + local annot = f_annot(prerolled,pdfrectangle(specification.width,specification.height,specification.depth)) + if objref then + pdfdelayedobject(annot,objref) else - r = pdfdelayedobject(annot) + objref = pdfdelayedobject(annot) end nofspecial = nofspecial + 1 - return pdfregisterannotation(r) + return pdfregisterannotation(objref) end function nodeinjections.reference(width,height,depth,prerolled) @@ -724,17 +804,30 @@ function nodeinjections.reference(width,height,depth,prerolled) if trace_references then report_references("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled) end - return new_latelua(function() finishreference(width,height,depth,prerolled) end) + return new_latelua { + action = finishreference, + width = width, + height = height, + depth = depth, + prerolled = prerolled, + } end end -function nodeinjections.annotation(width,height,depth,prerolled,r) +function nodeinjections.annotation(width,height,depth,prerolled,objref) if prerolled then if trace_references then report_references("special: width %p, height %p, depth %p, prerolled %a",width,height,depth, type(prerolled) == "string" and prerolled or "-") end - return new_latelua(function() finishannotation(width,height,depth,prerolled,r or false) end) + return new_latelua { + action = finishannotation, + width = width, + height = height, + depth = depth, + prerolled = prerolled, + objref = objref or false, + } end end @@ -757,7 +850,9 @@ pdfregisterannotation = lpdf.registerannotation function lpdf.annotationspecification() if annotations then local r = pdfdelayedobject(tostring(annotations)) -- delayed so okay in latelua - pdfaddtopageattributes("Annots",pdfreference(r)) + if r then + pdfaddtopageattributes("Annots",pdfreference(r)) + end annotations = nil end end @@ -872,16 +967,21 @@ end runners["special operation"] = runners["special"] runners["special operation with arguments"] = runners["special"] +local reported = { } + function specials.internal(var,actions) -- better resolve in strc-ref - local i = tonumber(var.operation) + local o = var.operation + local i = o and tonumber(o) local v = i and references.internals[i] - if not v then - -- error - report_references("no internal reference %a",i or "") - else - flaginternals[i] = true + if v then + flaginternals[i] = true -- also done in pdflinkinternal return pdflinkinternal(i,v.references.realpage) end + local v = i or o or "" + if not reported[v] then + report_references("no internal reference %a",v) + reported[v] = true + end end -- realpage already resolved @@ -946,19 +1046,18 @@ end -- sections --- function specials.section(var,actions) --- local sectionname = var.operation --- local destination = var.arguments --- local internal = structures.sections.internalreference(sectionname,destination) --- if internal then --- var.special = "internal" --- var.operation = internal --- var.arguments = nil --- specials.internal(var,actions) --- end --- end - -specials.section = specials.internal -- specials.section just need to have a value as it's checked +function specials.section(var,actions) + -- a bit duplicate + local sectionname = var.arguments + local destination = var.operation + local internal = structures.sections.internalreference(sectionname,destination) + if internal then + var.special = "internal" + var.operation = internal + var.arguments = nil + return specials.internal(var,actions) + end +end -- todo, do this in references namespace ordered instead (this is an experiment) @@ -1129,7 +1228,8 @@ end local function build(levels,start,parent,method,nested) local startlevel = levels[start].level local noflevels = #levels - local i, n = start, 0 + local i = start + local n = 0 local child, entry, m, prev, first, last, f, l while i and i <= noflevels do local current = levels[i] @@ -1146,11 +1246,12 @@ local function build(levels,start,parent,method,nested) local variant = "unknown" if reftype == "table" then -- we're okay - variant = "list" - block = reference.block + variant = "list" + block = reference.block + realpage = reference.realpage elseif reftype == "string" then local resolved = references.identify("",reference) - local realpage = resolved and structures.references.setreferencerealpage(resolved) or 0 + realpage = resolved and structures.references.setreferencerealpage(resolved) or 0 if realpage > 0 then variant = "realpage" realpage = realpage @@ -1251,7 +1352,6 @@ end function codeinjections.addbookmarks(levels,method) if levels and #levels > 0 then --- inspect(levels) local parent = pdfreserveobject() local _, m, first, last = build(levels,1,pdfreference(parent),method or "internal",false) local dict = pdfdictionary { diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-aux.lua new file mode 100644 index 00000000000..0d7cecbb853 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-aux.lua @@ -0,0 +1,152 @@ +if not modules then modules = { } end modules ['lpdf-aux'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local tonumber = tonumber +local format, concat = string.format, table.concat +local utfchar, utfbyte, char = utf.char, utf.byte, string.char +local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local P, C, R, S, Cc, Cs, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs, lpeg.V +local rshift = bit32.rshift + +lpdf = lpdf or { } + +-- tosixteen -- + +local cache = table.setmetatableindex(function(t,k) -- can be made weak + local v = utfbyte(k) + if v < 0x10000 then + v = format("%04x",v) + else + v = format("%04x%04x",rshift(v,10),v%1024+0xDC00) + end + t[k] = v + return v +end) + +local unified = Cs(Cc("")) + +function lpdf.tosixteen(str) -- an lpeg might be faster (no table) + if not str or str == "" then + return "" -- not () as we want an indication that it's unicode + else + return lpegmatch(unified,str) + end +end + +-- fromsixteen -- + +-- local zero = S(" \n\r\t") + P("\\ ") +-- local one = C(4) +-- local two = P("d") * R("89","af") * C(2) * C(4) +-- +-- local pattern = P { "start", +-- start = V("wrapped") + V("unwrapped") + V("original"), +-- original = Cs(P(1)^0), +-- wrapped = P("<") * V("unwrapped") * P(">") * P(-1), +-- unwrapped = P("feff") +-- * Cs( ( +-- zero / "" +-- + two / function(a,b) +-- a = (tonumber(a,16) - 0xD800) * 1024 +-- b = (tonumber(b,16) - 0xDC00) +-- return utfchar(a+b) +-- end +-- + one / function(a) +-- return utfchar(tonumber(a,16)) +-- end +-- )^1 ) * P(-1) +-- } +-- +-- function lpdf.fromsixteen(s) +-- return lpegmatch(pattern,s) or s +-- end + +local more = 0 + +local pattern = C(4) / function(s) -- needs checking ! + local now = tonumber(s,16) + if more > 0 then + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + more = 0 + return utfchar(now) + elseif now >= 0xD800 and now <= 0xDBFF then + more = now + return "" -- else the c's end up in the stream + else + return utfchar(now) + end +end + +local pattern = P(true) / function() more = 0 end * Cs(pattern^0) + +function lpdf.fromsixteen(str) + if not str or str == "" then + return "" + else + return lpegmatch(pattern,str) + end +end + +-- frombytes -- + +local b_pattern = Cs((P("\\")/"" * ( + S("()") + + S("nrtbf")/ { n = "\n", r = "\r", t = "\t", b = "\b", f = "\f" } + + lpegpatterns.octdigit^-3 / function(s) return char(tonumber(s,8)) end) ++ P(1))^0) + +local u_pattern = lpegpatterns.utfbom_16_be * lpegpatterns.utf16_to_utf8_be -- official + + lpegpatterns.utfbom_16_le * lpegpatterns.utf16_to_utf8_le -- we've seen these + +local h_pattern = lpegpatterns.hextobytes + +local zero = S(" \n\r\t") + P("\\ ") +local one = C(4) +local two = P("d") * R("89","af") * C(2) * C(4) + +local x_pattern = P { "start", + start = V("wrapped") + V("unwrapped") + V("original"), + original = Cs(P(1)^0), + wrapped = P("<") * V("unwrapped") * P(">") * P(-1), + unwrapped = P("feff") + * Cs( ( + zero / "" + + two / function(a,b) + a = (tonumber(a,16) - 0xD800) * 1024 + b = (tonumber(b,16) - 0xDC00) + return utfchar(a+b) + end + + one / function(a) + return utfchar(tonumber(a,16)) + end + )^1 ) * P(-1) +} + +function lpdf.frombytes(s,hex) + if not s or s == "" then + return "" + end + if hex then + local x = lpegmatch(x_pattern,s) + if x then + return x + end + local h = lpegmatch(h_pattern,s) + if h then + return h + end + else + local u = lpegmatch(u_pattern,s) + if u then + return u + end + end + return lpegmatch(b_pattern,s) +end + +-- done -- diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua index d1a1af97dcf..b697dc4816a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-col.lua @@ -23,7 +23,7 @@ local registrations = backends.pdf.registrations local nodepool = nodes.nuts.pool local register = nodepool.register -local pdfpageliteral = nodepool.pdfpageliteral +local pageliteral = nodepool.pageliteral local pdfconstant = lpdf.constant local pdfdictionary = lpdf.dictionary @@ -64,13 +64,20 @@ local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"] local f_spot = formatters["/%s cs /%s CS %s SCN %s scn"] local f_tr = formatters["Tr%s"] local f_cm = formatters["q %.6F %.6F %.6F %.6F %.6F %.6F cm"] -local f_effect = formatters["%s Tc %s w %s Tr"] +local f_effect = formatters["%s Tc %s w %s Tr"] -- %.3F ? local f_tr_gs = formatters["/Tr%s gs"] local f_num_1 = tostring local f_num_2 = formatters["%s %s"] local f_num_3 = formatters["%s %s %s"] local f_num_4 = formatters["%s %s %s %s"] +directives.register("pdf.stripzeros",function() + f_gray = formatters["%.3N g %.3N G"] + f_rgb = formatters["%.3N %.3N %.3N rg %.3N %.3N %.3N RG"] + f_cmyk = formatters["%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K"] + f_cm = formatters["q %.6N %.6N %.6N %.6N %.6N %.6N cm"] +end) + local report_color = logs.reporter("colors","backend") -- page groups (might move to lpdf-ini.lua) @@ -122,26 +129,26 @@ lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup") -- color injection function nodeinjections.rgbcolor(r,g,b) - return register(pdfpageliteral(f_rgb(r,g,b,r,g,b))) + return register(pageliteral(f_rgb(r,g,b,r,g,b))) end function nodeinjections.cmykcolor(c,m,y,k) - return register(pdfpageliteral(f_cmyk(c,m,y,k,c,m,y,k))) + return register(pageliteral(f_cmyk(c,m,y,k,c,m,y,k))) end function nodeinjections.graycolor(s) -- caching 0/1 does not pay off - return register(pdfpageliteral(f_gray(s,s))) + return register(pageliteral(f_gray(s,s))) end function nodeinjections.spotcolor(n,f,d,p) if type(p) == "string" then p = gsub(p,","," ") -- brr misuse of spot end - return register(pdfpageliteral(f_spot(n,n,p,p))) + return register(pageliteral(f_spot(n,n,p,p))) end function nodeinjections.transparency(n) - return register(pdfpageliteral(f_tr_gs(n))) + return register(pageliteral(f_tr_gs(n))) end -- a bit weird but let's keep it here for a while @@ -160,7 +167,7 @@ function nodeinjections.effect(effect,stretch,rulethickness) -- always, no zero test (removed) rulethickness = bp * rulethickness effect = effects[effect] or effects['normal'] - return register(pdfpageliteral(f_effect(stretch,rulethickness,effect))) -- watch order + return register(pageliteral(f_effect(stretch,rulethickness,effect))) -- watch order end -- spot- and indexcolors @@ -335,7 +342,9 @@ local function registersomeindexcolor(name,noffractions,names,p,colorspace,range colorspace, pdfreference(n), } - local vector, set, n = { }, { }, #values + local vector = { } + local set = { } + local n = #values for i=255,0,-1 do for j=1,n do set[j] = format("%02X",round(values[j]*i)) @@ -512,13 +521,21 @@ local function lpdfcolor(model,ca,default) -- todo: use gray when no color local s = cv[2] return f_gray(s,s) elseif model == 3 then - local r, g, b = cv[3], cv[4], cv[5] + local r = cv[3] + local g = cv[4] + local b = cv[5] return f_rgb(r,g,b,r,g,b) elseif model == 4 then - local c, m, y, k = cv[6],cv[7],cv[8],cv[9] + local c = cv[6] + local m = cv[7] + local y = cv[8] + local k = cv[9] return f_cmyk(c,m,y,k,c,m,y,k) else - local n,f,d,p = cv[10],cv[11],cv[12],cv[13] + local n = cv[10] + local f = cv[11] + local d = cv[12] + local p = cv[13] if type(p) == "string" then p = gsub(p,","," ") -- brr misuse of spot end @@ -617,7 +634,7 @@ function lpdf.colorvalues(model,ca,default) return cv[3], cv[4], cv[5] elseif model == 4 then return cv[6], cv[7], cv[8], cv[9] - elseif model == 4 then + elseif model == 5 then return cv[13] end else @@ -717,6 +734,10 @@ do local f_slant = formatters["q 1 0 %.6F 1 0 0 cm"] + directives.register("pdf.stripzeros",function() + f_slant = formatters["q 1 0 %.6N 1 0 0 cm"] + end) + -- local fillcolors = { -- red = { "pdf", "origin", "1 0 0 rg" }, -- green = { "pdf", "origin", "0 1 0 rg" }, diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua index 89b2c6e0e59..570d738817f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epa.lua @@ -6,49 +6,79 @@ if not modules then modules = { } end modules ['lpdf-epa'] = { license = "see context related readme files" } --- This is a rather experimental feature and the code will probably change. +-- Links can also have quadpoint -local type, tonumber = type, tonumber -local format, gsub, lower = string.format, string.gsub, string.lower +-- embedded files ... not bound to a page + +local type, tonumber, next = type, tonumber, next +local format, gsub, lower, find = string.format, string.gsub, string.lower, string.find local formatters = string.formatters +local concat, merged = table.concat, table.merged local abs = math.abs local expandname = file.expandname local allocate = utilities.storage.allocate +local bor, band = bit32.bor, bit32.band local isfile = lfs.isfile ------ lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local trace_links = false trackers.register("figures.links", function(v) trace_links = v end) +local trace_comments = false trackers.register("figures.comments", function(v) trace_comments = v end) +local trace_fields = false trackers.register("figures.fields", function(v) trace_fields = v end) +local trace_outlines = false trackers.register("figures.outlines", function(v) trace_outlines = v end) + +local report_link = logs.reporter("backend","link") +local report_comment = logs.reporter("backend","comment") +local report_field = logs.reporter("backend","field") +local report_outline = logs.reporter("backend","outline") + +local lpdf = lpdf +local epdf = epdf +local backends = backends +local context = context + +local nodeinjections = backends.pdf.nodeinjections + +local pdfarray = lpdf.array +local pdfdictionary = lpdf.dictionary +local pdfconstant = lpdf.constant +local pdfreserveobject = lpdf.reserveobject +local pdfreference = lpdf.reference -local trace_links = false trackers.register("figures.links", function(v) trace_links = v end) -local trace_outlines = false trackers.register("figures.outliness", function(v) trace_outlines = v end) +local pdfcopyboolean = lpdf.copyboolean +local pdfcopyunicode = lpdf.copyunicode +local pdfcopyarray = lpdf.copyarray +local pdfcopydictionary = lpdf.copydictionary +local pdfcopynumber = lpdf.copynumber +local pdfcopyinteger = lpdf.copyinteger +local pdfcopystring = lpdf.copystring +local pdfcopyconstant = lpdf.copyconstant -local report_link = logs.reporter("backend","link") -local report_comment = logs.reporter("backend","comment") -local report_field = logs.reporter("backend","field") -local report_outline = logs.reporter("backend","outline") +local createimage = images.create +local embedimage = images.embed -local epdf = epdf -local backends = backends -local lpdf = lpdf -local context = context +local hpack_node = nodes.hpack -local loadpdffile = lpdf.epdf.load +local loadpdffile = lpdf.epdf.load -local nameonly = file.nameonly +local nameonly = file.nameonly -local variables = interfaces.variables -local codeinjections = backends.pdf.codeinjections ------ urlescaper = lpegpatterns.urlescaper ------ utftohigh = lpegpatterns.utftohigh -local escapetex = characters.filters.utf.private.escape +local variables = interfaces.variables +local codeinjections = backends.pdf.codeinjections +----- urlescaper = lpegpatterns.urlescaper +----- utftohigh = lpegpatterns.utftohigh +local escapetex = characters.filters.utf.private.escape -local bookmarks = structures.bookmarks +local bookmarks = structures.bookmarks -local maxdimen = 0x3FFFFFFF -- 2^30-1 +local maxdimen = 0x3FFFFFFF -- 2^30-1 + +local bpfactor = number.dimenfactors.bp local layerspec = { -- predefining saves time - "epdflinks" + "epdfcontent" } +local getpos = function() getpos = backends.codeinjections.getpos return getpos () end + local collected = allocate() local tobesaved = allocate() @@ -66,6 +96,68 @@ end job.register('job.embedded.collected',tobesaved,initializer) +local function validdocument(specification) + if figures and not specification then + specification = figures and figures.current() + specification = specification and specification.status + end + if specification then + local fullname = specification.fullname + local expanded = lower(expandname(fullname)) + -- we could add a check for duplicate page insertion + tobesaved[expanded] = true + --- but that is messy anyway so we forget about it + return specification, fullname, loadpdffile(fullname) -- costs time + end +end + +local function getmediasize(specification,pagedata) + local xscale = specification.xscale or 1 + local yscale = specification.yscale or 1 + ----- size = specification.size or "crop" -- todo + local mediabox = pagedata.MediaBox + local llx = mediabox[1] + local lly = mediabox[2] + local urx = mediabox[3] + local ury = mediabox[4] + local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight + local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight + return llx, lly, urx, ury, width, height, xscale, yscale +end + +local function getdimensions(annotation,llx,lly,xscale,yscale,width,height,report) + local rectangle = annotation.Rect + local a_llx = rectangle[1] + local a_lly = rectangle[2] + local a_urx = rectangle[3] + local a_ury = rectangle[4] + local x = xscale * (a_llx - llx) + local y = yscale * (a_lly - lly) + local w = xscale * (a_urx - a_llx) + local h = yscale * (a_ury - a_lly) + if w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then + report("broken rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2) + return + end + return x, y, w, h, a_llx, a_lly, a_urx, a_ury +end + +local layerused = false + +local function initializelayer(height,width) + if not layerused then + context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" }) + layerused = true + end +end + +function codeinjections.flushmergelayer() + if layerused then + context.flushlayer(layerspec) + layerused = false + end +end + local f_namespace = formatters["lpdf-epa-%s-"] local function makenamespace(filename) @@ -182,82 +274,51 @@ local function link_file(x,y,w,h,document,annotation) end end +-- maybe handler per subtype and then one loop but then what about order ... + function codeinjections.mergereferences(specification) - if figures and not specification then - specification = figures and figures.current() - specification = specification and specification.status - end - if not specification then - return "" - end - local fullname = specification.fullname - local expanded = lower(expandname(fullname)) - -- we could add a check for duplicate page insertion - tobesaved[expanded] = true - --- but that is messy anyway so we forget about it - local document = loadpdffile(fullname) -- costs time + local specification, fullname, document = validdocument(specification) if not document then return "" end - local pagenumber = specification.page or 1 - local xscale = specification.yscale or 1 - local yscale = specification.yscale or 1 - local size = specification.size or "crop" -- todo + local pagenumber = specification.page or 1 local pagedata = document.pages[pagenumber] local annotations = pagedata and pagedata.Annots local namespace = makenamespace(fullname) local reference = namespace .. pagenumber - if annotations and annotations.n > 0 then - local mediabox = pagedata.MediaBox - local llx = mediabox[1] - local lly = mediabox[2] - local urx = mediabox[3] - local ury = mediabox[4] - local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight - local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight - context.definelayer( { "epdflinks" }, { height = height.."bp" , width = width.."bp" }) - for i=1,annotations.n do + if annotations and #annotations > 0 then + local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + initializelayer(height,width) + for i=1,#annotations do local annotation = annotations[i] if annotation then - local subtype = annotation.Subtype - local rectangle = annotation.Rect - local a_llx = rectangle[1] - local a_lly = rectangle[2] - local a_urx = rectangle[3] - local a_ury = rectangle[4] - local x = xscale * (a_llx - llx) - local y = yscale * (a_lly - lly) - local w = xscale * (a_urx - a_llx) - local h = yscale * (a_ury - a_lly) - if subtype == "Link" then + if annotation.Subtype == "Link" then local a = annotation.A if not a then report_link("missing link annotation") - elseif w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then - report_link("broken link rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2) else - local linktype = a.S - if linktype == "GoTo" then - link_goto(x,y,w,h,document,annotation,pagedata,namespace) - elseif linktype == "GoToR" then - link_file(x,y,w,h,document,annotation) - elseif linktype == "URI" then - link_uri(x,y,w,h,document,annotation) - elseif trace_links then - report_link("unsupported link annotation %a",linktype) + local x, y, w, h = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_link) + if x then + local linktype = a.S + if linktype == "GoTo" then + link_goto(x,y,w,h,document,annotation,pagedata,namespace) + elseif linktype == "GoToR" then + link_file(x,y,w,h,document,annotation) + elseif linktype == "URI" then + link_uri(x,y,w,h,document,annotation) + elseif trace_links then + report_link("unsupported link annotation %a",linktype) + end end end - elseif trace_links then - report_link("unsupported annotation %a",subtype) end elseif trace_links then report_link("broken annotation, index %a",i) end end - context.flushlayer { "epdflinks" } end -- moved outside previous test - context.setgvalue("figurereference",reference) -- global + context.setgvalue("figurereference",reference) -- global, todo: setmacro if trace_links then report_link("setting figure reference to %a",reference) end @@ -270,43 +331,527 @@ function codeinjections.mergeviewerlayers(specification) if true then return end - if not specification then - specification = figures and figures.current() - specification = specification and specification.status + local specification, fullname, document = validdocument(specification) + if not document then + return "" end - if specification then - local fullname = specification.fullname - local document = loadpdffile(fullname) - if document then - local namespace = makenamespace(fullname) - local layers = document.layers - if layers then - for i=1,layers.n do - local layer = layers[i] - if layer then - local tag = namespace .. gsub(layer," ",":") - local title = tag - if trace_links then - report_link("using layer %a",tag) + local namespace = makenamespace(fullname) + local layers = document.layers + if layers then + for i=1,#layers do + local layer = layers[i] + if layer then + local tag = namespace .. gsub(layer," ",":") + local title = tag + if trace_links then + report_link("using layer %a",tag) + end + attributes.viewerlayers.define { -- also does some cleaning + tag = tag, -- todo: #3A or so + title = title, + visible = variables.start, + editable = variables.yes, + printable = variables.yes, + } + codeinjections.useviewerlayer(tag) + elseif trace_links then + report_link("broken layer, index %a",i) + end + end + end +end + +-- It took a bit of puzzling and playing around to come to the following +-- implementation. In the end it looks simple but as usual it takes a while +-- to see what the specification (and implementation) boils down to. Lots of +-- shared properties and such. The scaling took some trial and error as +-- viewers differ. I had to extend some low level helpers to make it more +-- comfortable. Hm, the specification is somewhat incomplete as some fields +-- are permitted even if not mentioned so in the end we can share more code. +-- +-- If all works ok, we can get rid of some copies which saves time and space. + +local commentlike = { + Text = "text", + FreeText = "freetext", + Line = "line", + Square = "shape", + Circle = "shape", + Polygon = "poly", + PolyLine = "poly", + Highlight = "markup", + Underline = "markup", + Squiggly = "markup", + StrikeOut = "markup", + Caret = "text", + Stamp = "stamp", + Ink = "ink", + Popup = "popup", +} + +local function copyBS(v) -- dict can be shared + if v then + -- return pdfdictionary { + -- Type = copypdfconstant(V.Type), + -- W = copypdfnumber (V.W), + -- S = copypdfstring (V.S), + -- D = copypdfarray (V.D), + -- } + return copypdfdictionary(v) + end +end + +local function copyBE(v) -- dict can be shared + if v then + -- return pdfdictionary { + -- S = copypdfstring(V.S), + -- I = copypdfnumber(V.I), + -- } + return copypdfdictionary(v) + end +end + +local function copyBorder(v) -- dict can be shared + if v then + -- todo + return copypdfarray(v) + end +end + +local function copyPopup(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyParent(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyIRT(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyC(v) + if v then + -- todo: check color space + return pdfcopyarray(v) + end +end + +local function finalizer(d,xscale,yscale,a_llx,a_ury) + local q = d.QuadPoints or d.Vertices or d.CL + if q then + return function() + local h, v = pdfgetpos() -- already scaled + for i=1,#q,2 do + q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx) + q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury) + end + return d() + end + end + q = d.InkList or d.Path + if q then + return function() + local h, v = pdfgetpos() -- already scaled + for i=1,#q do + local q = q[i] + for i=1,#q,2 do + q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx) + q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury) + end + end + return d() + end + end + return d() +end + +local validstamps = { + Approved = true, + Experimental = true, + NotApproved = true, + AsIs = true, + Expired = true, + NotForPublicRelease = true, + Confidential = true, + Final = true, + Sold = true, + Departmental = true, + ForComment = true, + TopSecret = true, + Draft = true, + ForPublicRelease = true, +} + +-- todo: we can use runtoks instead of steps + +local function validStamp(v) + local name = "Stamped" -- fallback + if v then + local ok = validstamps[v] + if ok then + name = ok + else + for k in next, validstamps do + if find(v,k.."$") then + name = k + validstamps[v] = k + break + end + end + end + end + -- we temporary return to \TEX: + context.predefinesymbol { name } + context.step() + -- beware, an error is not reported + return pdfconstant(name), codeinjections.analyzenormalsymbol(name) +end + +local annotationflags = lpdf.flags.annotations + +local function copyF(v,lock) -- todo: bxor 24 + if lock then + v = bor(v or 0,annotationflags.ReadOnly + annotationflags.Locked + annotationflags.LockedContents) + end + if v then + return pdfcopyinteger(v) + end +end + +-- Speed is not really an issue so we don't optimize this code too much. In the end (after +-- testing we end up with less code that we started with. + +function codeinjections.mergecomments(specification) + local specification, fullname, document = validdocument(specification) + if not document then + return "" + end + local pagenumber = specification.page or 1 + local pagedata = document.pages[pagenumber] + local annotations = pagedata and pagedata.Annots + if annotations and #annotations > 0 then + local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + initializelayer(height,width) + -- + local lockflags = specification.lock -- todo: proper parameter + local references = { } + local usedpopups = { } + for i=1,#annotations do + local annotation = annotations[i] + if annotation then + local subtype = annotation.Subtype + if commentlike[subtype] then + references[annotation] = pdfreserveobject() + local p = annotation.Popup + if p then + usedpopups[p] = true + end + end + end + end + -- + for i=1,#annotations do + -- we keep the order + local annotation = annotations[i] + if annotation then + local reference = references[annotation] + if reference then + local subtype = annotation.Subtype + local kind = commentlike[subtype] + if kind ~= "popup" or usedpopups[annotation] then + local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_comment) + if x then + local voffset = h + local dictionary = pdfdictionary { + Subtype = pdfconstant (subtype), + -- common (skipped: P AP AS OC AF BM StructParent) + Contents = pdfcopyunicode(annotation.Contents), + NM = pdfcopystring (annotation.NM), + M = pdfcopystring (annotation.M), + F = copyF (annotation.F,lockflags), + C = copyC (annotation.C), + ca = pdfcopynumber (annotation.ca), + CA = pdfcopynumber (annotation.CA), + Lang = pdfcopystring (annotation.Lang), + -- also common + CreationDate = pdfcopystring (annotation.CreationDate), + T = pdfcopyunicode(annotation.T), + Subj = pdfcopyunicode(annotation.Subj), + -- border + Border = pdfcopyarray (annotation.Border), + BS = copyBS (annotation.BS), + BE = copyBE (annotation.BE), + -- sort of common + Popup = copyPopup (annotation.Popup,references), + RC = pdfcopyunicode(annotation.RC) -- string or stream + } + if kind == "markup" then + dictionary.IRT = copyIRT (annotation.IRT,references) + dictionary.RT = pdfconstant (annotation.RT) + dictionary.IT = pdfcopyconstant (annotation.IT) + dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints) + -- dictionary.RD = pdfcopyarray (annotation.RD) + elseif kind == "text" then + -- somehow F fails to view : /F 24 : bit4=nozoom bit5=norotate + dictionary.F = nil + dictionary.Open = pdfcopyboolean (annotation.Open) + dictionary.Name = pdfcopyunicode (annotation.Name) + dictionary.State = pdfcopystring (annotation.State) + dictionary.StateModel = pdfcopystring (annotation.StateModel) + dictionary.IT = pdfcopyconstant (annotation.IT) + dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints) + dictionary.RD = pdfcopyarray (annotation.RD) -- caret + dictionary.Sy = pdfcopyconstant (annotation.Sy) -- caret + voffset = 0 + elseif kind == "freetext" then + dictionary.DA = pdfcopystring (annotation.DA) + dictionary.Q = pdfcopyinteger (annotation.Q) + dictionary.DS = pdfcopystring (annotation.DS) + dictionary.CL = pdfcopyarray (annotation.CL) + dictionary.IT = pdfcopyconstant (annotation.IT) + dictionary.LE = pdfcopyconstant (annotation.LE) + -- dictionary.RC = pdfcopystring (annotation.RC) + elseif kind == "line" then + dictionary.LE = pdfcopyarray (annotation.LE) + dictionary.IC = pdfcopyarray (annotation.IC) + dictionary.LL = pdfcopynumber (annotation.LL) + dictionary.LLE = pdfcopynumber (annotation.LLE) + dictionary.Cap = pdfcopyboolean (annotation.Cap) + dictionary.IT = pdfcopyconstant (annotation.IT) + dictionary.LLO = pdfcopynumber (annotation.LLO) + dictionary.CP = pdfcopyconstant (annotation.CP) + dictionary.Measure = pdfcopydictionary(annotation.Measure) -- names + dictionary.CO = pdfcopyarray (annotation.CO) + voffset = 0 + elseif kind == "shape" then + dictionary.IC = pdfcopyarray (annotation.IC) + -- dictionary.RD = pdfcopyarray (annotation.RD) + voffset = 0 + elseif kind == "stamp" then + local name, appearance = validStamp(annotation.Name) + dictionary.Name = name + dictionary.AP = appearance + voffset = 0 + elseif kind == "ink" then + dictionary.InkList = pdfcopyarray (annotation.InkList) + elseif kind == "poly" then + dictionary.Vertices = pdfcopyarray (annotation.Vertices) + -- dictionary.LE = pdfcopyarray (annotation.LE) -- todo: names in array + dictionary.IC = pdfcopyarray (annotation.IC) + dictionary.IT = pdfcopyconstant (annotation.IT) + dictionary.Measure = pdfcopydictionary(annotation.Measure) + dictionary.Path = pdfcopyarray (annotation.Path) + -- dictionary.RD = pdfcopyarray (annotation.RD) + elseif kind == "popup" then + dictionary.Open = pdfcopyboolean (annotation.Open) + dictionary.Parent = copyParent (annotation.Parent,references) + voffset = 0 + end + if dictionary then + local locationspec = { + x = x .. "bp", + y = y .. "bp", + voffset = voffset .. "bp", + preset = "leftbottom", + } + local finalize = finalizer(dictionary,xscale,yscale,a_llx,a_ury) + context.setlayer(layerspec,locationspec,function() + context(hpack_node(nodeinjections.annotation(w/bpfactor,h/bpfactor,0,finalize,reference))) + end) + end end - attributes.viewerlayers.define { -- also does some cleaning - tag = tag, -- todo: #3A or so - title = title, - visible = variables.start, - editable = variables.yes, - printable = variables.yes, - } - codeinjections.useviewerlayer(tag) - elseif trace_links then - report_link("broken layer, index %a",i) + else + -- report_comment("skipping annotation, index %a",i) end end + elseif trace_comments then + report_comment("broken annotation, index %a",i) end end end + return namespace end --- new: for taco +local widgetflags = lpdf.flags.widgets + +local function flagstoset(flag,flags) + local t = { } + if flags then + for k, v in next, flags do + if band(flag,v) ~= 0 then + t[k] = true + end + end + end + return t +end + +-- BS : border style dict +-- R : rotation 0 90 180 270 +-- BG : background array +-- CA : caption string +-- RC : roll over caption +-- AC : down caption +-- I/RI/IX : icon streams +-- IF : fit dictionary +-- TP : text position number + +-- Opt : array of texts +-- TI : top index + +-- V : value +-- DV : default value +-- DS : default string +-- RV : rich +-- Q : quadding (0=left 1=middle 2=right) + +function codeinjections.mergefields(specification) + local specification, fullname, document = validdocument(specification) + if not document then + return "" + end + local pagenumber = specification.page or 1 + local pagedata = document.pages[pagenumber] + local annotations = pagedata and pagedata.Annots + if annotations and #annotations > 0 then + local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + initializelayer(height,width) + -- + for i=1,#annotations do + -- we keep the order + local annotation = annotations[i] + if annotation then + local subtype = annotation.Subtype + if subtype == "Widget" then + local parent = annotation.Parent or { } + local name = annotation.T or parent.T + local what = annotation.FT or parent.FT + if name and what then + local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_field) + if x then + x = x .. "bp" + y = y .. "bp" + local W, H = w, h + w = w .. "bp" + h = h .. "bp" + if trace_fields then + report_field("field %a, type %a, dx %s, dy %s, wd %s, ht %s",name,what,x,y,w,h) + end + local locationspec = { + x = x, + y = y, + preset = "leftbottom", + } + -- + local aflags = flagstoset(annotation.F or parent.F, annotationflags) + local wflags = flagstoset(annotation.Ff or parent.Ff, widgetflags) + if what == "Tx" then + -- DA DV F FT MaxLen MK Q T V | AA OC + if wflags.MultiLine then + wflags.MultiLine = nil + what = "text" + else + what = "line" + end + -- via context + local fieldspec = { + width = w, + height = h, + offset = variables.overlay, + frame = trace_links and variables.on or variables.off, + n = annotation.MaxLen or (parent and parent.MaxLen), + type = what, + option = concat(merged(aflags,wflags),","), + } + context.setlayer (layerspec,locationspec,function() + context.definefieldbody ( { name } , fieldspec ) + context.fieldbody ( { name } ) + end) + -- + elseif what == "Btn" then + if wflags.Radio or wflags.RadiosInUnison then + -- AP AS DA F Ff FT H MK T V | AA OC + wflags.Radio = nil + wflags.RadiosInUnison = nil + what = "radio" + elseif wflags.PushButton then + -- AP DA F Ff FT H MK T | AA OC + -- + -- Push buttons only have an appearance and some associated + -- actions so they are not worth copying. + -- + wflags.PushButton = nil + what = "push" + else + -- AP AS DA F Ff FT H MK T V | OC AA + what = "check" + -- direct + local AP = annotation.AP or (parent and parent.AP) + if AP then + local a = document.__xrefs__[AP] + if a and pdfe.copyappearance then + local o = pdfe.copyappearance(document,a) + if o then + AP = pdfreference(o) + end + end + end + local dictionary = pdfdictionary { + Subtype = pdfconstant("Widget"), + FT = pdfconstant("Btn"), + T = pdfcopyunicode(annotation.T or parent.T), + F = pdfcopyinteger(annotation.F or parent.F), + Ff = pdfcopyinteger(annotation.Ff or parent.Ff), + AS = pdfcopyconstant(annotation.AS or (parent and parent.AS)), + AP = AP and pdfreference(AP), + } + local finalize = dictionary() + context.setlayer(layerspec,locationspec,function() + context(hpack_node(nodeinjections.annotation(W/bpfactor,H/bpfactor,0,finalize))) + end) + -- + end + elseif what == "Ch" then + -- F Ff FT Opt T | AA OC (rest follows) + if wflags.PopUp then + wflags.PopUp = nil + if wflags.Edit then + wflags.Edit = nil + what = "combo" + else + what = "popup" + end + else + what = "choice" + end + elseif what == "Sig" then + what = "signature" + else + what = nil + end + end + end + end + end + end + end +end -- Beware, bookmarks can be in pdfdoc encoding or in unicode. However, in mkiv we -- write out the strings in unicode (hex). When we read them in, we check for a bom @@ -337,7 +882,7 @@ function codeinjections.getbookmarks(filename) local outlines = document.Catalog.Outlines local pages = document.pages - local nofpages = pages.n -- we need to access once in order to initialize + local nofpages = document.nofpages local destinations = document.destinations -- I need to check this destination analyzer with the one in annotations .. best share @@ -359,7 +904,7 @@ function codeinjections.getbookmarks(filename) entry.realpage = pagedata.number end elseif kind == "table" then - local pageref = destination.n + local pageref = #destination if pageref then local pagedata = pages[pageref] if pagedata then @@ -367,8 +912,8 @@ function codeinjections.getbookmarks(filename) end end end - else - -- maybe + -- elseif subtype then + -- report("unsupported bookmark action %a",subtype) end else local destination = current.Dest @@ -383,6 +928,8 @@ function codeinjections.getbookmarks(filename) local pagedata = destination and destination[1] if pagedata and pagedata.Type == "Page" then entry.realpage = pagedata.number + -- else + -- report("unsupported bookmark destination (no page)") end end end @@ -471,16 +1018,6 @@ function codeinjections.mergebookmarks(specification) end end --- placeholders: - -function codeinjections.mergecomments(specification) - report_comment("unfinished experimental code, not used yet") -end - -function codeinjections.mergefields(specification) - report_field("unfinished experimental code, not used yet") -end - -- A bit more than a placeholder but in the same perspective as -- inclusion of comments and fields: -- @@ -501,7 +1038,7 @@ function codeinjections.getinfo(specification) local catalog = pdffile.Catalog local info = pdffile.Info local pages = pdffile.pages - local nofpages = pages.n + local nofpages = pdffile.nofpages if metadata then local m = catalog.Metadata if m then @@ -525,10 +1062,8 @@ function codeinjections.getinfo(specification) local media = nobox local page = pages[pagenumber] if page then - crop = page.CropBox or nobox - media = page.MediaBox or crop or nobox - crop.n = nil -- nicer - media.n = nil -- nicer + crop = page.CropBox or nobox + media = page.MediaBox or crop or nobox end local bbox = crop or media or nobox return { diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua index cf02b5a227d..86aa6f29445 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-epd.lua @@ -32,7 +32,7 @@ if not modules then modules = { } end modules ['lpdf-epd'] = { -- already was unicode). local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next -local tostring, tonumber = tostring, tonumber +local tostring, tonumber, unpack = tostring, tonumber, unpack local lower, match, char, byte, find = string.lower, string.match, string.char, string.byte, string.find local abs = math.abs local concat = table.concat @@ -67,13 +67,27 @@ local xref = registry["epdf.XRef"] local catalog = registry["epdf.Catalog"] local pdfdoc = registry["epdf.PDFDoc"] +if not (object and dictionary and array and xref and catalog and pdfdoc) then + logs.report("fatal error","invalid pdf inclusion library (%s)",1) + os.exit() +end + local openPDF = epdf.open +local getMajorVersion = pdfdoc.getPDFMajorVersion +local getMinorVersion = pdfdoc.getPDFMinorVersion +local getXRef = pdfdoc.getXRef +local getRawCatalog = pdfdoc.getCatalog + +if not (openPDF and getMajorVersion and getMinorVersion and getXRef and getRawCatalog) then + logs.report("fatal error","invalid pdf inclusion library (%s)",2) + os.exit() +end + local getDict = object.getDict local getArray = object.getArray local getReal = object.getReal local getInt = object.getInt -local getNum = object.getNum local getString = object.getString local getBool = object.getBool local getName = object.getName @@ -81,59 +95,81 @@ local getRef = object.getRef local getRefNum = object.getRefNum local getType = object.getType -local getTypeName = object.getTypeName + +if not (getDict and getArray and getReal and getInt and getString and getBool and getName and getRef and getRefNum and getType) then + logs.report("fatal error","invalid pdf inclusion library (%s)",3) + os.exit() +end local streamReset = object.streamReset local streamGetDict = object.streamGetDict local streamGetChar = object.streamGetChar +local streamGetAll = object.streamGetAll + +if not (streamReset and streamGetDict and streamGetChar) then + logs.report("fatal error","invalid pdf inclusion library (%s)",3) + os.exit() +end local dictGetLength = dictionary.getLength local dictGetVal = dictionary.getVal local dictGetValNF = dictionary.getValNF local dictGetKey = dictionary.getKey +if not (dictGetLength and dictGetVal and dictGetValNF and dictGetKey) then + logs.report("fatal error","invalid pdf inclusion library (%s)",4) + os.exit() +end + local arrayGetLength = array.getLength local arrayGetNF = array.getNF local arrayGet = array.get +if not (arrayGetLength and arrayGetNF and arrayGet) then + logs.report("fatal error","invalid pdf inclusion library (%s)",5) + os.exit() +end + -- these are kind of weird as they can't be accessed by (root) object local getNumPages = catalog.getNumPages local getPageRef = catalog.getPageRef -local getXRef = pdfdoc.getXRef -local getRawCatalog = pdfdoc.getCatalog - local fetch = xref.fetch local getCatalog = xref.getCatalog local getDocInfo = xref.getDocInfo +if not (getNumPages and getPageRef and fetch and getCatalog and getDocInfo) then + logs.report("fatal error","invalid pdf inclusion library (%s)",6) + os.exit() +end + -- we're done with library shortcuts -local report_epdf = logs.reporter("epdf") - -local typenames = { [0] = - "boolean", - "integer", - "real", - "string", - "name", - "null", - "array", - "dictionary", - "stream", - "ref", - "cmd", - "error", - "eof", - "none", - "integer64", +local typenames = { [0] = + "boolean", + "integer", + "real", + "string", + "name", + "null", + "array", + "dictionary", + "stream", + "ref", + "cmd", + "error", + "eof", + "none", + "integer64", } -local typenumbers = table.swapped(typenames) +local typenumbers = table.swapped(typenames) + +local null_object_code = typenumbers.null +local ref_object_code = typenumbers.ref -local null_code = typenumbers.null -local ref_code = typenumbers.ref +local report_epdf = logs.reporter("epdf") local function fatal_error(...) report_epdf(...) @@ -206,32 +242,30 @@ local function prepare(document,d,t,n,k,mt,flags) if v then local r = dictGetValNF(d,i) local kind = getType(v) - if kind == null_code then + if kind == null_object_code then -- ignore - else + elseif kind then local key = dictGetKey(d,i) - if kind then - if r and getType(r) == ref_code then - local objnum = getRefNum(r) - local cached = document.__cache__[objnum] - if not cached then - cached = checked_access[kind](v,document,objnum,mt) - if cached then - document.__cache__[objnum] = cached - document.__xrefs__[cached] = objnum - end - end - t[key] = cached - else - local v, flag = checked_access[kind](v,document) - t[key] = v - if flag and flags then - flags[key] = flag -- flags + if r and getType(r) == ref_object_code then + local objnum = getRefNum(r) + local cached = document.__cache__[objnum] + if not cached then + cached = checked_access[kind](v,document,objnum,mt) + if cached then + document.__cache__[objnum] = cached + document.__xrefs__[cached] = objnum end end + t[key] = cached else - report_epdf("warning: nil value for key %a in dictionary",key) + local v, flag = checked_access[kind](v,document) + t[key] = v + if flag and flags then + flags[key] = flag -- flags + end end + else + report_epdf("warning: nil value for key %a in dictionary",key) end else fatal_error("error: invalid value at index %a in dictionary of %a",i,document.filename) @@ -245,6 +279,42 @@ local function prepare(document,d,t,n,k,mt,flags) return t[k] end +-- local function prepare(document,d,t,n,k,mt,flags) +-- for i=1,n do +-- local v = dictGetValNF(d,i) +-- if v then +-- local key = dictGetKey(d,i) +-- local kind = getType(v) +-- if kind == ref_object_code then +-- local objnum = getRefNum(v) +-- local cached = document.__cache__[objnum] +-- if not cached then +-- local v = dictGetVal(d,i) +-- local kind = getType(v) +-- cached = checked_access[kind](v,document,objnum,mt) +-- if cached then +-- document.__cache__[objnum] = cached +-- document.__xrefs__[cached] = objnum +-- end +-- end +-- t[key] = cached +-- else +-- local v, flag = checked_access[kind](v,document) +-- t[key] = v +-- if flag and flags then +-- flags[key] = flag -- flags +-- end +-- end +-- end +-- end +-- if mt then +-- setmetatable(t,mt) +-- else +-- getmetatable(t).__index = nil +-- end +-- return t[k] +-- end + local function some_dictionary(d,document) local n = d and dictGetLength(d) or 0 if n > 0 then @@ -293,11 +363,11 @@ local function prepare(document,a,t,n,k) local v = arrayGet(a,i) if v then local kind = getType(v) - if kind == null_code then + if kind == null_object_code then -- ignore elseif kind then local r = arrayGetNF(a,i) - if r and getType(r) == ref_code then + if r and getType(r) == ref_object_code then local objnum = getRefNum(r) local cached = document.__cache__[objnum] if not cached then @@ -326,6 +396,37 @@ local function prepare(document,a,t,n,k) end end +-- local function prepare(document,a,t,n,k) +-- for i=1,n do +-- local v = arrayGetNF(a,i) +-- if v then +-- local kind = getType(v) +-- if kind == ref_object_code then +-- local objnum = getRefNum(v) +-- local cached = document.__cache__[objnum] +-- if not cached then +-- local v = arrayGet(a,i) +-- local kind = getType(v) +-- cached = checked_access[kind](v,document,objnum) +-- document.__cache__[objnum] = cached +-- document.__xrefs__[cached] = objnum +-- end +-- t[i] = cached +-- else +-- t[i] = checked_access[kind](v,document) +-- end +-- end +-- end +-- local m = getmetatable(t) +-- if m then +-- m.__index = nil +-- m.__len = nil +-- end +-- if k then +-- return t[k] +-- end +-- end + local function some_array(a,document) local n = a and arrayGetLength(a) or 0 if n > 0 then @@ -376,23 +477,53 @@ end -- todo: collect chunks -local function streamaccess(s,_,what) - if not what or what == "all" or what == "*all" then - local t, n = { }, 0 - streamReset(s) +-- local function streamaccess(s,_,what) +-- if not what or what == "all" or what == "*all" then +-- local t, n = { }, 0 +-- streamReset(s) +-- while true do +-- local c = streamGetChar(s) +-- if c < 0 then +-- break +-- else +-- n = n + 1 +-- t[n] = char(c) +-- end +-- end +-- return concat(t,"",1,n) +-- end +-- end + +local function getstream(s) + streamReset(s) + if streamGetAll then + return streamGetAll(s) + else + local t, b, n = { }, { }, 0 while true do local c = streamGetChar(s) if c < 0 then break else n = n + 1 - t[n] = char(c) + b[n] = c + end + if n == 2000 then + t[#t+1] = char(unpack(b,1,n)) + n = 1 end end + t[#t+1] = char(unpack(b,1,n)) return concat(t) end end +local function streamaccess(s,_,what) + if not what or what == "all" or what == "*all" then + return getstream(s) + end +end + local function get_stream(d,document) if d then streamReset(d) @@ -562,16 +693,19 @@ end -- with but it won't win a beauty contest. local function getpages(document,Catalog) - local __data__ = document.__data__ - local __xrefs__ = document.__xrefs__ - local __cache__ = document.__cache__ - local __xref__ = document.__xref__ + local __data__ = document.__data__ + local __xrefs__ = document.__xrefs__ + local __cache__ = document.__cache__ + local __xref__ = document.__xref__ + -- + local rawcatalog = getRawCatalog(__data__) + local nofpages = getNumPages(rawcatalog) -- - local rawcatalog = getRawCatalog(__data__) - local nofpages = getNumPages(rawcatalog) + local majorversion = getMajorVersion(__data__) + local minorversion = getMinorVersion(__data__) -- - local pages = { } - local metatable = { __index = Catalog.Pages } -- somewhat empty + local pages = { } + local metatable = { __index = Catalog.Pages } -- somewhat empty -- for pagenumber=1,nofpages do local pagereference = getPageRef(rawcatalog,pagenumber).num @@ -580,6 +714,7 @@ local function getpages(document,Catalog) if pagedata then -- rawset(pagedata,"number",pagenumber) pagedata.number = pagenumber + pagedata.object = pageobject pages[pagenumber] = pagedata __xrefs__[pagedata] = pagereference __cache__[pagereference] = pagedata @@ -590,7 +725,10 @@ local function getpages(document,Catalog) -- pages.n = nofpages -- - document.pages = pages + document.pages = pages + document.majorversion = majorversion + document.minorversion = minorversion + -- return pages end @@ -637,6 +775,8 @@ function lpdf_epdf.load(filename) document.Catalog = some_dictionary(getDict(getCatalog(__xref__)),document) document.Info = some_dictionary(getDict(getDocInfo(__xref__)),document) setmetatableindex(document,resolve) + -- + document.nofpages = getNumPages(getRawCatalog(__data__)) else document = false end @@ -735,14 +875,14 @@ local fromunicode = ( P(1) )^1 * Carg(1) -local function analyzefonts(document,resources) -- unfinished +local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code local fonts = document.__fonts__ if resources then local fontlist = resources.Font if fontlist then for id, data in expanded(fontlist) do if not fonts[id] then - -- a quck hack ... I will look into it more detail if I find a real + -- a quick hack ... I will look into it more detail if I find a real -- -application for it local tounicode = data.ToUnicode() if tounicode then @@ -836,7 +976,7 @@ function lpdf_epdf.getpagecontent(document,pagenumber) end --- This is also an experiment. When I really neet it I can improve it, fo rinstance +-- This is also an experiment. When I really need it I can improve it, for instance -- with proper position calculating. It might be usefull for some search or so. local softhyphen = utfchar(0xAD) .. "$" @@ -925,3 +1065,249 @@ end -- local destination = document.__data__:findDest(name) -- return destination and destination.number -- end + +-- This is experimental code that we need for testing the transition from +-- poppler to a new lightweight library. Don't rely on this code to remain +-- as it is now. Interesting is that performance of this variant is the same +-- as the natural page includer. + +if img then do + + local copydictionary = nil + local copyarray = nil + + local ref_object_code = typenumbers.ref + local boolean_object_code = typenumbers.boolean + local integer_object_code = typenumbers.integer + local real_object_code = typenumbers.real + local string_object_code = typenumbers.string + local name_object_code = typenumbers.name + local null_object_code = typenumbers.null + local array_object_code = typenumbers.array + local dictionary_object_code = typenumbers.dictionary + local stream_object_code = typenumbers.stream + local cmd_object_code = typenumbers.cmd + + local pdfreserveobject = lpdf.reserveobject + local pdfflushobject = lpdf.flushobject + local pdfflushstreamobject = lpdf.flushstreamobject + local pdfreference = lpdf.reference + local pdfconstant = lpdf.constant + local pdfarray = lpdf.array + local pdfdictionary = lpdf.dictionary + local pdfunicode = lpdf.unicode + local pdfstring = lpdf.string + local pdfnull = lpdf.null + + local report = logs.reporter("backend","xobjects") + + local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp + + local createimage = images.create + + local function scaledbbox(b) + return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor } + end + + local function copyobject(xref,copied,kind,r,v) + if kind == null_object_code then + return pdfnull() + elseif r and getType(r) == ref_object_code then + local objnum = getRefNum(r) + local r = copied[objnum] + if r then + -- report("%s object %i is reused",kind,objnum) + else + local o + r = pdfreserveobject() + copied[objnum] = r + if kind == array_object_code then + local a = copyarray(xref,copied,fetch(xref,objnum,0)) + pdfflushobject(r,tostring(a)) + elseif kind == dictionary_object_code then + local d = copydictionary(xref,copied,fetch(xref,objnum,0)) + pdfflushobject(r,tostring(d)) + elseif kind == stream_object_code then + local f = fetch(xref,objnum,0) + local d = copydictionary(xref,copied,false,streamGetDict(f)) + local s = getstream(f) + -- + d.Filter = nil + d.Length = nil + d.DecodeParms = nil + d.DL = nil + -- + pdfflushstreamobject(s,d,true,r) + else + report("reference not done: %s", kind) + end + end + return pdfreference(r) + elseif kind == array_object_code then + return copyarray(xref,copied,v) + elseif kind == dictionary_object_code then + return copydictionary(xref,copied,v) + elseif kind == integer_object_code then + return getInt(v) + elseif kind == real_object_code then + return getReal(v) + elseif kind == name_object_code then + return pdfconstant(getName(v)) + elseif kind == string_object_code then + local s = getString(v) + if not s or s == "" then + return "" + end + local u = lpegmatch(u_pattern,s) + if u then + return pdfunicode(s) + end + return pdfstring(s) + elseif kind == boolean_object_code then + return getBool(v) + elseif kind == stream_object_code then + -- hm ... + return getStream(v) + else + report("object not done: %s", kind) + end + end + + copyarray = function (xref,copied,object) + local a = getArray(object) + local n = a and arrayGetLength(a) or 0 + if n > 0 then + local target = pdfarray() + for i=1,n do + local v = arrayGet(a,i) + if v then + local kind = getType(v) + local r = arrayGetNF(a,i) + target[i] = copyobject(xref,copied,kind,r,v) + end + end + return target + end + end + + copydictionary = function (xref,copied,object,d) + local d = d or getDict(object) + local n = d and dictGetLength(d) or 0 + if n > 0 then + local target = pdfdictionary() + for i=1,n do + local v = dictGetVal(d,i) + if v then + local kind = getType(v) + local key = dictGetKey(d,i) + local r = dictGetValNF(d,i) + target[key] = copyobject(xref,copied,kind,r,v) + end + end + return target + end + end + + local function copy_resources(pdfdoc,xref,copied,pagedata) + local object = pagedata.object + if object then + local d = getDict(object) + local n = d and dictGetLength(d) or 0 + for i=1,n do + local k = dictGetKey(d,i) + if v and k == "Resources" then + local v = dictGetVal(d,i) + local kind = getType(v) + local r = dictGetValNF(d,i) + return copyobject(xref,copied,kind,r,v) + end + end + end + end + + local function openpdf(filename) + local pdfdoc = lpdf_epdf.load(filename) + if pdfdoc then + pdfdoc.__copied__ = pdfdoc.__copied__ or { } + pdfdoc.filename = filename + return pdfdoc + end + end + + local function closepdf(pdfdoc) + if pdfdoc then + lpdf_epdf.unload(pdfdoc.filename) + end + end + + local function querypdf(pdfdoc,pagenumber) + if pdfdoc then + if not pagenumber then + pagenumber = 1 + end + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber] + if page then + local mediabox = page.MediaBox or { 0, 0, 0, 0 } + local cropbox = page.CropBox or mediabox + return { + filename = pdfdoc.filename, + pagenumber = pagenumber, + nofpages = pdfdoc.nofpages, + boundingbox = scaledbbox(cropbox), + cropbox = cropbox, + mediabox = mediabox, + bleedbox = page.BleedBox or cropbox, + trimbox = page.TrimBox or cropbox, + artbox = page.ArtBox or cropbox, + } + end + end + end + + local function copypage(pdfdoc,pagenumber,attributes) + if pdfdoc then + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber or 1] + local pageinfo = querypdf(pdfdoc,pagenumber) + local contents = page.Contents + local xref = pdfdoc.__xref__ + local copied = pdfdoc.__copied__ + -- + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Form"), + -- image attributes + FormType = 1, + BBox = pageinfo.cropbox, + -- Metadata = copy(xref,copied,root,"Metadata"), + -- Group = copy(xref,copied,page,"Group"), + -- LastModified = copy(xref,copied,page,"LastModified"), + -- Metadata = copy(xref,copied,page,"Metadata"), + -- PieceInfo = copy(xref,copied,page,"PieceInfo"), + Resources = copy_resources(pdfdoc,xref,copied,page), + -- SeparationInfo = copy(xref,copied,page,"SeparationInfo"), + } + if attributes then + for k, v in next, expand(attributes) do + page[k] = v -- maybe nested + end + end + return createimage { + bbox = pageinfo.boundingbox, + stream = contents(), + attr = xobject(), + } + end + end + + -- todo: codeinjections + + lpdf_epdf.image = { + open = openpdf, + close = closepdf, + query = querypdf, + copy = copypage, + } + +end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua index 73de5eaf60d..983be508f2c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fld.lua @@ -103,7 +103,7 @@ local pdf_tx = pdfconstant("Tx") local pdf_sig = pdfconstant("Sig") local pdf_ch = pdfconstant("Ch") local pdf_btn = pdfconstant("Btn") ------ pdf_yes = pdfconstant("Yes") +local pdf_yes = pdfconstant("Yes") local pdf_off = pdfconstant("Off") local pdf_p = pdfconstant("P") -- None Invert Outline Push local pdf_n = pdfconstant("N") -- None Invert Outline Push @@ -341,10 +341,10 @@ local function fieldsurrounding(specification) alternative, a = "tf", s.tf end local tag = fontstyle .. fontalternative - fontsize = todimen(fontsize) - fontsize = fontsize and (bpfactor * fontsize) or 12 + fontsize = todimen(fontsize) + fontsize = fontsize and (bpfactor * fontsize) or 12 fontraise = 0.1 * fontsize -- todo: figure out what the natural one is and compensate for strutdp - local fontcode = formatters["%0.4f Tf %0.4f Ts"](fontsize,fontraise) + local fontcode = formatters["%0.4F Tf %0.4F Ts"](fontsize,fontraise) -- we could test for colorvalue being 1 (black) and omit it then local colorcode = pdfcolor(3,colorvalue) -- we force an rgb color space if trace_fields then @@ -360,14 +360,16 @@ local function fieldsurrounding(specification) return tostring(stream) end +-- Can we use any font? + codeinjections.fieldsurrounding = fieldsurrounding local function registerfonts() if next(usedfonts) then checkpdfdocencoding() -- already done - local d = pdfdictionary() - local pdffonttype, pdffontsubtype = pdfconstant("Font"), pdfconstant("Type1") - -- for tag, name in next, usedfonts do + local pdffontlist = pdfdictionary() + local pdffonttype = pdfconstant("Font") + local pdffontsubtype = pdfconstant("Type1") for tag, name in sortedhash(usedfonts) do local f = pdfdictionary { Type = pdffonttype, @@ -376,9 +378,9 @@ local function registerfonts() BaseFont = pdfconstant(name), Encoding = pdfdocencodingvector, } - d[tag] = pdfreference(pdfflushobject(f)) + pdffontlist[tag] = pdfreference(pdfflushobject(f)) end - return d + return pdffontlist end end @@ -386,7 +388,7 @@ end local function fieldappearances(specification) -- todo: caching - local values = specification.values + local values = specification.values local default = specification.default -- todo if not values then -- error @@ -402,22 +404,51 @@ local function fieldappearances(specification) n, r, d = v[1], v[2], v[3] end local appearance = pdfdictionary { - N = registeredsymbol(n), R = registeredsymbol(r), D = registeredsymbol(d), + N = registeredsymbol(n), + R = registeredsymbol(r), + D = registeredsymbol(d), } return pdfshareobjectreference(appearance) -- return pdfreference(pdfflushobject(appearance)) end -local YesorOn = "Yes" -- somehow On is not always working out well any longer (why o why this change) - --- beware ... maybe we should have unique /Yes1 ... we will probably --- change this one too. +-- The rendering part of form support has always been crappy and didn't really +-- improve over time. Did bugs become features? Who knows. Why provide for instance +-- control over appearance and then ignore it when the mouse clicks someplace else. +-- Strangely enough a lot of effort went into JavaScript support while basic +-- appearance control of checkboxes stayed poor. I found this link when googling for +-- conformation after the n^th time looking into this behaviour: +-- +-- https://stackoverflow.com/questions/15479855/pdf-appearance-streams-checkbox-not-shown-correctly-after-focus-lost +-- +-- ... "In particular check boxes, therefore, whenever not interacting with the user, shall +-- be displayed using their normal captions, not their appearances." -- --- TODO: the same as radio .. play safe and use different names. +-- So: don't use check boxes. In fact, even radio buttons can have these funny "flash some +-- funny symbol" side effect when clocking on them. I tried all combinations if /H and /AP +-- and /AS and ... Because (afaiks) the acrobat interface assumes that one uses dingbats no +-- one really cared about getting custom appeances done well. This erratic behaviour might +-- as well be the reason why no open source viewer ever bothered implementing forms. It's +-- probably also why most forms out there look kind of bad. + +local function fieldstates_precheck(specification) + local values = specification.values + local default = specification.default + if not values or values == "" then + return + end + local yes = settings_to_array(values)[1] + local yesshown, yesvalue = lpegmatch(splitter,yes) + if not (yesshown and yesvalue) then + yesshown = yes + end + return default == settings_to_array(yesshown)[1] and pdf_yes or pdf_off +end -local function fieldstates_check(specification,forceyes,values,default,yesdefault) +local function fieldstates_check(specification) -- we don't use Opt here (too messy for radio buttons) - local values, default = values or specification.values, default or specification.default + local values = specification.values + local default = specification.default if not values or values == "" then -- error return @@ -459,28 +490,27 @@ local function fieldstates_check(specification,forceyes,values,default,yesdefaul if not offvalue then offvalue = offn end - if forceyes == true then - forceyes = YesorOn -- spec likes Yes more but we've used On for ages now - else - -- false or string - end if default == yesn then - default = pdfconstant(forceyes or yesn) + default = pdf_yes + yesvalue = yesvalue == yesn and "Yes" or "Off" else - default = pdf_off + default = pdf_off + yesvalue = "Off" end local appearance - if false then -- needs testing + -- if false then + if true then + -- needs testing appearance = pdfdictionary { -- maybe also cache components - N = pdfshareobjectreference(pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) }), - R = pdfshareobjectreference(pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) }), - D = pdfshareobjectreference(pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }), + N = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesn), Off = registeredsymbol(offn) }), + R = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesr), Off = registeredsymbol(offr) }), + D = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesd), Off = registeredsymbol(offd) }), } else appearance = pdfdictionary { -- maybe also cache components - N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) }, - R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) }, - D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) } + N = pdfdictionary { Yes = registeredsymbol(yesn), Off = registeredsymbol(offn) }, + R = pdfdictionary { Yes = registeredsymbol(yesr), Off = registeredsymbol(offr) }, + D = pdfdictionary { Yes = registeredsymbol(yesd), Off = registeredsymbol(offd) } } end local appearanceref = pdfshareobjectreference(appearance) @@ -488,12 +518,11 @@ local function fieldstates_check(specification,forceyes,values,default,yesdefaul return appearanceref, default, yesvalue end --- It looks like there is always a (MK related) symbol used and that --- the appearances are only used as ornaments behind a symbol. So, --- contrary to what we did when widgets showed up, we now limit --- ourself to more dumb definitions. Especially when highlighting is --- enabled weird interferences happen. So, we play safe (some nice code --- has been removed that worked well till recently). +-- It looks like there is always a (MK related) symbol used and that the appearances +-- are only used as ornaments behind a symbol. So, contrary to what we did when +-- widgets showed up, we now limit ourself to more dumb definitions. Especially when +-- highlighting is enabled weird interferences happen. So, we play safe (some nice +-- code has been removed that worked well till recently). local function fieldstates_radio(specification,name,parent) local values = values or specification.values @@ -572,7 +601,7 @@ local function fieldstates_radio(specification,name,parent) return appearanceref, default, yesvalue end -local function fielddefault(field) +local function fielddefault(field,pdf_yes) local default = field.default if not default or default == "" then local values = settings_to_array(field.values) @@ -581,12 +610,12 @@ local function fielddefault(field) if not default or default == "" then return pdf_off else - return pdfconstant(default) + return pdf_yes or pdfconstant(default) end end local function fieldoptions(specification) - local values = specification.values + local values = specification.values local default = specification.default if values then local v = settings_to_array(values) @@ -790,7 +819,9 @@ function codeinjections.definefield(specification) end function codeinjections.clonefield(specification) -- obsolete - local p, c, v = specification.parent, specification.children, specification.alternative + local p = specification.parent + local c = specification.children + local v = specification.alternative if not p or not c then if trace_fields then report_fields("invalid clone, children %a, parent %a, alternative %a",c,p,v) @@ -874,7 +905,8 @@ local function enhance(specification,option) return specification end --- finish +-- finish (if we also collect parents we can inline the kids which is +-- more efficient ... but hardly anyone used widgets so ...) local collected = pdfarray() local forceencoding = false @@ -949,14 +981,14 @@ end local function save_parent(field,specification,d,hasopt) local kidsnum = pdfreserveobject() - d.Kids = pdfreference(kidsnum) + d.Kids = pdfreference(kidsnum) field.kidsnum = kidsnum - field.kids = pdfarray() + field.kids = pdfarray() if hasopt then local optnum = pdfreserveobject() - d.Opt = pdfreference(optnum) + d.Opt = pdfreference(optnum) field.optnum = optnum - field.opt = pdfarray() + field.opt = pdfarray() end local pnum = pdfflushobject(d) field.pobj = pnum @@ -972,16 +1004,21 @@ local function save_kid(field,specification,d,optname) opt[#opt+1] = optname end end - local width, height, depth = specification.width or 0, specification.height or 0, specification.depth + local width = specification.width or 0 + local height = specification.height or 0 + local depth = specification.depth or 0 local box = hpack_node(nodeinjections.annotation(width,height,depth,d(),kn)) - box.width, box.height, box.depth = width, height, depth -- redundant + -- redundant + box.width = width + box.height = height + box.depth = depth return box end local function makelineparent(field,specification) - local text = pdfunicode(field.default) + local text = pdfunicode(field.default) local length = tonumber(specification.length or 0) or 0 - local d = pdfdictionary { + local d = pdfdictionary { Subtype = pdf_widget, T = pdfunicode(specification.title), F = fieldplus(specification), @@ -999,7 +1036,8 @@ local function makelineparent(field,specification) end local function makelinechild(name,specification) - local field, parent = clones[name], nil + local field = clones[name] + local parent = nil if field then parent = fields[field.parent] if not parent.pobj then @@ -1010,7 +1048,7 @@ local function makelinechild(name,specification) end else parent = fields[name] - field = parent + field = parent if not parent.pobj then if trace_fields then report_fields("using parent text %a",name) @@ -1047,9 +1085,9 @@ end -- copy of line ... probably also needs a /Lock local function makesignatureparent(field,specification) - local text = pdfunicode(field.default) + local text = pdfunicode(field.default) local length = tonumber(specification.length or 0) or 0 - local d = pdfdictionary { + local d = pdfdictionary { Subtype = pdf_widget, T = pdfunicode(specification.title), F = fieldplus(specification), @@ -1067,7 +1105,8 @@ local function makesignatureparent(field,specification) end local function makesignaturechild(name,specification) - local field, parent = clones[name], nil + local field = clones[name] + local parent = nil if field then parent = fields[field.parent] if not parent.pobj then @@ -1078,7 +1117,7 @@ local function makesignaturechild(name,specification) end else parent = fields[name] - field = parent + field = parent if not parent.pobj then if trace_fields then report_fields("using parent text %a",name) @@ -1124,7 +1163,8 @@ local function makechoiceparent(field,specification) end local function makechoicechild(name,specification) - local field, parent = clones[name], nil + local field = clones[name] + local parent = nil if field then parent = fields[field.parent] if not parent.pobj then @@ -1135,7 +1175,7 @@ local function makechoicechild(name,specification) end else parent = fields[name] - field = parent + field = parent if not parent.pobj then if trace_fields then report_fields("using parent choice %a",name) @@ -1169,20 +1209,22 @@ function methods.combo(name,specification) end local function makecheckparent(field,specification) + local default = fieldstates_precheck(field) local d = pdfdictionary { T = pdfunicode(specification.title), -- todo: when tracing use a string F = fieldplus(specification), Ff = fieldflag(specification), OC = fieldlayer(specification), - AA = fieldactions(specification), + AA = fieldactions(specification), -- can be shared FT = pdf_btn, - V = fielddefault(field), + V = fielddefault(field,default), } save_parent(field,specification,d,true) end local function makecheckchild(name,specification) - local field, parent = clones[name], nil + local field = clones[name] + local parent = nil if field then parent = fields[field.parent] if not parent.pobj then @@ -1193,7 +1235,7 @@ local function makecheckchild(name,specification) end else parent = fields[name] - field = parent + field = parent if not parent.pobj then if trace_fields then report_fields("using parent check %a",name) @@ -1209,7 +1251,7 @@ local function makecheckchild(name,specification) Parent = pdfreference(parent.pobj), F = fieldplus(specification), OC = fieldlayer(specification), - AA = fieldactions(specification), + AA = fieldactions(specification), -- can be shared H = pdf_n, } local fontsymbol = specification.fontsymbol @@ -1221,10 +1263,10 @@ local function makecheckchild(name,specification) d.MK = fieldrendering(specification) return save_kid(parent,specification,d) else - local appearance, default, value = fieldstates_check(field,true) + local appearance, default, value = fieldstates_check(field) d.AS = default d.AP = appearance - return save_kid(parent,specification,d,value) + return save_kid(parent,specification,d) end end @@ -1239,7 +1281,7 @@ local function makepushparent(field,specification) -- check if we can share with F = fieldplus(specification), Ff = fieldflag(specification), OC = fieldlayer(specification), - AA = fieldactions(specification), + AA = fieldactions(specification), -- can be shared FT = pdf_btn, AP = fieldappearances(field), H = pdf_p, @@ -1276,7 +1318,7 @@ local function makepushchild(name,specification) Parent = pdfreference(field.pobj), F = fieldplus(specification), OC = fieldlayer(specification), - AA = fieldactions(specification), + AA = fieldactions(specification), -- can be shared H = pdf_p, } if fontsymbol and fontsymbol ~= "" then @@ -1311,7 +1353,7 @@ end local function makeradiochild(name,specification) local field, parent = clones[name], nil if field then - field = radios[field.parent] + field = radios[field.parent] parent = fields[field.parent] if not parent.pobj then if trace_fields then diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua index 0830d2d8d82..25a72fa49bc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fmt.lua @@ -116,6 +116,7 @@ local formats = utilities.storage.allocate { jbig2_compression = true, -- todo: block at lua level jpeg2000_compression = true, -- todo: block at lua level include_cidsets = true, + include_charsets = true, inject_metadata = function() -- nothing end @@ -131,6 +132,7 @@ local formats = utilities.storage.allocate { spot_colors = true, internal_icc_profiles = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() addtoinfo("GTS_PDFXVersion","PDF/X-1a:2001") injectxmpinfo("xml://rdf:RDF","PDF/X-1a:2001",false) @@ -146,6 +148,7 @@ local formats = utilities.storage.allocate { spot_colors = true, internal_icc_profiles = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() addtoinfo("GTS_PDFXVersion","PDF/X-1a:2003") injectxmpinfo("xml://rdf:RDF","PDF/X-1a:2003",false) @@ -165,6 +168,7 @@ local formats = utilities.storage.allocate { internal_icc_profiles = true, include_intents = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() addtoinfo("GTS_PDFXVersion","PDF/X-3:2002") end @@ -184,6 +188,7 @@ local formats = utilities.storage.allocate { include_intents = true, jbig2_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() addtoinfo("GTS_PDFXVersion","PDF/X-3:2003") end @@ -207,6 +212,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","PDF/X-4",false) insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","1",false) @@ -233,6 +239,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","PDF/X-4p",false) insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","1",false) @@ -259,6 +266,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() -- todo end @@ -284,6 +292,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() -- todo end @@ -308,6 +317,7 @@ local formats = utilities.storage.allocate { nchannel_colorspace = true, object_compression = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() -- todo end @@ -328,6 +338,7 @@ local formats = utilities.storage.allocate { tagging = true, -- NEW; the only difference to PDF/A-1b internal_icc_profiles = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","1A",false) end @@ -347,6 +358,7 @@ local formats = utilities.storage.allocate { forms = true, internal_icc_profiles = true, include_cidsets = true, + include_charsets = true, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","1B",false) end @@ -371,6 +383,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, -- NEW object_compression = true, include_cidsets = false, + include_charsets = false, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","2A",false) end @@ -395,6 +408,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = false, + include_charsets = false, inject_metadata = function() injectxmpinfo("xml://rdf:RDF","3A",false) end @@ -418,6 +432,7 @@ local formats = utilities.storage.allocate { jpeg2000_compression = true, object_compression = true, include_cidsets = true, + include_charsets = true, --- really ? inject_metadata = function() injectxmpinfo("xml://rdf:RDF","3A",false) injectxmpinfo("xml://rdf:RDF","1",false) @@ -753,7 +768,11 @@ function codeinjections.setformat(s) majorversion,minorversion) end -- - pdf.setomitcidset(formatspecification.include_cidsets == false and 1 or 0) + -- cid sets can always omitted now, but those validators still complain so let's + -- for a while keep it (for luigi): + -- + lpdf.setomitcidset (formatspecification.include_cidsets == false and 1 or 0) + lpdf.setomitcharset(formatspecification.include_charsets == false and 1 or 0) -- -- context.setupcolors { -- not this way -- cmyk = spec.cmyk_colors and variables.yes or variables.no, diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fnt.lua new file mode 100644 index 00000000000..1caa2f93c98 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-fnt.lua @@ -0,0 +1,202 @@ +if not modules then modules = { } end modules ['lpdf-fnt'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is experimental code. + +local match, gmatch = string.match, string.gmatch +local tonumber = tonumber + +local pdfreserveobject = lpdf.reserveobject +local pdfincludechar = lpdf.includechar +local pdfincludefont = lpdf.includefont +local pdfreference = lpdf.reference + +local pdfe = lpdf.epdf + +local tobemerged = { } +local trace_merge = false trackers.register("graphics.fonts",function(v) trace_merge = v end) +local report_merge = logs.reporter("graphics","fonts") + +local function register(usedname,cleanname) + local cleanname = cleanname or fonts.names.cleanname(usedname) + local fontid = fonts.definers.internal { name = cleanname } + if fontid then + local objref = pdfreserveobject() + pdfincludefont(fontid) + if trace_merge then + report_merge("registering %a with name %a, id %a and object %a",usedname,cleanname,fontid,objref) + end + return { + id = fontid, + reference = objref, + indices = { }, + cleanname = cleanname, + } + end + return false +end + +function lpdf.registerfont(usedname,cleanname) + local v = register(usedname,cleanname) + tobemerged[usedname] = v + return v +end + +table.setmetatableindex(tobemerged,function(t,k) + return lpdf.registerfont(k) +end) + +local function finalizefont(v) + local indextoslot = fonts.helpers.indextoslot + if v then + local id = v.id + local n = 0 + for i in next, v.indices do + local u = indextoslot(id,i) + -- pdfincludechar(id,u) + n = n + 1 + end + v.n = n + end +end + +statistics.register("merged fonts", function() + if next(tobemerged) then + local t = { } + for k, v in table.sortedhash(tobemerged) do + t[#t+1] = string.formatters["%s (+%i)"](k,v.n) + end + return table.concat(t," ") + end +end) + +function lpdf.finalizefonts() + for k, v in next, tobemerged do + finalizefont(v) + end +end + +callback.register("font_descriptor_objnum_provider",function(name) + local m = rawget(tobemerged,name) + if m then + -- finalizefont(m) + local r = m.reference or 0 + if trace_merge then + report_merge("using object %a for font descriptor of %a",r,name) + end + return r + end + return 0 +end) + +local function getunicodes1(str,indices) + for s in gmatch(str,"beginbfrange%s*(.-)%s*endbfrange") do + for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do + for i=tonumber(first,16),tonumber(last,16) do + indices[i] = true + end + end + end + for s in gmatch(str,"beginbfchar%s*(.-)%s*endbfchar") do + for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do + indices[tonumber(old,16)] = true + end + end +end + +local function getunicodes2(widths,indices) + for i=1,#widths,2 do + local start = widths[i] + local count = #widths[i+1] + if start and count then + for i=start,start+count-1 do + indices[i] = true + end + end + end +end + +local function checkedfonts(pdfdoc,xref,copied,page) + local list = page.Resources.Font + local done = { } + for k, somefont in pdfe.expanded(list) do + if somefont.Subtype == "Type0" and somefont.Encoding == "Identity-H" then + local descendants = somefont.DescendantFonts + if descendants then + for i=1,#descendants do + local d = descendants[i] + if d then + local subtype = d.Subtype + if subtype == "CIDFontType0" or subtype == "CIDFontType2" then + local basefont = somefont.BaseFont + if basefont then + local fontname = match(basefont,"^[A-Z]+%+(.+)$") + local fontdata = tobemerged[fontname] + if fontdata then + local descriptor = d.FontDescriptor + if descriptor then + local okay = false + local widths = d.W + if widths then + getunicodes2(widths,fontdata.indices) + okay = true + else + local tounicode = somefont.ToUnicode + if tounicode then + getunicodes1(tounicode(),fontdata.indices) + okay = true + end + end + if okay then + local r = xref[descriptor] + done[r] = fontdata.reference + end + end + end + end + end + end + end + end + end + end + return next(done) and done +end + +if pdfincludefont then + + function lpdf.epdf.plugin(pdfdoc,xref,copied,page) + local done = checkedfonts(pdfdoc,xref,copied,page) + if done then + return { + FontDescriptor = function(xref,copied,object,key,value,copyobject) + local r = value[3] + local d = done[r] + if d then + return pdfreference(d) + else + return copyobject(xref,copied,object,key,value) + end + end + } + end + end + +else + + function lpdf.epdf.plugin() end + +end + +lpdf.registerdocumentfinalizer(lpdf.finalizefonts) + +-- already defined in font-ocl but the context variatn will go here +-- +-- function lpdf.vfimage(wd,ht,dp,data,name) +-- return { "image", { filename = name, width = wd, height = ht, depth = dp } } +-- end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua index 34925fddd98..49cc7687111 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-grp.lua @@ -29,6 +29,10 @@ local pdfboolean = lpdf.boolean local pdfreference = lpdf.reference local pdfflushobject = lpdf.flushobject +local createimage = images.create +local wrapimage = images.wrap +local embedimage = images.embed + -- can also be done indirectly: -- -- 12 : << /AntiAlias false /ColorSpace 8 0 R /Coords [ 0.0 0.0 1.0 0.0 ] /Domain [ 0.0 1.0 ] /Extend [ true true ] /Function 22 0 R /ShadingType 2 >> @@ -153,13 +157,18 @@ function nodeinjections.injectbitmap(t) elseif height == 0 then height = width * yresolution / xresolution end - local image = img.new { + local a = pdfdictionary { + BBox = pdfarray { 0, 0, urx * basepoints, ury * basepoints } + } + local image = createimage { stream = formatters[template](d(),t.data), width = width, height = height, bbox = { 0, 0, urx, ury }, + attr = a(), + nobbox = true, } - return img.node(image) + return wrapimage(image) end -- general graphic helpers @@ -181,7 +190,7 @@ function codeinjections.setfigurealternative(data,figure) local displayfigure = figures.check() if displayfigure then -- figure.aform = true - img.immediatewrite(figure) + embedimage(figure) local a = pdfarray { pdfdictionary { Image = pdfreference(figure.objnum), @@ -215,14 +224,14 @@ function codeinjections.getpreviewfigure(request) end local image = figure.status.private if image then - img.immediatewrite(image) + embedimage(image) end return figure end function codeinjections.setfiguremask(data,figure) -- mark local request = data.request - local mask = request.mask + local mask = request.mask if mask and mask ~= "" then figures.push { name = mask, @@ -233,15 +242,16 @@ function codeinjections.setfiguremask(data,figure) -- mark width = request.width, height = request.height, } - figures.identify() - local maskfigure = figures.check() - if maskfigure then - local image = maskfigure.status.private + mask = figures.identify() + mask = figures.check(mask) + if mask then + local image = mask.status.private if image then - img.immediatewrite(image) + figures.include(mask) + embedimage(image) local d = pdfdictionary { Interpolate = false, - SMask = pdfreference(image.objnum), + SMask = pdfreference(mask.status.objectnumber), } figure.attr = d() end @@ -250,39 +260,16 @@ function codeinjections.setfiguremask(data,figure) -- mark end end --- temp hack +-- experimental (q Q is not really needed) -function img.package(image) -- see lpdf-u3d ** - local boundingbox = image.bbox - local imagetag = "Im" .. image.index - local resources = pdfdictionary { - ProcSet = pdfarray { - pdfconstant("PDF"), - pdfconstant("ImageC") - }, - Resources = pdfdictionary { - XObject = pdfdictionary { - [imagetag] = pdfreference(image.objnum) - } - } - } - local width = boundingbox[3] - local height = boundingbox[4] - local xform = img.scan { - attr = resources(), - stream = formatters["%.6F 0 0 %.6F 0 0 cm /%s Do"](width,height,imagetag), - bbox = { 0, 0, width/basepoints, height/basepoints }, - } - img.immediatewrite(xform) - return xform -end +local f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6F %.6F re f Q"] --- experimental +directives.register("pdf.stripzeros",function() + f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6N %.6N re f Q"] +end) -local nofpatterns = 0 -local f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6F %.6F re f Q"] -- q Q is not really needed - -local texsavebox = tex.saveboxresource +local saveboxresource = tex.boxresources.save +local nofpatterns = 0 function lpdf.registerpattern(specification) nofpatterns = nofpatterns + 1 @@ -299,10 +286,11 @@ function lpdf.registerpattern(specification) (specification.voffset or 0) * basepoints, }, } + local resources = lpdf.collectedresources{ patterns = false } local attributes = d() local onlybounds = 1 - local patternobj = texsavebox(specification.number,attributes,resources,true,onlybounds) + local patternobj = saveboxresource(specification.number,attributes,resources,true,onlybounds) lpdf.adddocumentpattern("Pt" .. nofpatterns,lpdf.reference(patternobj )) return nofpatterns end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua index 8af1fb40965..ec837449f7e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ini.lua @@ -13,7 +13,8 @@ local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values local sind, cosd, max, min = math.sind, math.cosd, math.max, math.min local sort = table.sort -local lpegmatch, P, C, R, S, Cc, Cs = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs +local P, C, R, S, Cc, Cs, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs, lpeg.V +local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns local formatters = string.formatters local isboolean = string.is_boolean local rshift = bit32.rshift @@ -31,217 +32,234 @@ local context = context -- encoded utf16 string type between <>. We could probably save some bytes by using -- strings between () but then we end up with escaped ()\ too. --- gethpos : used --- getpos : used --- getvpos : used --- --- getmatrix : used --- hasmatrix : used --- --- mapfile : used in font-ctx.lua --- mapline : used in font-ctx.lua --- --- maxobjnum : not used --- obj : used --- immediateobj : used --- objtype : not used --- pageref : used --- print : can be used --- refobj : used --- registerannot : not to be used --- reserveobj : used - --- pdf.catalog : used --- pdf.info : used --- pdf.trailer : used --- pdf.names : not to be used - --- pdf.setinfo : used --- pdf.setcatalog : used --- pdf.setnames : not to be used --- pdf.settrailer : used - --- pdf.getinfo : used --- pdf.getcatalog : used --- pdf.getnames : not to be used --- pdf.gettrailer : used - -local pdf = pdf -local factor = number.dimenfactors.bp - -local pdfsetinfo = pdf.setinfo -local pdfsetcatalog = pdf.setcatalog ------ pdfsettrailerid = pdf.settrailerid ------ pdfsetnames = pdf.setnames ------ pdfsettrailer = pdf.settrailer - -local pdfsetpageresources = pdf.setpageresources -local pdfsetpageattributes = pdf.setpageattributes -local pdfsetpagesattributes = pdf.setpagesattributes - -local pdfgetpos = pdf.getpos -local pdfgethpos = pdf.gethpos -local pdfgetvpos = pdf.getvpos -local pdfgetmatrix = pdf.getmatrix -local pdfhasmatrix = pdf.hasmatrix - -local pdfreserveobject = pdf.reserveobj -local pdfimmediateobject = pdf.immediateobj -local pdfdeferredobject = pdf.obj -local pdfreferenceobject = pdf.refobj - -local function pdfdisablecommand(command) - pdf[command] = function() report_blocked("'pdf.%s' is not supported",command) end -end +pdf = type(pdf) == "table" and pdf or { } +local factor = number.dimenfactors.bp -pdfdisablecommand("setinfo") -pdfdisablecommand("setcatalog") -pdfdisablecommand("setnames") -pdfdisablecommand("settrailer") -pdfdisablecommand("setpageresources") -pdfdisablecommand("setpageattributes") -pdfdisablecommand("setpagesattributes") -pdfdisablecommand("registerannot") +local codeinjections = { } +local nodeinjections = { } -pdf.disablecommand = pdfdisablecommand +local backends = backends -local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end) -local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end) -local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end) -local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end) - -local backends = backends -local pdfbackend = { +local pdfbackend = { comment = "backend for directly generating pdf output", - nodeinjections = { }, - codeinjections = { }, + nodeinjections = nodeinjections, + codeinjections = codeinjections, registrations = { }, tables = { }, } -backends.pdf = pdfbackend -lpdf = lpdf or { } -local lpdf = lpdf -lpdf.flags = lpdf.flags or { } -- will be filled later +backends.pdf = pdfbackend -do +lpdf = lpdf or { } +local lpdf = lpdf +lpdf.flags = lpdf.flags or { } -- will be filled later + +local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end) +local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end) +local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end) +local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end) - local setmajorversion = pdf.setmajorversion - local setminorversion = pdf.setminorversion - local getmajorversion = pdf.getmajorversion - local getminorversion = pdf.getminorversion +do - if not setmajorversion then + local pdfsetmajorversion, pdfsetminorversion, pdfgetmajorversion, pdfgetminorversion + local pdfsetcompresslevel, pdfsetobjectcompresslevel, pdfgetcompresslevel, pdfgetobjectcompresslevel + local pdfsetsuppressoptionalinfo, pdfsetomitcidset, pdfsetomitcharset - setmajorversion = function() end - getmajorversion = function() return 1 end + updaters.register("backend.update.lpdf",function() + pdfsetmajorversion = pdf.setmajorversion + pdfsetminorversion = pdf.setminorversion + pdfgetmajorversion = pdf.getmajorversion + pdfgetminorversion = pdf.getminorversion - pdf.setmajorversion = setmajorversion - pdf.getmajorversion = getmajorversion + pdfsetcompresslevel = pdf.setcompresslevel + pdfsetobjectcompresslevel = pdf.setobjcompresslevel + pdfgetcompresslevel = pdf.getcompresslevel + pdfgetobjectcompresslevel = pdf.getobjcompresslevel - end + pdfsetsuppressoptionalinfo = pdf.setsuppressoptionalinfo + pdfsetomitcidset = pdf.setomitcidset + pdfsetomitcharset = pdf.setomitcharset + end) function lpdf.setversion(major,minor) - setmajorversion(major or 1) - setminorversion(minor or 7) + pdfsetmajorversion(major or 1) + pdfsetminorversion(minor or 7) end function lpdf.getversion(major,minor) - return getmajorversion(), getminorversion() + return pdfgetmajorversion(), pdfgetminorversion() end - lpdf.majorversion = getmajorversion - lpdf.minorversion = getminorversion - -end - -do - - local setcompresslevel = pdf.setcompresslevel - local setobjectcompresslevel = pdf.setobjcompresslevel - local getcompresslevel = pdf.getcompresslevel - local getobjectcompresslevel = pdf.getobjcompresslevel + function lpdf.majorversion() return pdfgetmajorversion() end + function lpdf.minorversion() return pdfgetminorversion() end local frozen = false + local clevel = 3 + local olevel = 1 function lpdf.setcompression(level,objectlevel,freeze) if not frozen then - setcompresslevel(level or 3) - setobjectcompresslevel(objectlevel or level or 3) + if pdfsetcompresslevel then + pdfsetcompresslevel(level or 3) + pdfsetobjectcompresslevel(objectlevel or level or 3) + else + clevel = level + olevel = objectlevel + end frozen = freeze end end function lpdf.getcompression() - return getcompresslevel(), getobjectcompresslevel() + if pdfgetcompresslevel then + return pdfgetcompresslevel(), pdfgetobjectcompresslevel() + else + return clevel, olevel + end end - lpdf.compresslevel = getcompresslevel - lpdf.objectcompresslevel = getobjectcompresslevel + function lpdf.compresslevel() + if pdfgetcompresslevel then + return pdfgetcompresslevel() + else + return clevel + end + end -end + function lpdf.objectcompresslevel() + if pdfgetobjectcompresslevel then + return pdfgetobjectcompresslevel() + else + return olevel + end + end -local codeinjections = pdfbackend.codeinjections -local nodeinjections = pdfbackend.nodeinjections - -codeinjections.getpos = pdfgetpos lpdf.getpos = pdfgetpos -codeinjections.gethpos = pdfgethpos lpdf.gethpos = pdfgethpos -codeinjections.getvpos = pdfgetvpos lpdf.getvpos = pdfgetvpos -codeinjections.hasmatrix = pdfhasmatrix lpdf.hasmatrix = pdfhasmatrix -codeinjections.getmatrix = pdfgetmatrix lpdf.getmatrix = pdfgetmatrix - --- local function transform(llx,lly,urx,ury,rx,sx,sy,ry) --- local x1 = llx * rx + lly * sy --- local y1 = llx * sx + lly * ry --- local x2 = llx * rx + ury * sy --- local y2 = llx * sx + ury * ry --- local x3 = urx * rx + lly * sy --- local y3 = urx * sx + lly * ry --- local x4 = urx * rx + ury * sy --- local y4 = urx * sx + ury * ry --- llx = min(x1,x2,x3,x4); --- lly = min(y1,y2,y3,y4); --- urx = max(x1,x2,x3,x4); --- ury = max(y1,y2,y3,y4); --- return llx, lly, urx, ury --- end + function lpdf.setsuppressoptionalinfo(n) + if pdfsetsuppressoptionalinfo then + pdfsetsuppressoptionalinfo(n) -- todo + end + end -function lpdf.transform(llx,lly,urx,ury) -- not yet used so unchecked - if pdfhasmatrix() then - local sx, rx, ry, sy = pdfgetmatrix() - local w, h = urx - llx, ury - lly - return llx, lly, llx + sy*w - ry*h, lly + sx*h - rx*w - -- return transform(llx,lly,urx,ury,sx,rx,ry,sy) - else - return llx, lly, urx, ury + function lpdf.setomitcidset(v) + return pdfsetomitcidset(v) end + + function lpdf.setomitcharset(v) + return pdfsetomitcharset(v) + end + end --- funny values for tx and ty - -function lpdf.rectangle(width,height,depth,offset) - local tx, ty = pdfgetpos() - if offset then - tx = tx - offset - ty = ty + offset - width = width + 2*offset - height = height + offset - depth = depth + offset - end - if pdfhasmatrix() then - local rx, sx, sy, ry = pdfgetmatrix() - return - factor * tx, - factor * (ty - ry*depth + sx*width), - factor * (tx + rx*width - sy*height), - factor * (ty + ry*height - sx*width) - else - return - factor * tx, - factor * (ty - depth), - factor * (tx + width), - factor * (ty + height) +do + + local pdfgetxformname, pdfincludeimage + + updaters.register("backend.update.lpdf",function() + pdfgetxformname = pdf.getxformname + pdfincludeimage = pdf.includeimage + end) + + function lpdf.getxformname(id) return pdfgetxformname(id) end + function lpdf.includeimage(id) return pdfincludeimage(id) end + +end + + local pdfsetpageresources, pdfsetpageattributes, pdfsetpagesattributes + local pdfreserveobject, pdfimmediateobject, pdfdeferredobject, pdfreferenceobject + local pdfgetpagereference + + updaters.register("backend.update.lpdf",function() + pdfreserveobject = pdf.reserveobj + pdfimmediateobject = pdf.immediateobj + pdfdeferredobject = pdf.obj + pdfreferenceobject = pdf.refobj + + pdfgetpagereference = pdf.getpageref + + pdfsetpageresources = pdf.setpageresources + pdfsetpageattributes = pdf.setpageattributes + pdfsetpagesattributes = pdf.setpagesattributes + end) + +local jobpositions = job.positions +local getpos = jobpositions.getpos + +jobpositions.registerhandlers { + getpos = pdf.getpos, + gethpos = pdf.gethpos, + getvpos = pdf.getvpos, +} + +do + + local pdfgetmatrix, pdfhasmatrix, pdfprint + + updaters.register("backend.update.lpdf",function() + pdfgetmatrix = pdf.getmatrix + pdfhasmatrix = pdf.hasmatrix + pdfprint = pdf.print + end) + + function lpdf.print(...) + return pdfprint(...) + end + + pdfbackend.codeinjections.print = lpdf.print -- will go + + -- local function transform(llx,lly,urx,ury,rx,sx,sy,ry) + -- local x1 = llx * rx + lly * sy + -- local y1 = llx * sx + lly * ry + -- local x2 = llx * rx + ury * sy + -- local y2 = llx * sx + ury * ry + -- local x3 = urx * rx + lly * sy + -- local y3 = urx * sx + lly * ry + -- local x4 = urx * rx + ury * sy + -- local y4 = urx * sx + ury * ry + -- llx = min(x1,x2,x3,x4); + -- lly = min(y1,y2,y3,y4); + -- urx = max(x1,x2,x3,x4); + -- ury = max(y1,y2,y3,y4); + -- return llx, lly, urx, ury + -- end + -- + -- function lpdf.transform(llx,lly,urx,ury) -- not yet used so unchecked + -- if pdfhasmatrix() then + -- local sx, rx, ry, sy = pdfgetmatrix() + -- local w, h = urx - llx, ury - lly + -- return llx, lly, llx + sy*w - ry*h, lly + sx*h - rx*w + -- -- return transform(llx,lly,urx,ury,sx,rx,ry,sy) + -- else + -- return llx, lly, urx, ury + -- end + -- end + + -- funny values for tx and ty + + function lpdf.rectangle(width,height,depth,offset) + local tx, ty = getpos() + if offset then + tx = tx - offset + ty = ty + offset + width = width + 2*offset + height = height + offset + depth = depth + offset + end + if pdfhasmatrix() then + local rx, sx, sy, ry = pdfgetmatrix() + return + factor * tx, + factor * (ty - ry*depth + sx*width), + factor * (tx + rx*width - sy*height), + factor * (ty + ry*height - sx*width) + else + return + factor * tx, + factor * (ty - depth), + factor * (tx + width), + factor * (ty + height) + end end + end -- we could use a hash of predefined unicodes @@ -265,204 +283,290 @@ end -- end -- end -local cache = table.setmetatableindex(function(t,k) -- can be made weak - local v = utfbyte(k) - if v < 0x10000 then - v = format("%04x",v) - else - v = format("%04x%04x",rshift(v,10),v%1024+0xDC00) +local tosixteen, fromsixteen, topdfdoc, frompdfdoc, toeight, fromeight + +do + + local escaped = Cs(Cc("(") * (S("\\()\n\r\t\b\f")/"\\%0" + P(1))^0 * Cc(")")) + + local cache = table.setmetatableindex(function(t,k) -- can be made weak + local v = utfbyte(k) + if v < 0x10000 then + v = format("%04x",v) + else + v = format("%04x%04x",rshift(v,10),v%1024+0xDC00) + end + t[k] = v + return v + end) + + local unified = Cs(Cc("")) + + tosixteen = function(str) -- an lpeg might be faster (no table) + if not str or str == "" then + return "" -- not () as we want an indication that it's unicode + else + return lpegmatch(unified,str) + end end - t[k] = v - return v -end) -local escaped = Cs(Cc("(") * (S("\\()")/"\\%0" + P(1))^0 * Cc(")")) -local unified = Cs(Cc("")) + local more = 0 -local function tosixteen(str) -- an lpeg might be faster (no table) - if not str or str == "" then - return "" -- not () as we want an indication that it's unicode - else - return lpegmatch(unified,str) + local pattern = C(4) / function(s) -- needs checking ! + local now = tonumber(s,16) + if more > 0 then + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + more = 0 + return utfchar(now) + elseif now >= 0xD800 and now <= 0xDBFF then + more = now + return "" -- else the c's end up in the stream + else + return utfchar(now) + end end -end -local more = 0 - -local pattern = C(4) / function(s) -- needs checking ! - local now = tonumber(s,16) - if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong - more = 0 - return utfchar(now) - elseif now >= 0xD800 and now <= 0xDBFF then - more = now - return "" -- else the c's end up in the stream - else - return utfchar(now) + local pattern = P(true) / function() more = 0 end * Cs(pattern^0) + + fromsixteen = function(str) + if not str or str == "" then + return "" + else + return lpegmatch(pattern,str) + end end -end -local pattern = P(true) / function() more = 0 end * Cs(pattern^0) + local toregime = regimes.toregime + local fromregime = regimes.fromregime -local function fromsixteen(str) - if not str or str == "" then - return "" - else - return lpegmatch(pattern,str) + topdfdoc = function(str,default) + if not str or str == "" then + return "" + else + return lpegmatch(escaped,toregime("pdfdoc",str,default)) -- could be combined if needed + end end -end -local toregime = regimes.toregime -local fromregime = regimes.fromregime + frompdfdoc = function(str) + if not str or str == "" then + return "" + else + return fromregime("pdfdoc",str) + end + end -local function topdfdoc(str,default) - if not str or str == "" then - return "" - else - return lpegmatch(escaped,toregime("pdfdoc",str,default)) -- could be combined if needed + if not toregime then topdfdoc = function(s) return s end end + if not fromregime then frompdfdoc = function(s) return s end end + + toeight = function(str) + if not str or str == "" then + return "()" + else + return lpegmatch(escaped,str) + end end -end -local function frompdfdoc(str) - if not str or str == "" then - return "" - else - return fromregime("pdfdoc",str) + local b_pattern = Cs((P("\\")/"" * ( + S("()") + + S("nrtbf") / { n = "\n", r = "\r", t = "\t", b = "\b", f = "\f" } + + lpegpatterns.octdigit^-3 / function(s) return char(tonumber(s,8)) end) + + P(1))^0) + + fromeight = function(str) + if not str or str == "" then + return "" + else + return lpegmatch(unescape,str) + end end -end -if not toregime then topdfdoc = function(s) return s end end -if not fromregime then frompdfdoc = function(s) return s end end + local u_pattern = lpegpatterns.utfbom_16_be * lpegpatterns.utf16_to_utf8_be -- official + + lpegpatterns.utfbom_16_le * lpegpatterns.utf16_to_utf8_le -- we've seen these + + local h_pattern = lpegpatterns.hextobytes + + local zero = S(" \n\r\t") + P("\\ ") + local one = C(4) + local two = P("d") * R("89","af") * C(2) * C(4) + + local x_pattern = P { "start", + start = V("wrapped") + V("unwrapped") + V("original"), + original = Cs(P(1)^0), + wrapped = P("<") * V("unwrapped") * P(">") * P(-1), + unwrapped = P("feff") + * Cs( ( + zero / "" + + two / function(a,b) + a = (tonumber(a,16) - 0xD800) * 1024 + b = (tonumber(b,16) - 0xDC00) + return utfchar(a+b) + end + + one / function(a) + return utfchar(tonumber(a,16)) + end + )^1 ) * P(-1) + } -local function toeight(str) - if not str or str == "" then - return "()" - else - return lpegmatch(escaped,str) + function lpdf.frombytes(s,hex) + if not s or s == "" then + return "" + end + if hex then + local x = lpegmatch(x_pattern,s) + if x then + return x + end + local h = lpegmatch(h_pattern,s) + if h then + return h + end + else + local u = lpegmatch(u_pattern,s) + if u then + return u + end + end + return lpegmatch(b_pattern,s) end -end -lpdf.tosixteen = tosixteen -lpdf.toeight = toeight -lpdf.topdfdoc = topdfdoc -lpdf.fromsixteen = fromsixteen -lpdf.frompdfdoc = frompdfdoc - -local function merge_t(a,b) - local t = { } - for k,v in next, a do t[k] = v end - for k,v in next, b do t[k] = v end - return setmetatable(t,getmetatable(a)) -end + lpdf.tosixteen = tosixteen + lpdf.toeight = toeight + lpdf.topdfdoc = topdfdoc + lpdf.fromsixteen = fromsixteen + lpdf.fromeight = fromeight + lpdf.frompdfdoc = frompdfdoc -local f_key_null = formatters["/%s null"] -local f_key_value = formatters["/%s %s"] -local f_key_dictionary = formatters["/%s << % t >>"] -local f_dictionary = formatters["<< % t >>"] -local f_key_array = formatters["/%s [ % t ]"] -local f_array = formatters["[ % t ]"] -local f_key_number = formatters["/%s %F"] -local f_tonumber = formatters["%F"] +end local tostring_a, tostring_d -tostring_d = function(t,contentonly,key) - if next(t) then - local r, n = { }, 0 - for k in next, t do - n = n + 1 - r[n] = k - end - sort(r) - for i=1,n do - local k = r[i] - local v = t[k] - local tv = type(v) - if tv == "string" then - r[i] = f_key_value(k,toeight(v)) - elseif tv == "number" then - r[i] = f_key_number(k,v) - -- elseif tv == "unicode" then -- can't happen - -- r[i] = f_key_value(k,tosixteen(v)) - elseif tv == "table" then - local mv = getmetatable(v) - if mv and mv.__lpdftype then - -- if v == t then - -- report_objects("ignoring circular reference in dirctionary") - -- r[i] = f_key_null(k) - -- else - r[i] = f_key_value(k,tostring(v)) - -- end - elseif v[1] then - r[i] = f_key_value(k,tostring_a(v)) +do + + local f_key_null = formatters["/%s null"] + local f_key_value = formatters["/%s %s"] + local f_key_dictionary = formatters["/%s << % t >>"] + local f_dictionary = formatters["<< % t >>"] + local f_key_array = formatters["/%s [ % t ]"] + local f_array = formatters["[ % t ]"] + local f_key_number = formatters["/%s %N"] -- always with max 9 digits and integer is possible + local f_tonumber = formatters["%N"] -- always with max 9 digits and integer is possible + + tostring_d = function(t,contentonly,key) + if next(t) then + local r = { } + local n = 0 + local e + for k, v in next, t do + if k == "__extra__" then + e = v + elseif k == "__stream__" then + -- do nothing (yet) else - r[i] = f_key_value(k,tostring_d(v)) + n = n + 1 + r[n] = k end + end + if n > 1 then + sort(r) + end + for i=1,n do + local k = r[i] + local v = t[k] + local tv = type(v) + -- mostly tables + if tv == "table" then + -- local mv = getmetatable(v) + -- if mv and mv.__lpdftype then + if v.__lpdftype__ then + -- if v == t then + -- report_objects("ignoring circular reference in dirctionary") + -- r[i] = f_key_null(k) + -- else + r[i] = f_key_value(k,tostring(v)) + -- end + elseif v[1] then + r[i] = f_key_value(k,tostring_a(v)) + else + r[i] = f_key_value(k,tostring_d(v)) + end + elseif tv == "string" then + r[i] = f_key_value(k,toeight(v)) + elseif tv == "number" then + r[i] = f_key_number(k,v) + else + r[i] = f_key_value(k,tostring(v)) + end + end + if e then + r[n+1] = e + end + if contentonly then + return concat(r," ") + elseif key then + return f_key_dictionary(key,r) else - r[i] = f_key_value(k,tostring(v)) + return f_dictionary(r) end - end - if contentonly then - return concat(r," ") - elseif key then - return f_key_dictionary(key,r) + elseif contentonly then + return "" else - return f_dictionary(r) + return "<< >>" end - elseif contentonly then - return "" - else - return "<< >>" end -end -tostring_a = function(t,contentonly,key) - local tn = #t - if tn ~= 0 then - local r = { } - for k=1,tn do - local v = t[k] - local tv = type(v) - if tv == "string" then - r[k] = toeight(v) - elseif tv == "number" then - r[k] = f_tonumber(v) - -- elseif tv == "unicode" then - -- r[k] = tosixteen(v) - elseif tv == "table" then - local mv = getmetatable(v) - local mt = mv and mv.__lpdftype - if mt then - -- if v == t then - -- report_objects("ignoring circular reference in array") - -- r[k] = "null" - -- else - r[k] = tostring(v) - -- end - elseif v[1] then - r[k] = tostring_a(v) + tostring_a = function(t,contentonly,key) + local tn = #t + if tn ~= 0 then + local r = { } + for k=1,tn do + local v = t[k] + local tv = type(v) + -- mostly numbers and tables + if tv == "number" then + r[k] = f_tonumber(v) + elseif tv == "table" then + -- local mv = getmetatable(v) + -- if mv and mv.__lpdftype then + if v.__lpdftype__ then + -- if v == t then + -- report_objects("ignoring circular reference in array") + -- r[k] = "null" + -- else + r[k] = tostring(v) + -- end + elseif v[1] then + r[k] = tostring_a(v) + else + r[k] = tostring_d(v) + end + elseif tv == "string" then + r[k] = toeight(v) else - r[k] = tostring_d(v) + r[k] = tostring(v) end + end + local e = t.__extra__ + if e then + r[tn+1] = e + end + if contentonly then + return concat(r, " ") + elseif key then + return f_key_array(key,r) else - r[k] = tostring(v) + return f_array(r) end - end - if contentonly then - return concat(r, " ") - elseif key then - return f_key_array(key,r) + elseif contentonly then + return "" else - return f_array(r) + return "[ ]" end - elseif contentonly then - return "" - else - return "[ ]" end + end +local f_tonumber = formatters["%N"] + local tostring_x = function(t) return concat(t," ") end local tostring_s = function(t) return toeight(t[1]) end local tostring_p = function(t) return topdfdoc(t[1],t[2]) end @@ -484,6 +588,17 @@ local tostring_v = function(t) end end +local tostring_l = function(t) + local s = t[1] + if not s or s == "" then + return "()" + elseif t[2] then + return "<" .. s .. ">" + else + return "(" .. s .. ")" + end +end + local function value_x(t) return t end local function value_s(t) return t[1] end local function value_p(t) return t[1] end @@ -495,24 +610,75 @@ local function value_a(t) return tostring_a(t,true) end local function value_z() return nil end local function value_t(t) return t.value or true end local function value_f(t) return t.value or false end -local function value_r() return t[1] or 0 end -- null -local function value_v() return t[1] end +local function value_r(t) return t[1] or 0 end -- null +local function value_v(t) return t[1] end +local function value_l(t) return t[1] end + +local function add_to_d(t,v) + local k = type(v) + if k == "string" then + if t.__extra__ then + t.__extra__ = t.__extra__ .. " " .. v + else + t.__extra__ = v + end + elseif k == "table" then + for k, v in next, v do + t[k] = v + end + end + return t +end + +local function add_to_a(t,v) + local k = type(v) + if k == "string" then + if t.__extra__ then + t.__extra__ = t.__extra__ .. " " .. v + else + t.__extra__ = v + end + elseif k == "table" then + local n = #t + for i=1,#v do + n = n + 1 + t[n] = v[i] + end + end + return t +end local function add_x(t,k,v) rawset(t,k,tostring(v)) end -local mt_x = { __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x } -local mt_d = { __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d } -local mt_a = { __lpdftype = "array", __tostring = tostring_a, __call = value_a } -local mt_u = { __lpdftype = "unicode", __tostring = tostring_u, __call = value_u } -local mt_s = { __lpdftype = "string", __tostring = tostring_s, __call = value_s } -local mt_p = { __lpdftype = "docstring", __tostring = tostring_p, __call = value_p } -local mt_n = { __lpdftype = "number", __tostring = tostring_n, __call = value_n } -local mt_c = { __lpdftype = "constant", __tostring = tostring_c, __call = value_c } -local mt_z = { __lpdftype = "null", __tostring = tostring_z, __call = value_z } -local mt_t = { __lpdftype = "true", __tostring = tostring_t, __call = value_t } -local mt_f = { __lpdftype = "false", __tostring = tostring_f, __call = value_f } -local mt_r = { __lpdftype = "reference", __tostring = tostring_r, __call = value_r } -local mt_v = { __lpdftype = "verbose", __tostring = tostring_v, __call = value_v } +-- local mt_x = { __index = { __lpdftype__ = "stream" }, __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x } +-- local mt_d = { __index = { __lpdftype__ = "dictionary" }, __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d, __add = add_to_d } +-- local mt_a = { __index = { __lpdftype__ = "array" }, __lpdftype = "array", __tostring = tostring_a, __call = value_a, __add = add_to_a } +-- local mt_u = { __index = { __lpdftype__ = "unicode" }, __lpdftype = "unicode", __tostring = tostring_u, __call = value_u } +-- local mt_s = { __index = { __lpdftype__ = "string" }, __lpdftype = "string", __tostring = tostring_s, __call = value_s } +-- local mt_p = { __index = { __lpdftype__ = "docstring" }, __lpdftype = "docstring", __tostring = tostring_p, __call = value_p } +-- local mt_n = { __index = { __lpdftype__ = "number" }, __lpdftype = "number", __tostring = tostring_n, __call = value_n } +-- local mt_c = { __index = { __lpdftype__ = "constant" }, __lpdftype = "constant", __tostring = tostring_c, __call = value_c } +-- local mt_z = { __index = { __lpdftype__ = "null" }, __lpdftype = "null", __tostring = tostring_z, __call = value_z } +-- local mt_t = { __index = { __lpdftype__ = "true" }, __lpdftype = "true", __tostring = tostring_t, __call = value_t } +-- local mt_f = { __index = { __lpdftype__ = "false" }, __lpdftype = "false", __tostring = tostring_f, __call = value_f } +-- local mt_r = { __index = { __lpdftype__ = "reference" }, __lpdftype = "reference", __tostring = tostring_r, __call = value_r } +-- local mt_v = { __index = { __lpdftype__ = "verbose" }, __lpdftype = "verbose", __tostring = tostring_v, __call = value_v } +-- local mt_l = { __index = { __lpdftype__ = "literal" }, __lpdftype = "literal", __tostring = tostring_l, __call = value_l } + +local mt_x = { __index = { __lpdftype__ = "stream" }, __tostring = tostring_x, __call = value_x, __newindex = add_x } +local mt_d = { __index = { __lpdftype__ = "dictionary" }, __tostring = tostring_d, __call = value_d, __add = add_to_d } +local mt_a = { __index = { __lpdftype__ = "array" }, __tostring = tostring_a, __call = value_a, __add = add_to_a } +local mt_u = { __index = { __lpdftype__ = "unicode" }, __tostring = tostring_u, __call = value_u } +local mt_s = { __index = { __lpdftype__ = "string" }, __tostring = tostring_s, __call = value_s } +local mt_p = { __index = { __lpdftype__ = "docstring" }, __tostring = tostring_p, __call = value_p } +local mt_n = { __index = { __lpdftype__ = "number" }, __tostring = tostring_n, __call = value_n } +local mt_c = { __index = { __lpdftype__ = "constant" }, __tostring = tostring_c, __call = value_c } +local mt_z = { __index = { __lpdftype__ = "null" }, __tostring = tostring_z, __call = value_z } +local mt_t = { __index = { __lpdftype__ = "true" }, __tostring = tostring_t, __call = value_t } +local mt_f = { __index = { __lpdftype__ = "false" }, __tostring = tostring_f, __call = value_f } +local mt_r = { __index = { __lpdftype__ = "reference" }, __tostring = tostring_r, __call = value_r } +local mt_v = { __index = { __lpdftype__ = "verbose" }, __tostring = tostring_v, __call = value_v } +local mt_l = { __index = { __lpdftype__ = "literal" }, __tostring = tostring_l, __call = value_l } local function pdfstream(t) -- we need to add attributes if t then @@ -522,9 +688,9 @@ local function pdfstream(t) -- we need to add attributes t[i] = tostring(t[i]) end elseif tt == "string" then - t= { t } + t = { t } else - t= { tostring(t) } + t = { tostring(t) } end end return setmetatable(t or { },mt_x) @@ -554,46 +720,70 @@ local function pdfunicode(str,default) return setmetatable({ str or default or "" },mt_u) -- could be a string end -local cache = { } -- can be weak - -local function pdfnumber(n,default) -- 0-10 - n = n or default - local c = cache[n] - if not c then - c = setmetatable({ n },mt_n) - -- cache[n] = c -- too many numbers - end - return c +local function pdfliteral(str,hex) -- can also produce a hex <> instead of () literal + return setmetatable({ str, hex },mt_l) end -for i=-1,9 do cache[i] = pdfnumber(i) end +local pdfnumber, pdfconstant -local cache = { } -- can be weak +do -local forbidden, replacements = "\0\t\n\r\f ()[]{}/%%#\\", { } -- table faster than function + local cache = { } -- can be weak -for s in gmatch(forbidden,".") do - replacements[s] = format("#%02x",byte(s)) -end + pdfnumber = function(n,default) -- 0-10 + if not n then + n = default + end + local c = cache[n] + if not c then + c = setmetatable({ n },mt_n) + -- cache[n] = c -- too many numbers + end + return c + end + + for i=-1,9 do cache[i] = pdfnumber(i) end + + local replacer = S("\0\t\n\r\f ()[]{}/%%#\\") / { + ["\00"]="#00", + ["\09"]="#09", + ["\10"]="#0a", + ["\12"]="#0c", + ["\13"]="#0d", + [ " " ]="#20", + [ "#" ]="#23", + [ "%" ]="#25", + [ "(" ]="#28", + [ ")" ]="#29", + [ "/" ]="#2f", + [ "[" ]="#5b", + [ "\\"]="#5c", + [ "]" ]="#5d", + [ "{" ]="#7b", + [ "}" ]="#7d", + } + P(1) + + local escaped = Cs(Cc("/") * replacer^0) + + local cache = table.setmetatableindex(function(t,k) + local v = setmetatable({ lpegmatch(escaped,k) }, mt_c) + t[k] = v + return v + end) + + pdfconstant = function(str,default) + if not str then + str = default or "none" + end + return cache[str] + end -local escaped = Cs(Cc("/") * (S(forbidden)/replacements + P(1))^0) + local escaped = Cs(replacer^0) -local function pdfconstant(str,default) - str = str or default or "" - local c = cache[str] - if not c then - -- c = setmetatable({ "/" .. str },mt_c) - c = setmetatable({ lpegmatch(escaped,str) },mt_c) - cache[str] = c + function lpdf.escaped(str) + return lpegmatch(escaped,str) or str end - return c -end -local escaped = Cs((S(forbidden)/replacements + P(1))^0) ------ escaped = Cs((1-forbidden)^0 * S(forbidden)/replacements * ((S(forbidden)/replacements + P(1))^0) - -function lpdf.escaped(str) - return lpegmatch(escaped,str) or str end local pdfnull, pdfboolean, pdfreference, pdfverbose @@ -657,6 +847,7 @@ lpdf.null = pdfnull lpdf.boolean = pdfboolean lpdf.reference = pdfreference lpdf.verbose = pdfverbose +lpdf.literal = pdfliteral local names, cache = { }, { } @@ -673,13 +864,7 @@ function lpdf.reserveobject(name) return r end --- lpdf.reserveobject = pdfreserveobject --- lpdf.immediateobject = pdfimmediateobject --- lpdf.deferredobject = pdfdeferredobject --- lpdf.referenceobject = pdfreferenceobject - -local pagereference = pdf.pageref -- tex.pdfpageref is obsolete -local nofpages = 0 +local nofpages = 0 function lpdf.pagereference(n) if nofpages == 0 then @@ -689,12 +874,24 @@ function lpdf.pagereference(n) end end if n > nofpages then - return pagereference(nofpages) -- or 1, could be configureable + return pdfgetpagereference(nofpages) -- or 1, could be configureable else - return pagereference(n) + return pdfgetpagereference(n) end end +function lpdf.nofpages() + return structures.pages.nofpages +end + +function lpdf.obj(...) + pdfdeferredobject(...) +end + +function lpdf.immediateobj(...) + pdfimmediateobject(...) +end + function lpdf.delayedobject(data,n) if n then pdfdeferredobject(n,data) @@ -733,14 +930,22 @@ function lpdf.flushobject(name,data) end end - -function lpdf.flushstreamobject(data,dict,compressed) -- default compressed +function lpdf.flushstreamobject(data,dict,compressed,objnum) -- default compressed if trace_objects then report_objects("flushing stream object of %s bytes",#data) end - local dtype = type(dict) + local dtype = type(dict) + local kind = compressed == "raw" and "raw" or "stream" + local nolength = nil + if compressed == "raw" then + compressed = nil + nolength = true + -- data = string.formatters["<< %s >>stream\n%s\nendstream"](attr,data) + end return pdfdeferredobject { + objnum = objnum, immediate = true, + nolength = nolength, compresslevel = compressed == false and 0 or nil, type = "stream", string = data, @@ -748,12 +953,13 @@ function lpdf.flushstreamobject(data,dict,compressed) -- default compressed } end -function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed +function lpdf.flushstreamfileobject(filename,dict,compressed,objnum) -- default compressed if trace_objects then report_objects("flushing stream file object %a",filename) end local dtype = type(dict) return pdfdeferredobject { + objnum = objnum, immediate = true, compresslevel = compressed == false and 0 or nil, type = "stream", @@ -810,6 +1016,14 @@ local function resetpageproperties() pagesattributes = pdfdictionary() end +function lpdf.getpageproperties() + return { + pageresources = pageresources, + pageattributes = pageattributes, + pagesattributes = pagesattributes, + } +end + resetpageproperties() local function setpageproperties() @@ -882,37 +1096,28 @@ function lpdf.finalizedocument() if not environment.initex then run(documentfinalizers,"document") function lpdf.finalizedocument() - report_finalizing("serious error: the document is finalized multiple times") + -- report_finalizing("serious error: the document is finalized multiple times") function lpdf.finalizedocument() end end end end --- codeinjections.finalizepage = lpdf.finalizepage -- no longer triggered at the tex end - -if not callbacks.register("finish_pdfpage", lpdf.finalizepage) then - - local find_tail = nodes.tail - local latelua_node = nodes.pool.latelua - - function nodeinjections.finalizepage(head) - local t = find_tail(head.list) - if t then - local n = latelua_node("lpdf.finalizepage(true)") -- last in the shipout - t.next = n - n.prev = t - end - return head, true - end - - nodes.tasks.appendaction("shipouts","normalizers","backends.pdf.nodeinjections.finalizepage") +callbacks.register("finish_pdfpage", lpdf.finalizepage) +callbacks.register("finish_pdffile", lpdf.finalizedocument) -end +do -callbacks.register("finish_pdffile", lpdf.finalizedocument) + local pdfsetinfo, pdfsetcatalog, pdfsettrailerid -- pdfsetnames pdfsettrailer + updaters.register("backend.update.lpdf",function() + pdfsetinfo = pdf.setinfo + pdfsetcatalog = pdf.setcatalog + pdfsettrailerid = pdf.settrailerid + end) -do + function lpdf.settrailerid(id) + pdfsettrailerid(id) + end -- some minimal tracing, handy for checking the order @@ -934,18 +1139,16 @@ do local info = pdfdictionary { Type = pdfconstant("Info") } -- nicer, but when we assign we nil the Type ----- names = pdfdictionary { Type = pdfconstant("Names") } -- nicer, but when we assign we nil the Type - local function flushcatalog() + local function checkcatalog() if not environment.initex then trace_flush("catalog") - catalog.Type = nil - pdfsetcatalog(catalog()) + return true end end - local function flushinfo() + local function checkinfo() if not environment.initex then trace_flush("info") - info.Type = nil if lpdf.majorversion() > 1 then for k, v in next, info do if k == "CreationDate" or k == "ModDate" then @@ -955,17 +1158,36 @@ do end end end + return true + end + end + + local function flushcatalog() + if checkcatalog() then + catalog.Type = nil + pdfsetcatalog(catalog()) + end + end + + local function flushinfo() + if checkinfo() then + info.Type = nil pdfsetinfo(info()) end end - -- local function flushnames() - -- if not environment.initex then - -- trace_flush("names") - -- names.Type = nil - -- pdfsetnames(names()) - -- end - -- end + function lpdf.getcatalog() + if checkcatalog() then + catalog.Type = pdfconstant("Catalog") + return pdfreference(pdfimmediateobject(tostring(catalog))) + end + end + + function lpdf.getinfo() + if checkinfo() then + return pdfreference(pdfimmediateobject(tostring(info))) + end + end function lpdf.addtocatalog(k,v) if not (lpdf.protectresources and catalog[k]) then @@ -1007,20 +1229,19 @@ do end end - local r_extgstates, d_extgstates = pdfreserveobject(), pdfdictionary() local p_extgstates = pdfreference(r_extgstates) - local r_colorspaces, d_colorspaces = pdfreserveobject(), pdfdictionary() local p_colorspaces = pdfreference(r_colorspaces) - local r_patterns, d_patterns = pdfreserveobject(), pdfdictionary() local p_patterns = pdfreference(r_patterns) - local r_shades, d_shades = pdfreserveobject(), pdfdictionary() local p_shades = pdfreference(r_shades) + local r_extgstates, r_colorspaces, r_patterns, r_shades + local d_extgstates, d_colorspaces, d_patterns, d_shades + local p_extgstates, p_colorspaces, p_patterns, p_shades - local function checkextgstates () if next(d_extgstates ) then addtopageresources("ExtGState", p_extgstates ) end end - local function checkcolorspaces() if next(d_colorspaces) then addtopageresources("ColorSpace",p_colorspaces) end end - local function checkpatterns () if next(d_patterns ) then addtopageresources("Pattern", p_patterns ) end end - local function checkshades () if next(d_shades ) then addtopageresources("Shading", p_shades ) end end + local function checkextgstates () if d_extgstates then addtopageresources("ExtGState", p_extgstates ) end end + local function checkcolorspaces() if d_colorspaces then addtopageresources("ColorSpace",p_colorspaces) end end + local function checkpatterns () if d_patterns then addtopageresources("Pattern", p_patterns ) end end + local function checkshades () if d_shades then addtopageresources("Shading", p_shades ) end end - local function flushextgstates () if next(d_extgstates ) then trace_flush("extgstates") pdfimmediateobject(r_extgstates, tostring(d_extgstates )) end end - local function flushcolorspaces() if next(d_colorspaces) then trace_flush("colorspaces") pdfimmediateobject(r_colorspaces,tostring(d_colorspaces)) end end - local function flushpatterns () if next(d_patterns ) then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end - local function flushshades () if next(d_shades ) then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end + local function flushextgstates () if d_extgstates then trace_flush("extgstates") pdfimmediateobject(r_extgstates, tostring(d_extgstates )) end end + local function flushcolorspaces() if d_colorspaces then trace_flush("colorspaces") pdfimmediateobject(r_colorspaces,tostring(d_colorspaces)) end end + local function flushpatterns () if d_patterns then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end + local function flushshades () if d_shades then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end -- patterns are special as they need resources to so we can get recursive references and in that case -- acrobat doesn't show anything (other viewers handle it well) @@ -1029,10 +1250,10 @@ do -- todo: force when not yet set function lpdf.collectedresources(options) - local ExtGState = next(d_extgstates ) and p_extgstates - local ColorSpace = next(d_colorspaces) and p_colorspaces - local Pattern = next(d_patterns ) and p_patterns - local Shading = next(d_shades ) and p_shades + local ExtGState = d_extgstates and next(d_extgstates ) and p_extgstates + local ColorSpace = d_colorspaces and next(d_colorspaces) and p_colorspaces + local Pattern = d_patterns and next(d_patterns ) and p_patterns + local Shading = d_shades and next(d_shades ) and p_shades if options and options.patterns == false then Pattern = nil end @@ -1042,18 +1263,56 @@ do ColorSpace = ColorSpace, Pattern = Pattern, Shading = Shading, - -- ProcSet = pdfarray { pdfconstant("PDF") }, } - return collected() + if options and options.serialize == false then + return collected + else + return collected() + end else - return "" + if options and options.serialize == false then + return pdfdictionary { } + else + return "" + end end end - function lpdf.adddocumentextgstate (k,v) d_extgstates [k] = v end - function lpdf.adddocumentcolorspace(k,v) d_colorspaces[k] = v end - function lpdf.adddocumentpattern (k,v) d_patterns [k] = v end - function lpdf.adddocumentshade (k,v) d_shades [k] = v end + function lpdf.adddocumentextgstate (k,v) + if not d_extgstates then + r_extgstates = pdfreserveobject() + d_extgstates = pdfdictionary() + p_extgstates = pdfreference(r_extgstates) + end + d_extgstates[k] = v + end + + function lpdf.adddocumentcolorspace(k,v) + if not d_colorspaces then + r_colorspaces = pdfreserveobject() + d_colorspaces = pdfdictionary() + p_colorspaces = pdfreference(r_colorspaces) + end + d_colorspaces[k] = v + end + + function lpdf.adddocumentpattern(k,v) + if not d_patterns then + r_patterns = pdfreserveobject() + d_patterns = pdfdictionary() + p_patterns = pdfreference(r_patterns) + end + d_patterns[k] = v + end + + function lpdf.adddocumentshade(k,v) + if not d_shades then + r_shades = pdfreserveobject() + d_shades = pdfdictionary() + p_shades = pdfreference(r_shades) + end + d_shades[k] = v + end registerdocumentfinalizer(flushextgstates,3,"extended graphic states") registerdocumentfinalizer(flushcolorspaces,3,"color spaces") @@ -1074,7 +1333,8 @@ end -- in strc-bkm: lpdf.registerdocumentfinalizer(function() structures.bookmarks.place() end,1) function lpdf.rotationcm(a) - local s, c = sind(a), cosd(a) + local s = sind(a) + local c = cosd(a) return format("%.6F %.6F %.6F %.6F 0 0 cm",c,s,-s,c) end @@ -1127,12 +1387,12 @@ do return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm) end - function lpdf.id(nodate) + function lpdf.id(date) local banner = environment.jobname or tex.jobname or "unknown" - if nodate then + if not date then return banner else - return format("%s.%s",banner,timestamp) + return format("%s | %s",banner,timestamp) end end @@ -1190,7 +1450,6 @@ function lpdf.checkedvalue(value,variant) -- code not shared end end end - -- return nil end function lpdf.limited(n,min,max,default) @@ -1210,61 +1469,6 @@ function lpdf.limited(n,min,max,default) end end --- if not pdfreferenceobject then --- --- local delayed = { } --- --- local function flush() --- local n = 0 --- for k,v in next, delayed do --- pdfimmediateobject(k,v) --- n = n + 1 --- end --- if trace_objects then --- report_objects("%s objects flushed",n) --- end --- delayed = { } --- end --- --- lpdf.registerdocumentfinalizer(flush,3,"objects") -- so we need a final flush too --- lpdf.registerpagefinalizer (flush,3,"objects") -- somehow this lags behind .. I need to look into that some day --- --- function lpdf.delayedobject(data) --- local n = pdfreserveobject() --- delayed[n] = data --- return n --- end --- --- end - --- setmetatable(pdf, { --- __index = function(t,k) --- if k == "info" then return pdf.getinfo() --- elseif k == "catalog" then return pdf.getcatalog() --- elseif k == "names" then return pdf.getnames() --- elseif k == "trailer" then return pdf.gettrailer() --- elseif k == "pageattribute" then return pdf.getpageattribute() --- elseif k == "pageattributes" then return pdf.getpageattributes() --- elseif k == "pageresources" then return pdf.getpageresources() --- elseif --- return nil --- end --- end, --- __newindex = function(t,k,v) --- if k == "info" then return pdf.setinfo(v) --- elseif k == "catalog" then return pdf.setcatalog(v) --- elseif k == "names" then return pdf.setnames(v) --- elseif k == "trailer" then return pdf.settrailer(v) --- elseif k == "pageattribute" then return pdf.setpageattribute(v) --- elseif k == "pageattributes" then return pdf.setpageattributes(v) --- elseif k == "pageresources" then return pdf.setpageresources(v) --- else --- rawset(t,k,v) --- end --- end, --- }) - - -- The next variant of ActualText is what Taco and I could come up with -- eventually. As of September 2013 Acrobat copies okay, Sumatra copies a -- question mark, pdftotext injects an extra space and Okular adds a @@ -1287,7 +1491,7 @@ do local f_actual_text = formatters["/Span <> BDC"] local context = context - local pdfdirect = nodes.pool.pdfdirectliteral + local pdfdirect = nodes.pool.directliteral -- we can use nuts.write deep down -- todo: use tounicode from the font mapper @@ -1383,11 +1587,9 @@ end function lpdf.copyarray(a) if a then local t = pdfarray() - local k = a.__kind for i=1,#a do t[i] = a(i) end --- inspect(t) return t end end @@ -1398,7 +1600,6 @@ function lpdf.copydictionary(d) for k, v in next, d do t[k] = d(k) end --- inspect(t) return t end end @@ -1420,3 +1621,73 @@ function lpdf.copystring(v) return pdfstring(v) end end + +do + + local pdfincludechar, pdfincludecharlist, pdfincludefont + local pdfgetfontname, pdfgetfontobjnum + local pdfsetmapfile, pdfsetmapline + + updaters.register("backend.update.lpdf",function() + pdfincludechar = pdf.includechar + pdfincludefont = pdf.includefont + pdfincludecharlist = pdf.includecharlist + pdfgetfontname = pdf.getfontname + pdfgetfontobjnum = pdf.getfontobjnum + pdfsetmapfile = pdf.mapfile + pdfsetmapline = pdf.mapline + end) + + function lpdf.includechar(f,c) pdfincludechar(f,c) end + function lpdf.includefont(...) pdfincludefont(...) end + + function lpdf.includecharlist(f,c) pdfincludecharlist(f,c) end -- can be disabled + + function lpdf.getfontname (id) return pdfgetfontname (id) end + function lpdf.getfontobjnumber(id) return pdfgetfontobjnum(id) end + + function lpdf.setmapfile(...) pdfsetmapfile(...) end + function lpdf.setmapline(...) pdfsetmapline(...) end + +end + +do + + -- This is obsolete but old viewers might still use it as directive + -- for what to send to a postscript printer. + + local a_procset, d_procset + + function lpdf.procset(dict) + if not a_procset then + a_procset = pdfarray { + pdfconstant("PDF"), + pdfconstant("Text"), + pdfconstant("ImageB"), + pdfconstant("ImageC"), + pdfconstant("ImageI"), + } + a_procset = pdfreference(pdfimmediateobject(tostring(a_procset))) + end + if dict then + if not d_procset then + d_procset = pdfdictionary { + ProcSet = a_procset + } + d_procset = pdfreference(pdfimmediateobject(tostring(d_procset))) + end + return d_procset + else + return a_procset + end + end + +end + +-- a left-over + +if environment.arguments.nocompression then + lpdf.setcompression(0,0,true) +end + + diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua index 6d1b09ca000..77f11918b46 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-mis.lua @@ -18,7 +18,6 @@ if not modules then modules = { } end modules ['lpdf-mis'] = { local next, tostring, type = next, tostring, type local format, gsub, formatters = string.format, string.gsub, string.formatters local flattened = table.flattened -local texset, texget = tex.set, tex.get local backends, lpdf, nodes = backends, lpdf, nodes @@ -30,7 +29,7 @@ local nuts = nodes.nuts local copy_node = nuts.copy local nodepool = nuts.pool -local pdfpageliteral = nodepool.pdfpageliteral +local pageliteral = nodepool.pageliteral local register = nodepool.register local pdfdictionary = lpdf.dictionary @@ -54,6 +53,8 @@ local addtonames = lpdf.addtonames local pdfgetmetadata = lpdf.getmetadata +local texset = tex.set + local variables = interfaces.variables local v_stop = variables.stop @@ -72,11 +73,18 @@ local v_page = variables.page local v_paper = variables.paper local v_attachment = variables.attachment local v_layer = variables.layer +local v_lefttoright = variables.lefttoright +local v_righttoleft = variables.righttoleft +local v_title = variables.title + +local positive = register(pageliteral("/GSpositive gs")) +local negative = register(pageliteral("/GSnegative gs")) +local overprint = register(pageliteral("/GSoverprint gs")) +local knockout = register(pageliteral("/GSknockout gs")) + +local omitextraboxes = false -local positive = register(pdfpageliteral("/GSpositive gs")) -local negative = register(pdfpageliteral("/GSnegative gs")) -local overprint = register(pdfpageliteral("/GSoverprint gs")) -local knockout = register(pdfpageliteral("/GSknockout gs")) +directives.register("backend.omitextraboxes", function(v) omitextraboxes = v end) local function initializenegative() local a = pdfarray { 0, 1 } @@ -86,7 +94,7 @@ local function initializenegative() Range = a, Domain = a, } - local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) } + local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) } -- can be shared local positive = pdfdictionary { Type = g, TR = pdfconstant("Identity") } adddocumentextgstate("GSnegative", pdfreference(pdfflushobject(negative))) adddocumentextgstate("GSpositive", pdfreference(pdfflushobject(positive))) @@ -230,6 +238,12 @@ local function setupidentity() addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x -- addtoinfo("ConTeXt.Version",version) + -- + local lmtx = codeinjections.lmtxmode() + if lmtx then + addtoinfo("ConTeXt.LMTX",formatters["%0.2f"](lmtx)) + end + -- addtoinfo("ConTeXt.Time",os.date("%Y-%m-%d %H:%M")) addtoinfo("ConTeXt.Jobname",jobname) addtoinfo("ConTeXt.Url","www.pragma-ade.com") @@ -254,7 +268,9 @@ local function flushjavascripts() local a = pdfarray() local pdf_javascript = pdfconstant("JavaScript") for i=1,#t do - local name, script = t[i][1], t[i][2] + local ti = t[i] + local name = ti[1] + local script = ti[2] local j = pdfdictionary { S = pdf_javascript, JS = pdfreference(pdfflushstreamobject(script)), @@ -304,14 +320,26 @@ local plusspecs = { [v_paper] = { paper = true, }, + [v_title] ={ + title = true, + }, + [v_lefttoright] ={ + direction = "L2R", + }, + [v_righttoleft] ={ + direction = "R2R", + }, } local pagespecs = { -- - [v_max] = plusspecs[v_max], - [v_bookmark] = plusspecs[v_bookmark], - [v_attachment] = plusspecs[v_attachment], - [v_layer] = plusspecs[v_layer], + [v_max] = plusspecs[v_max], + [v_bookmark] = plusspecs[v_bookmark], + [v_attachment] = plusspecs[v_attachment], + [v_layer] = plusspecs[v_layer], + [v_lefttoright] = plusspecs[v_lefttoright], + [v_righttoleft] = plusspecs[v_righttoleft], + [v_title] = plusspecs[v_title], -- [v_none] = { }, @@ -372,21 +400,23 @@ local cropoffset, bleedoffset, trimoffset, artoffset = 0, 0, 0, 0 local marked = false local copies = false +local getpagedimensions getpagedimensions = function() + getpagedimensions = backends.codeinjections.getpagedimensions + return getpagedimensions() +end + function codeinjections.setupcanvas(specification) local paperheight = specification.paperheight local paperwidth = specification.paperwidth local paperdouble = specification.doublesided - if paperheight then - texset('global','pageheight',paperheight) - end - if paperwidth then - texset('global','pagewidth',paperwidth) - end + -- + paperwidth, paperheight = codeinjections.setpagedimensions(paperwidth,paperheight) + -- pagespec = specification.mode or pagespec topoffset = specification.topoffset or 0 leftoffset = specification.leftoffset or 0 - height = specification.height or texget("pageheight") - width = specification.width or texget("pagewidth") + height = specification.height or paperheight + width = specification.width or paperwidth marked = specification.print -- copies = specification.copies @@ -433,13 +463,15 @@ local function documentspecification() end end end - -- - local layout = spec.layout - local mode = spec.mode - local fit = spec.fit - local fixed = spec.fixed - local duplex = spec.duplex - local paper = spec.paper + -- maybe interfaces.variables + local layout = spec.layout + local mode = spec.mode + local fit = spec.fit + local fixed = spec.fixed + local duplex = spec.duplex + local paper = spec.paper + local title = spec.title + local direction = spec.direction if layout then addtocatalog("PageLayout",pdfconstant(layout)) end @@ -458,34 +490,42 @@ local function documentspecification() prints = pdfarray(flattened(pages.toranges(marked))) end end - if fit or fixed or duplex or copies or paper or prints then + if fit or fixed or duplex or copies or paper or prints or title or direction then addtocatalog("ViewerPreferences",pdfdictionary { - FitWindow = fit and true or nil, - PrintScaling = fixed and pdfconstant("None") or nil, - Duplex = duplex and pdfconstant(duplex) or nil, - NumCopies = copies and copies or nil, - PickTrayByPDFSize = paper and true or nil, - PrintPageRange = prints or nil, + FitWindow = fit and true or nil, + PrintScaling = fixed and pdfconstant("None") or nil, + Duplex = duplex and pdfconstant(duplex) or nil, + NumCopies = copies and copies or nil, + PickTrayByPDFSize = paper and true or nil, + PrintPageRange = prints or nil, + DisplayDocTitle = title and true or nil, + Direction = direction and pdfconstant(direction) or nil, }) end addtoinfo ("Trapped", pdfconstant("False")) -- '/Trapped' in /Info, 'Trapped' in XMP addtocatalog("Version", pdfconstant(format("1.%s",pdfminorversion()))) + addtocatalog("Lang", pdfstring(tokens.getters.macro("currentmainlanguage"))) end -- temp hack: the mediabox is not under our control and has a precision of 5 digits local factor = number.dimenfactors.bp -local f_value = formatters["%0.6F"] +local f_value = formatters["%.6F"] + +directives.register("pdf.stripzeros",function() + local f_value = formatters["%.6N"] +end) local function boxvalue(n) -- we could share them return pdfverbose(f_value(factor * n)) end local function pagespecification() + local paperwidth, paperheight = codeinjections.getpagedimensions() local llx = leftoffset - local lly = texget("pageheight") + topoffset - height + local lly = paperheight + topoffset - height local urx = width - leftoffset - local ury = texget("pageheight") - topoffset + local ury = paperheight - topoffset -- boxes can be cached local function extrabox(WhatBox,offset,always) if offset ~= 0 or always then @@ -497,10 +537,14 @@ local function pagespecification() }) end end - extrabox("CropBox",cropoffset,true) -- mandate for rendering - extrabox("TrimBox",trimoffset,true) -- mandate for pdf/x - extrabox("BleedBox",bleedoffset) -- optional - -- extrabox("ArtBox",artoffset) -- optional .. unclear what this is meant to do + if omitextraboxes then + -- only useful for testing / comparing + else + extrabox("CropBox",cropoffset,true) -- mandate for rendering + extrabox("TrimBox",trimoffset,true) -- mandate for pdf/x + extrabox("BleedBox",bleedoffset) -- optional + -- extrabox("ArtBox",artoffset) -- optional .. unclear what this is meant to do + end end lpdf.registerpagefinalizer(pagespecification,"page specification") diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua index e3c1778f27f..8bcf18c62ae 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua @@ -6,178 +6,84 @@ if not modules then modules = { } end modules ['lpdf-nod'] = { license = "see context related readme files" } -local type = type - -local formatters = string.formatters +if CONTEXTLMTXMODE > 1 then + return +end -local whatsitcodes = nodes.whatsitcodes -local nodeinjections = backends.nodeinjections +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes -local nuts = nodes.nuts -local tonut = nuts.tonut +local nodeinjections = backends.nodeinjections -local setfield = nuts.setfield +local nuts = nodes.nuts -local copy_node = nuts.copy -local new_node = nuts.new +local setfield = nuts.setfield +local setdata = nuts.setdata -local nodepool = nuts.pool -local register = nodepool.register +local copy_node = nuts.copy +local new_node = nuts.new -local literalvalues = nodes.literalvalues +local nodepool = nuts.pool +local register = nodepool.register -local pdforiginliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdforiginliteral,"mode",literalvalues.origin) -local pdfpageliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfpageliteral, "mode",literalvalues.page) -local pdfdirectliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfdirectliteral,"mode",literalvalues.direct) -local pdfrawliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfrawliteral, "mode",literalvalues.raw) +local whatsit_code = nodecodes.whatsit -local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave)) -local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore)) -local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix)) ------ pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched ------ pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot)) +local savewhatsit_code = whatsitcodes.save +local restorewhatsit_code = whatsitcodes.restore +local setmatrixwhatsit_code = whatsitcodes.setmatrix +local literalwhatsit_code = whatsitcodes.literal -local variables = interfaces.variables +local literalvalues = nodes.literalvalues +local originliteral_code = literalvalues.origin +local pageliteral_code = literalvalues.page +local directliteral_code = literalvalues.direct +local rawliteral_code = literalvalues.raw -function nodepool.pdforiginliteral(str) local t = copy_node(pdforiginliteral) setfield(t,"data",str) return t end -function nodepool.pdfpageliteral (str) local t = copy_node(pdfpageliteral ) setfield(t,"data",str) return t end -function nodepool.pdfdirectliteral(str) local t = copy_node(pdfdirectliteral) setfield(t,"data",str) return t end -function nodepool.pdfrawliteral (str) local t = copy_node(pdfrawliteral ) setfield(t,"data",str) return t end +local tomatrix = drivers.helpers.tomatrix -nodepool.pdfliteral = nodepool.pdfpageliteral -- best is to use a specific one: origin | page | direct | raw +local originliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(originliteralnode,"mode",originliteral_code) +local pageliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(pageliteralnode, "mode",pageliteral_code) +local directliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(directliteralnode,"mode",directliteral_code) +local rawliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(rawliteralnode, "mode",rawliteral_code) -function nodepool.pdfsave() - return copy_node(pdfsave) -end +function nodepool.originliteral(str) local t = copy_node(originliteralnode) setdata(t,str) return t end +function nodepool.pageliteral (str) local t = copy_node(pageliteralnode ) setdata(t,str) return t end +function nodepool.directliteral(str) local t = copy_node(directliteralnode) setdata(t,str) return t end +function nodepool.rawliteral (str) local t = copy_node(rawliteralnode ) setdata(t,str) return t end -function nodepool.pdfrestore() - return copy_node(pdfrestore) -end +local literals = { + [originliteral_code] = originliteralnode, [literalvalues[originliteral_code]] = originliteralnode, + [pageliteral_code] = pageliteralnode, [literalvalues[pageliteral_code]] = pageliteralnode, + [directliteral_code] = directliteralnode, [literalvalues[directliteral_code]] = directliteralnode, + [rawliteral_code] = rawliteralnode, [literalvalues[rawliteral_code]] = rawliteralnode, +} -function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty - local t = copy_node(pdfsetmatrix) - if type(rx) == "string" then - setfield(t,"data",rx) +function nodepool.literal(mode,str) + if str then + local t = copy_node(literals[mode] or pageliteralnode) + setdata(t,str) + return t else - if not rx then - rx = 1 - elseif rx == 0 then - rx = 0.0001 - end - if not ry then - ry = 1 - elseif ry == 0 then - ry = 0.0001 - end - if not sx then - sx = 0 - end - if not sy then - sy = 0 - end - if sx == 0 and sy == 0 then - if rx == 1 and ry == 1 then - setfield(t,"data","1 0 0 1") - else - setfield(t,"data",formatters["%0.6F 0 0 %0.6F"](rx,ry)) - end - else - setfield(t,"data",formatters["%0.6F %0.6F %0.6F %0.6F"](rx,sx,sy,ry)) - end + local t = copy_node(pageliteralnode) + setdata(t,mode) + return t end - return t end -nodeinjections.save = nodepool.pdfsave -nodeinjections.restore = nodepool.pdfrestore -nodeinjections.transform = nodepool.pdfsetmatrix - --- the next one is implemented differently, using latelua - -function nodepool.pdfannotation(w,h,d,data,n) - report("don't use node based annotations!") - os.exit() - -- local t = copy_node(pdfannot) - -- if w and w ~= 0 then - -- setfield(t,"width",w) - -- end - -- if h and h ~= 0 then - -- setfield(t,"height",h) - -- end - -- if d and d ~= 0 then - -- setfield(t,"depth",d) - -- end - -- if n then - -- setfield(t,"objnum",n) - -- end - -- if data and data ~= "" then - -- setfield(t,"data",data) - -- end - -- return t +local savenode = register(new_node(whatsit_code, savewhatsit_code)) +local restorenode = register(new_node(whatsit_code, restorewhatsit_code)) +local setmatrixnode = register(new_node(whatsit_code, setmatrixwhatsit_code)) + +function nodepool.save() + return copy_node(savenode) end --- (!) The next code in pdfdest.w is wrong: --- --- case pdf_dest_xyz: --- if (matrixused()) { --- set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin) ; --- } else { --- pdf_ann_left(p) = pos.h ; --- pdf_ann_top (p) = pos.v ; --- } --- break ; --- --- so we need to force a matrix. - --- local views = { -- beware, we do support the pdf keys but this is *not* official --- xyz = 0, [variables.standard] = 0, --- fit = 1, [variables.fit] = 1, --- fith = 2, [variables.width] = 2, --- fitv = 3, [variables.height] = 3, --- fitb = 4, --- fitbh = 5, [variables.minwidth] = 5, --- fitbv = 6, [variables.minheight] = 6, --- fitr = 7, --- } - -function nodepool.pdfdestination(w,h,d,name,view,n) - report("don't use node based destinations!") - os.exit() - -- local t = copy_node(pdfdest) - -- local hasdimensions = false - -- if w and w ~= 0 then - -- setfield(t,"width",w) - -- hasdimensions = true - -- end - -- if h and h ~= 0 then - -- setfield(t,"height",h) - -- hasdimensions = true - -- end - -- if d and d ~= 0 then - -- setfield(t,"depth",d) - -- hasdimensions = true - -- end - -- if n then - -- setfield(t,"objnum",n) - -- end - -- view = views[view] or view or 1 -- fit is default - -- setfield(t,"dest_id",name) - -- setfield(t,"dest_type",view) - -- if hasdimensions and view == 0 then -- xyz - -- -- see (!) s -> m -> t -> r - -- -- linked - -- local s = copy_node(pdfsave) - -- local m = copy_node(pdfsetmatrix) - -- local r = copy_node(pdfrestore) - -- setfield(m,"data","1 0 0 1") - -- setfield(s,"next",m) - -- setfield(m,"next",t) - -- setfield(t,"next",r) - -- setfield(m,"prev",s) - -- setfield(t,"prev",m) - -- setfield(r,"prev",t) - -- return s -- a list - -- else - -- return t - -- end +function nodepool.restore() + return copy_node(restorenode) +end + +function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) + local t = copy_node(setmatrixnode) + setdata(t,tomatrix(rx,sx,sy,ry,tx,ty)) + return t end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml index efdfc4d7d43..2f07fed2def 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pda.xml @@ -30,6 +30,7 @@ + @@ -100,40 +101,76 @@ - external - Name of the ConTeXt job - ConTeXt.Jobname - Text + external + Name of the ConTeXt job + ConTeXt.Jobname + Text - external - Time stamp of ConTeXt version - ConTeXt.Time - Text + external + Time stamp of ConTeXt version + ConTeXt.Time + Text - external - ConTeXt website - ConTeXt.Url - Text + external + ConTeXt website + ConTeXt.Url + Text - external - ConTeXt version - ConTeXt.Version - Text + external + ConTeXt support + ConTeXt.Support + Text - external - Banner of pdftex or one of its successors - PTEX.Fullbanner - Text + external + ConTeXt version + ConTeXt.Version + Text - external - Document identifier - ID - Text + external + ConTeXt LMTX version + ConTeXt.LMTX + Text + + + external + TeX support + TeX.Support + Text + + + external + LuaTeX version + LuaTeX.Version + Text + + + external + LuaTeX functionality + LuaTeX.Functionality + Text + + + external + LuaTeX Lua version + LuaTeX.LuaVersion + Text + + + external + LuaTeX platform + LuaTeX.Platform + Text + + + external + Document identifier + ID + Text diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua new file mode 100644 index 00000000000..9d14f8f5e82 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua @@ -0,0 +1,1157 @@ +if not modules then modules = { } end modules ['lpdf-epd'] = { + version = 1.001, + comment = "companion to lpdf-epa.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", + history = "this one replaces the poppler/pdfe binding", +} + +-- \enabledirectives[graphics.pdf.uselua] +-- \enabledirectives[graphics.pdf.recompress] +-- \enabledirectives[graphics.pdf.stripmarked] + +-- maximum integer : +2^32 +-- maximum real : +2^15 +-- minimum real : 1/(2^16) + +-- get_flagged : does that still work + +-- ppdoc_permissions (ppdoc *pdf); + +-- PPSTRING_ENCODED 1 << 0 +-- PPSTRING_DECODED 1 << 1 +-- PPSTRING_EXEC 1 << 2 postscript only +-- PPSTRING_PLAIN 0 +-- PPSTRING_BASE16 1 << 3 +-- PPSTRING_BASE85 1 << 4 +-- PPSTRING_UTF16BE 1 << 5 +-- PPSTRING_UTF16LE 1 << 6 + +-- PPDOC_ALLOW_PRINT 1 << 2 printing +-- PPDOC_ALLOW_MODIFY 1 << 3 filling form fields, signing, creating template pages +-- PPDOC_ALLOW_COPY 1 << 4 copying, copying for accessibility +-- PPDOC_ALLOW_ANNOTS 1 << 5 filling form fields, copying, signing +-- PPDOC_ALLOW_EXTRACT 1 << 9 contents copying for accessibility +-- PPDOC_ALLOW_ASSEMBLY 1 << 10 no effect +-- PPDOC_ALLOW_PRINT_HIRES 1 << 11 no effect + +-- PPCRYPT_NONE 0 no encryption, go ahead +-- PPCRYPT_DONE 1 encryption present but password succeeded, go ahead +-- PPCRYPT_PASS -1 encryption present, need non-empty password +-- PPCRYPT_FAIL -2 invalid or unsupported encryption (eg. undocumented in pdf spec) + +local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next +local tostring, tonumber, unpack = tostring, tonumber, unpack +local char, byte, find = string.char, string.byte, string.find +local abs = math.abs +local concat, swapped, sortedhash, sortedkeys = table.concat, table.swapped, table.sortedhash, table.sortedkeys +local utfchar = string.char +local setmetatableindex = table.setmetatableindex + +local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local P, C, S, R, Ct, Cc, V, Carg, Cs, Cf, Cg = lpeg.P, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cc, lpeg.V, lpeg.Carg, lpeg.Cs, lpeg.Cf, lpeg.Cg + +if not lpdf then + require("lpdf-aux") +end + +if not (number and number.dimenfactors) then + require("util-dim") +end + +local epdf = pdfe + lpdf = lpdf or { } +local lpdf = lpdf +local lpdf_epdf = { } +lpdf.epdf = lpdf_epdf + +local openPDF = epdf.open +local newPDF = epdf.new +local closePDF = epdf.close + +local getcatalog = epdf.getcatalog +local getinfo = epdf.getinfo +local gettrailer = epdf.gettrailer +local getnofpages = epdf.getnofpages +local getversion = epdf.getversion +local getbox = epdf.getbox +local getstatus = epdf.getstatus +local unencrypt = epdf.unencrypt + +local dictionarytotable = epdf.dictionarytotable +local arraytotable = epdf.arraytotable +local pagestotable = epdf.pagestotable +local readwholestream = epdf.readwholestream + +local getfromreference = pdfe.getfromreference + +local report_epdf = logs.reporter("epdf") + +local allocate = utilities.storage.allocate + +local bpfactor = number.dimenfactors.bp + +local objectcodes = { [0] = + "none", + "null", + "bool", + "integer", + "number", + "name", + "string", + "array", + "dictionary", + "stream", + "reference", +} + +local encryptioncodes = { + [0] = "notencrypted", + [1] = "unencrypted", + [-1] = "protected", + [-2] = "failure", +} + +objectcodes = allocate(swapped(objectcodes,objectcodes)) +encryptioncodes = allocate(swapped(encryptioncodes,encryptioncodes)) + +pdfe.objectcodes = objectcodes +pdfe.encryptioncodes = encryptioncodes + +local null_object_code = objectcodes.null +local reference_object_code = objectcodes.reference + +local none_object_code = objectcodes.none +local null_object_code = objectcodes.null +local bool_object_code = objectcodes.bool +local integer_object_code = objectcodes.integer +local number_object_code = objectcodes.number +local name_object_code = objectcodes.name +local string_object_code = objectcodes.string +local array_object_code = objectcodes.array +local dictionary_object_code = objectcodes.dictionary +local stream_object_code = objectcodes.stream +local reference_object_code = objectcodes.reference + +local checked_access +local get_flagged -- from pdfe -> lpdf + +if lpdf.dictionary then + + -- we're in context + + local pdfdictionary = lpdf.dictionary + local pdfarray = lpdf.array + local pdfconstant = lpdf.constant + local pdfstring = lpdf.string + local pdfunicode = lpdf.unicode + + get_flagged = function(t,f,k) + local tk = t[k] -- triggers resolve + local fk = f[k] + if not fk then + return tk + elseif fk == "name" then + return pdfconstant(tk) + elseif fk == "array" then + return pdfarray(tk) + elseif fk == "dictionary" then + return pdfarray(tk) + elseif fk == "rawtext" then + return pdfstring(tk) + elseif fk == "unicode" then + return pdfunicode(tk) + else + return tk + end + end + +else + + get_flagged = function(t,f,k) + return t[k] + end + +end + +-- We need to convert the string from utf16 although there is no way to +-- check if we have a regular string starting with a bom. So, we have +-- na dilemma here: a pdf doc encoded string can be invalid utf. + +-- : implicit 0 appended if odd +-- (byte encoded) : \( \) \\ escaped +-- +-- : utf16be +-- +-- \r \r \t \b \f \( \) \\ \NNN and \ : append next line +-- +-- the getString function gives back bytes so we don't need to worry about +-- the hex aspect. + +local some_dictionary +local some_array +local some_stream +local some_reference + +local some_string = lpdf.frombytes + +local function get_value(document,t,key) + if not key then + return + end + local value = t[key] + if not value then + return + end + if type(value) ~= "table" then + return value + end + -- we can assume names to be simple and strings to be tables + local kind = value[1] + if kind == name_object_code then + return value[2] + elseif kind == string_object_code then + return some_string(value[2],value[3]) + elseif kind == array_object_code then + return some_array(value[2],document) + elseif kind == dictionary_object_code then + return some_dictionary(value[2],document) + elseif kind == stream_object_code then + return some_stream(value,document) + elseif kind == reference_object_code then + return some_reference(value,document) + end + return value +end + +some_dictionary = function (d,document) + local f = dictionarytotable(d,true) + local t = setmetatable({ __raw__ = f, __type__ = dictionary_object_code }, { + __index = function(t,k) + return get_value(document,f,k) + end, + __call = function(t,k) + return get_flagged(t,f,k) + end, + } ) + return t, "dictionary" +end + +some_array = function (a,document) + local f = arraytotable(a,true) + local n = #f + local t = setmetatable({ __raw__ = f, __type__ = array_object_code, n = n }, { + __index = function(t,k) + return get_value(document,f,k) + end, + __call = function(t,k) + return get_flagged(t,f,k) + end, + __len = function(t,k) + return n + end, + } ) + return t, "array" +end + +some_stream = function(s,d,document) + local f = dictionarytotable(d,true) + local t = setmetatable({ __raw__ = f, __type__ = stream_object_code }, { + __index = function(t,k) + return get_value(document,f,k) + end, + __call = function(t,raw) + if raw == false then + return readwholestream(s,false) -- original + else + return readwholestream(s,true) -- uncompressed + end + end, + } ) + return t, "stream" +end + +some_reference = function(r,document) + local objnum = r[3] + local cached = document.__cache__[objnum] + if not cached then + local kind, object, b, c = getfromreference(r[2]) + if kind == dictionary_object_code then + cached = some_dictionary(object,document) + elseif kind == array_object_code then + cached = some_array(object,document) + elseif kind == stream_object_code then + cached = some_stream(object,b,document) + else + cached = { kind, object, b, c } + -- really cache this? + end + document.__cache__[objnum] = cached + document.__xrefs__[cached] = objnum + end + return cached +end + +local resolvers = { } +lpdf_epdf.resolvers = resolvers + +local function resolve(document,k) + local resolver = resolvers[k] + if resolver then + local entry = resolver(document) + document[k] = entry + return entry + end +end + +local function getnames(document,n,target) -- direct + if n then + local Names = n.Names + if Names then + if not target then + target = { } + end + for i=1,#Names,2 do + target[Names[i]] = Names[i+1] + end + else + local Kids = n.Kids + if Kids then + for i=1,#Kids do + target = getnames(document,Kids[i],target) + end + end + end + return target + end +end + +local function getkids(document,n,target) -- direct + if n then + local Kids = n.Kids + if Kids then + for i=1,#Kids do + target = getkids(document,Kids[i],target) + end + elseif target then + target[#target+1] = n + else + target = { n } + end + return target + end +end + +function resolvers.destinations(document) + local Names = document.Catalog.Names + return getnames(document,Names and Names.Dests) +end + +function resolvers.javascripts(document) + local Names = document.Catalog.Names + return getnames(document,Names and Names.JavaScript) +end + +function resolvers.widgets(document) + local Names = document.Catalog.AcroForm + return Names and Names.Fields +end + +function resolvers.embeddedfiles(document) + local Names = document.Catalog.Names + return getnames(document,Names and Names.EmbeddedFiles) +end + +-- /OCProperties << +-- /OCGs [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] +-- /D << +-- /Order [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] +-- /ON [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] +-- /OFF [ ] +-- >> +-- >> + +function resolvers.layers(document) + local properties = document.Catalog.OCProperties + if properties then + local layers = properties.OCGs + if layers then + local t = { } + for i=1,#layers do + local layer = layers[i] + t[i] = layer.Name + end + -- t.n = n + return t + end + end +end + +function resolvers.structure(document) + -- this might become a tree + return document.Catalog.StructTreeRoot +end + +function resolvers.pages(document) + local __data__ = document.__data__ + local __xrefs__ = document.__xrefs__ + local __cache__ = document.__cache__ + -- + local nofpages = document.nofpages + local pages = { } + local rawpages = pagestotable(__data__) + document.pages = pages + -- + for pagenumber=1,nofpages do + local rawpagedata = rawpages[pagenumber] + local pagereference = rawpagedata[3] + local pageobject = rawpagedata[1] + local pagedata = some_dictionary(pageobject,document) + if pagedata and pageobject then + pagedata.number = pagenumber + pagedata.MediaBox = getbox(pageobject,"MediaBox") + pagedata.CropBox = getbox(pageobject,"CropBox") + pagedata.BleedBox = getbox(pageobject,"BleedBox") + pagedata.ArtBox = getbox(pageobject,"ArtBox") + pagedata.TrimBox = getbox(pageobject,"TrimBox") + pages[pagenumber] = pagedata + __xrefs__[pagedata] = pagereference + __cache__[pagereference] = pagedata + else + report_epdf("missing pagedata for page %i",i) + end + end + -- + -- pages.n = nofpages + -- + return pages +end + +local loaded = { } +local nofloaded = 0 + +function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring) + local document = loaded[filename] + if not document then + statistics.starttiming(lpdf_epdf) + local __data__ + if fromstring then + __data__ = newPDF(filename,#filename) + else + __data__ = openPDF(filename) + end + if __data__ then + if userpassword and getstatus(__data__) < 0 then + unencrypt(__data__,userpassword,nil) + end + if ownerpassword and getstatus(__data__) < 0 then + unencrypt(__data__,nil,ownerpassword) + end + if getstatus(__data__) < 0 then + report_epdf("the document is encrypted, provide proper passwords",getstatus(__data__)) + __data__ = false + end + if __data__ then + document = { + filename = filename, + __cache__ = { }, + __xrefs__ = { }, + __fonts__ = { }, + __copied__ = { }, + __data__ = __data__, + } + document.Catalog = some_dictionary(getcatalog(__data__),document) + document.Info = some_dictionary(getinfo(__data__),document) + document.Trailer = some_dictionary(gettrailer(__data__),document) + -- + setmetatableindex(document,resolve) + -- + document.majorversion, document.minorversion = getversion(__data__) + -- + document.nofpages = getnofpages(__data__) + else + document = false + end + else + document = false + end + loaded[filename] = document + loaded[document] = document + statistics.stoptiming(lpdf_epdf) + -- print(statistics.elapsedtime(lpdf_epdf)) + end + return document or nil +end + +function lpdf_epdf.unload(filename) + if type(filename) == "table" then + filename = filename.filename + end + if type(filename) == "string" then + local document = loaded[filename] + if document then +-- report_epdf("%04i closed: %s",nofloaded,filename) +-- nofloaded = nofloaded - 1 + loaded[document] = nil + loaded[filename] = nil + end + end +end + +-- for k, v in expanded(t) do + +local function expanded(t) + local function iterator(raw,k) + local k, v = next(raw,k) + if v then + return k, t[k] + end + end + return iterator, t.__raw__, nil +end + +---------.expand = expand +lpdf_epdf.expanded = expanded + +-- we could resolve the text stream in one pass if we directly handle the +-- font but why should we complicate things + +local spaces = lpegpatterns.whitespace^1 +local optspaces = lpegpatterns.whitespace^0 +local numchar = P("\\")/"" * (R("09")^3/function(s) return char(tonumber(s,8)) end) + + P("\\") * P(1) +local key = P("/") * C(R("AZ","az","09","__")^1) +local number = Ct(Cc("number") * (lpegpatterns.number/tonumber)) +local keyword = Ct(Cc("name") * key) +local operator = C((R("AZ","az")+P("*")+P("'")+P('"'))^1) + +local grammar = P { "start", + start = (keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces)^1, + keyvalue = key * optspaces * V("start"), + array = Ct(Cc("array") * P("[") * Ct(V("start")^1) * P("]")), + dictionary = Ct(Cc("dict") * P("<<") * Ct(V("keyvalue")^1) * P(">>")), + hexstring = Ct(Cc("hex") * P("<") * Cs(( 1-P(">"))^1) * P(">")), + decstring = Ct(Cc("dec") * P("(") * Cs((numchar+1-(P")"))^1) * P(")")), -- untested +} + +local operation = Ct(grammar^1 * operator) +local parser = Ct((operation + P(1))^1) + +-- todo: speed this one up + +local numchar = P("\\") * (R("09")^3 + P(1)) +local number = lpegpatterns.number +local keyword = P("/") * R("AZ","az","09","__")^1 +local operator = (R("AZ","az")+P("*")+P("'")+P('"'))^1 + +local skipstart = P("BDC") + P("BMC") + P("DP") + P("MP") +local skipstop = P("EMC") +local skipkeep = P("/ActualText") + +local grammar = P { "skip", + start = keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces, + keyvalue = optspaces * (keyword * optspaces * V("start") * optspaces)^1, + xeyvalue = optspaces * ((keyword - skipkeep) * optspaces * V("start") * optspaces)^1, + array = P("[") * V("start")^0 * P("]"), + dictionary = P("<<") * V("keyvalue")^0 * P(">>"), + xictionary = P("<<") * V("xeyvalue")^0 * P(">>"), + hexstring = P("<") * ( 1-P(">"))^0 * P(">"), + decstring = P("(") * (numchar+1-(P")"))^0 * P(")"), + skip = (optspaces * ( keyword * optspaces * V("xictionary") * optspaces * skipstart + skipstop) / "") + + V("start") + + operator +} + +local stripper = Cs((grammar + P(1))^1) + +function lpdf_epdf.parsecontent(str) + return lpegmatch(parser,str) +end + +function lpdf_epdf.stripcontent(str) + if find(str,"EMC") then + return lpegmatch(stripper,str) + else + return str + end +end + +-- beginbfrange : +-- [ ] +-- beginbfchar : + +local fromsixteen = lpdf.fromsixteen -- maybe inline the lpeg ... but not worth it + +local function f_bfchar(t,a,b) + t[tonumber(a,16)] = fromsixteen(b) +end + +local function f_bfrange_1(t,a,b,c) + print("todo 1",a,b,c) + -- c is string + -- todo t[tonumber(a,16)] = fromsixteen(b) +end + +local function f_bfrange_2(t,a,b,c) + print("todo 2",a,b,c) + -- c is table + -- todo t[tonumber(a,16)] = fromsixteen(b) +end + +local optionals = spaces^0 +local hexstring = optionals * P("<") * C((1-P(">"))^1) * P(">") +local bfchar = Carg(1) * hexstring * hexstring / f_bfchar +local bfrange = Carg(1) * hexstring * hexstring * hexstring / f_bfrange_1 + + Carg(1) * hexstring * hexstring * optionals * P("[") * Ct(hexstring^1) * optionals * P("]") / f_bfrange_2 +local fromunicode = ( + P("beginbfchar" ) * bfchar ^1 * optionals * P("endbfchar" ) + + P("beginbfrange") * bfrange^1 * optionals * P("endbfrange") + + spaces + + P(1) +)^1 * Carg(1) + +local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code + local fonts = document.__fonts__ + if resources then + local fontlist = resources.Font + if fontlist then + for id, data in expanded(fontlist) do + if not fonts[id] then + -- a quick hack ... I will look into it more detail if I find a real + -- -application for it + local tounicode = data.ToUnicode() + if tounicode then + tounicode = lpegmatch(fromunicode,tounicode,1,{}) + end + fonts[id] = { + tounicode = type(tounicode) == "table" and tounicode or { } + } + setmetatableindex(fonts[id],"self") + end + end + end + end + return fonts +end + +local more = 0 +local unic = nil -- cheaper than passing each time as Carg(1) + +local p_hex_to_utf = C(4) / function(s) -- needs checking ! + local now = tonumber(s,16) + if more > 0 then + now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong + more = 0 + return unic[now] or utfchar(now) + elseif now >= 0xD800 and now <= 0xDBFF then + more = now + -- return "" + else + return unic[now] or utfchar(now) + end +end + +local p_dec_to_utf = C(1) / function(s) -- needs checking ! + local now = byte(s) + return unic[now] or utfchar(now) +end + +local p_hex_to_utf = P(true) / function() more = 0 end * Cs(p_hex_to_utf^1) +local p_dec_to_utf = P(true) / function() more = 0 end * Cs(p_dec_to_utf^1) + +function lpdf_epdf.getpagecontent(document,pagenumber) + + local page = document.pages[pagenumber] + + if not page then + return + end + + local fonts = analyzefonts(document,page.Resources) + + local content = page.Contents() or "" + local list = lpegmatch(parser,content) + local font = nil + -- local unic = nil + + for i=1,#list do + local entry = list[i] + local size = #entry + local operator = entry[size] + if operator == "Tf" then + font = fonts[entry[1]] + unic = font.tounicode + elseif operator == "TJ" then -- { array, TJ } + local list = entry[1] + for i=1,#list do + local li = list[i] + if type(li) == "table" then + if li[1] == "hex" then + list[i] = lpegmatch(p_hex_to_utf,li[2]) + else + list[i] = lpegmatch(p_dec_to_utf,li[2]) + end + else + -- kern + end + end + elseif operator == "Tj" or operator == "'" or operator == '"' then -- { string, Tj } { string, ' } { n, m, string, " } + local list = entry[size-1] + if list[1] == "hex" then + list[2] = lpegmatch(p_hex_to_utf,li[2]) + else + list[2] = lpegmatch(p_dec_to_utf,li[2]) + end + end + end + + unic = nil -- can be collected + + return list + +end + +-- This is also an experiment. When I really need it I can improve it, for instance +-- with proper position calculating. It might be usefull for some search or so. + +local softhyphen = utfchar(0xAD) .. "$" +local linefactor = 1.3 + +function lpdf_epdf.contenttotext(document,list) -- maybe signal fonts + local last_y = 0 + local last_f = 0 + local text = { } + local last = 0 + + for i=1,#list do + local entry = list[i] + local size = #entry + local operator = entry[size] + if operator == "Tf" then + last_f = entry[2] + elseif operator == "TJ" then + local list = entry[1] + for i=1,#list do + local li = list[i] + if type(li) == "string" then + last = last + 1 + text[last] = li + elseif li < -50 then + last = last + 1 + text[last] = " " + end + end + line = concat(list) + elseif operator == "Tj" then + last = last + 1 + text[last] = entry[size-1] + elseif operator == "cm" or operator == "Tm" then + local ty = entry[6] + local dy = abs(last_y - ty) + if dy > linefactor*last_f then + if last > 0 then + if find(text[last],softhyphen,1,true) then + -- ignore + else + last = last + 1 + text[last] = "\n" + end + end + end + last_y = ty + end + end + + return concat(text) +end + +function lpdf_epdf.getstructure(document,list) -- just a test + local depth = 0 + for i=1,#list do + local entry = list[i] + local size = #entry + local operator = entry[size] + if operator == "BDC" then + report_epdf("%w%s : %s",depth,entry[1] or "?",entry[2] and entry[2].MCID or "?") + depth = depth + 1 + elseif operator == "EMC" then + depth = depth - 1 + elseif operator == "TJ" then + local list = entry[1] + for i=1,#list do + local li = list[i] + if type(li) == "string" then + report_epdf("%w > %s",depth,li) + elseif li < -50 then + report_epdf("%w >",depth,li) + end + end + elseif operator == "Tj" then + report_epdf("%w > %s",depth,entry[size-1]) + end + end +end + +if img then do + + -- This can be made a bit faster (just get raw data and pass it) but I will + -- do that later. In the end the benefit is probably neglectable. + + local recompress = false + local stripmarked = false + + local copydictionary = nil + local copyarray = nil + + local pdfreserveobject = lpdf.reserveobject + local shareobjectreference = lpdf.shareobjectreference + local pdfflushobject = lpdf.flushobject + local pdfflushstreamobject = lpdf.flushstreamobject + local pdfreference = lpdf.reference + local pdfconstant = lpdf.constant + local pdfarray = lpdf.array + local pdfdictionary = lpdf.dictionary + local pdfnull = lpdf.null + local pdfliteral = lpdf.literal + + local report = logs.reporter("backend","xobjects") + + local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp + + local createimage = images.create + + directives.register("graphics.pdf.recompress", function(v) recompress = v end) + directives.register("graphics.pdf.stripmarked", function(v) stripmarked = v end) + + local function scaledbbox(b) + return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor } + end + + local codecs = { + ASCIIHexDecode = true, + ASCII85Decode = true, + RunLengthDecode = true, + FlateDecode = true, + LZWDecode = true, + } + + local function deepcopyobject(xref,copied,value) + -- no need for tables, just nested loop with obj + local objnum = xref[value] + if objnum then + local usednum = copied[objnum] + if usednum then + -- report("%s object %i is reused",kind,objnum) + else + usednum = pdfreserveobject() + copied[objnum] = usednum + local entry = value + local kind = entry.__type__ + if kind == array_object_code then + local a = copyarray(xref,copied,entry) + pdfflushobject(usednum,tostring(a)) + elseif kind == dictionary_object_code then + local d = copydictionary(xref,copied,entry) + pdfflushobject(usednum,tostring(d)) + elseif kind == stream_object_code then + local d = copydictionary(xref,copied,entry) + local filter = d.Filter + if filter and codecs[filter] and recompress then + -- recompress + d.Filter = nil + d.Length = nil + d.DecodeParms = nil -- relates to filter + d.DL = nil -- needed? + local s = entry() -- get uncompressed stream + pdfflushstreamobject(s,d,true,usednum) -- compress stream + else + -- keep as-is, even Length which indicates the + -- decompressed length + local s = entry(false) -- get compressed stream + -- pdfflushstreamobject(s,d,false,usednum,true) -- don't compress stream + pdfflushstreamobject(s,d,"raw",usednum) -- don't compress stream + end + else + local t = type(value) + if t == "string" then + value = pdfconstant(value) + elseif t == "table" then + local kind = value[1] + local entry = value[2] + if kind == name_object_code then + value = pdfconstant(entry) + elseif kind == string_object_code then + value = pdfliteral(entry,value[3]) + elseif kind == null_object_code then + value = pdfnull() + elseif kind == reference_object_code then + value = deepcopyobject(xref,copied,entry) + else + value = tostring(entry) + end + end + pdfflushobject(usednum,value) + end + end + return pdfreference(usednum) + elseif kind == stream_object_code then + report("stream not done: %s", objectcodes[kind] or "?") + else + report("object not done: %s", objectcodes[kind] or "?") + end + end + + local function copyobject(xref,copied,object,key,value) + if not value then + value = object.__raw__[key] + end + local t = type(value) + if t == "string" then + return pdfconstant(value) + elseif t ~= "table" then + return value + end + local kind = value[1] + if kind == name_object_code then + return pdfconstant(value[2]) + elseif kind == string_object_code then + return pdfliteral(value[2],value[3]) + elseif kind == array_object_code then + return copyarray(xref,copied,object[key]) + elseif kind == dictionary_object_code then + return copydictionary(xref,copied,object[key]) + elseif kind == null_object_code then + return pdfnull() + elseif kind == reference_object_code then + -- expand + return deepcopyobject(xref,copied,object[key]) + else + report("weird: %s", objecttypes[kind] or "?") + end + end + + copyarray = function (xref,copied,object) + local target = pdfarray() + local source = object.__raw__ + for i=1,#source do + target[i] = copyobject(xref,copied,object,i,source[i]) + end + return target + end + + local plugins = nil + + -- Sorting the hash slows down upto 5% bit but it is still as fast as the C + -- code. We could loop over the index instead but sorting might be nicer in + -- the end. + + copydictionary = function (xref,copied,object) + local target = pdfdictionary() + local source = object.__raw__ + -- for key, value in next, source do + for key, value in sortedhash(source) do + if plugins then + local p = plugins[key] + if p then + target[key] = p(xref,copied,object,key,value,copyobject) -- maybe a table of methods + else + target[key] = copyobject(xref,copied,object,key,value) + end + else + target[key] = copyobject(xref,copied,object,key,value) + end + end + return target + end + + -- local function copyresources(pdfdoc,xref,copied,pagedata) + -- local Resources = pagedata.Resources + -- if Resources then + -- local r = pdfreserveobject() + -- local d = copydictionary(xref,copied,Resources) + -- pdfflushobject(r,tostring(d)) + -- return pdfreference(r) + -- end + -- end + + local function copyresources(pdfdoc,xref,copied,pagedata) + local Resources = pagedata.Resources + -- + -- -- This needs testing: + -- + -- if not Resources then + -- local Parent = page.Parent + -- while (Parent and (Parent.__type__ == dictionary_object_code or Parent.__type__ == reference_object_code) do + -- Resources = Parent.Resources + -- if Resources then + -- break + -- end + -- Parent = Parent.Parent + -- end + -- end + if Resources then + local d = copydictionary(xref,copied,Resources) + return shareobjectreference(d) + end + end + + local openpdf = lpdf_epdf.load + local closepdf = lpdf_epdf.unload + + local function newpdf(str,userpassword,ownerpassword) + return openpdf(str,userpassword,ownerpassword,true) + end + + local function querypdf(pdfdoc,pagenumber) + if pdfdoc then + if not pagenumber then + pagenumber = 1 + end + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber] + if page then + -- todo + local mediabox = page.MediaBox or { 0, 0, 0, 0 } + local cropbox = page.CropBox or mediabox + return { + filename = pdfdoc.filename, + pagenumber = pagenumber, + nofpages = pdfdoc.nofpages, + boundingbox = scaledbbox(cropbox), + cropbox = cropbox, + mediabox = mediabox, + bleedbox = page.BleedBox or cropbox, + trimbox = page.TrimBox or cropbox, + artbox = page.ArtBox or cropbox, + rotation = page.Rotate or 0, + xsize = cropbox[3] - cropbox[1], + ysize = cropbox[4] - cropbox[2], + } + end + end + end + + local function copypage(pdfdoc,pagenumber,attributes,compact,width,height,attr) + if pdfdoc then + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber or 1] + local pageinfo = querypdf(pdfdoc,pagenumber) + local contents = page.Contents + local xref = pdfdoc.__xrefs__ + local copied = pdfdoc.__copied__ + if compact and lpdf_epdf.plugin then + plugins = lpdf_epdf.plugin(pdfdoc,xref,copied,page) + end + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Form"), + FormType = 1, + Group = copyobject(xref,copied,page,"Group"), + LastModified = copyobject(xref,copied,page,"LastModified"), + Metadata = copyobject(xref,copied,page,"Metadata"), + PieceInfo = copyobject(xref,copied,page,"PieceInfo"), + Resources = copyresources(pdfdoc,xref,copied,page), + SeparationInfo = copyobject(xref,copied,page,"SeparationInfo"), + } + attr + if attributes then + for k, v in expanded(attributes) do + page[k] = v -- maybe nested + end + end + local content = "" + local nolength = nil + local ctype = contents.__type__ + -- we always recompress because image object streams can not be + -- influenced (yet) + if ctype == stream_object_code then + if stripmarked then + content = contents() -- uncompressed + local stripped = lpdf_epdf.stripcontent(content) + if stripped ~= content then + -- report("%i bytes stripped on page %i",#content-#stripped,pagenumber or 1) + content = stripped + end + elseif recompress then + content = contents() -- uncompressed + else + local Filter = copyobject(xref,copied,contents,"Filter") + local Length = copyobject(xref,copied,contents,"Length") + if Length and Filter then + nolength = true + xobject.Length = Length + xobject.Filter = Filter + content = contents(false) -- uncompressed + else + content = contents() -- uncompressed + end + end + elseif ctype == array_object_code then + content = { } + for i=1,#contents do + content[i] = contents[i]() -- uncompressed + end + content = concat(content," ") + end + -- still not nice: we double wrap now + plugins = nil + local rotation = pageinfo.rotation + local boundingbox = pageinfo.boundingbox + local transform = nil + if rotation == 90 then + transform = 3 + elseif rotation == 180 then + transform = 2 + elseif rotation == 270 then + transform = 1 + elseif rotation > 1 and rotation < 4 then + transform = rotation + end + xobject.BBox = pdfarray { + boundingbox[1] * bpfactor, + boundingbox[2] * bpfactor, + boundingbox[3] * bpfactor, + boundingbox[4] * bpfactor, + } + -- maybe like bitmaps + return createimage { -- beware: can be a img.new or a dummy + bbox = boundingbox, + transform = transform, + nolength = nolength, + nobbox = true, + notype = true, + stream = content, -- todo: no compress, pass directly also length, filter etc + attr = xobject(), + kind = images.types.stream, + } + end + end + + lpdf_epdf.image = { + open = openpdf, + close = closepdf, + new = newpdf, + query = querypdf, + copy = copypage, + } + +-- lpdf.injectors.pdf = function(specification) +-- local d = lpdf_epdf.load(specification.filename) +-- print(d) +-- end + + +end end + +-- local d = lpdf_epdf.load("e:/tmp/oeps.pdf") +-- inspect(d) +-- inspect(d.Catalog.Lang) +-- inspect(d.Catalog.OCProperties.D.AS[1].Event) +-- inspect(d.Catalog.Metadata()) +-- inspect(d.Catalog.Pages.Kids[1]) +-- inspect(d.layers) +-- inspect(d.pages) +-- inspect(d.destinations) +-- inspect(lpdf_epdf.getpagecontent(d,1)) +-- inspect(lpdf_epdf.contenttotext(document,lpdf_epdf.getpagecontent(d,1))) +-- inspect(lpdf_epdf.getstructure(document,lpdf_epdf.getpagecontent(d,1))) diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml index 889862c76f7..35726a5c051 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pdx.xml @@ -29,6 +29,7 @@ + diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml index f985b54d334..f717762b6e6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pua.xml @@ -29,6 +29,7 @@ + @@ -110,6 +111,12 @@ ConTeXt.Url Text + + external + ConTeXt support + ConTeXt.Support + Text + external ConTeXt version @@ -118,8 +125,38 @@ external - Banner of pdftex or one of its successors - PTEX.Fullbanner + ConTeXt LMTX version + ConTeXt.LMTX + Text + + + external + TeX support + TeX.Support + Text + + + external + LuaTeX version + LuaTeX.Version + Text + + + external + LuaTeX functionality + LuaTeX.Functionality + Text + + + external + LuaTeX Lua version + LuaTeX.LuaVersion + Text + + + external + LuaTeX platform + LuaTeX.Platform Text diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua index e9b22f38299..d6e95e66a22 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ren.lua @@ -54,7 +54,7 @@ local copy_node = nuts.copy local nodepool = nuts.pool local register = nodepool.register -local pdfpageliteral = nodepool.pdfpageliteral +local pageliteral = nodepool.pageliteral local pdf_ocg = pdfconstant("OCG") local pdf_ocmd = pdfconstant("OCMD") @@ -261,7 +261,7 @@ function nodeinjections.startlayer(name) local c = cache[name] if not c then useviewerlayer(name) - c = register(pdfpageliteral(f_bdc(escapednames[name]))) + c = register(pageliteral(f_bdc(escapednames[name]))) cache[name] = c end return copy_node(c) @@ -269,7 +269,7 @@ end function nodeinjections.stoplayer() if not stop then - stop = register(pdfpageliteral(s_emc)) + stop = register(pageliteral(s_emc)) end return copy_node(stop) end @@ -286,7 +286,7 @@ function nodeinjections.startstackedlayer(s,t,first,last) r[#r+1] = startlayer(values[t[i]]) end r = concat(r," ") - return pdfpageliteral(r) + return pageliteral(r) end function nodeinjections.stopstackedlayer(s,t,first,last) @@ -295,7 +295,7 @@ function nodeinjections.stopstackedlayer(s,t,first,last) r[#r+1] = stoplayer() end r = concat(r," ") - return pdfpageliteral(r) + return pageliteral(r) end function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2) @@ -307,7 +307,7 @@ function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2) r[#r+1] = startlayer(values[t2[i]]) end r = concat(r," ") - return pdfpageliteral(r) + return pageliteral(r) end -- transitions diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua index 8b00835ef84..d3c591343fc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-res.lua @@ -6,23 +6,25 @@ if not modules then modules = { } end modules ['lpdf-res'] = { license = "see context related readme files" } -local codeinjections = backends.codeinjections -local implement = interfaces.implement +local codeinjections = backends.codeinjections -local nuts = nodes.nuts -local tonut = nodes.tonut +local nuts = nodes.nuts +local tonut = nodes.tonut -local setwhd = nuts.setwhd -local setlist = nuts.setlist +local setwhd = nuts.setwhd +local setlist = nuts.setlist -local new_hlist = nuts.pool.hlist +local new_hlist = nuts.pool.hlist -local saveboxresource = tex.saveboxresource -local useboxresource = tex.useboxresource -local getboxresource = tex.getboxresourcedimensions +local boxresources = tex.boxresources +local saveboxresource = boxresources.save +local useboxresource = boxresources.use +local getboxresourcedimensions = boxresources.getdimensions + +local pdfcollectedresources = lpdf.collectedresources function codeinjections.registerboxresource(n,offset) - local r = saveboxresource(n,nil,lpdf.collectedresources(),true,0,offset or 0) -- direct, todo: accept functions as attr/resources + local r = saveboxresource(n,nil,pdfcollectedresources(),true,0,offset or 0) -- direct, todo: accept functions as attr/resources return r end @@ -35,5 +37,5 @@ function codeinjections.restoreboxresource(index) end function codeinjections.boxresourcedimensions(index) - return getboxresource(index) + return getboxresourcedimensions(index) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua index 0ac107f8b5e..44e42dc5f8d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-swf.lua @@ -11,6 +11,7 @@ if not modules then modules = { } end modules ['lpdf-swf'] = { local format, gsub = string.format, string.gsub local concat = table.concat +local formatters = string.formatters local backends = backends local lpdf = lpdf @@ -33,6 +34,43 @@ local trace_swf = false trackers.register("backend.swf", function(v) trace_swf local report_swf = logs.reporter("backend","swf") +-------------------------------------------------------------------------------------- + +local createimage = images.create +local embedimage = images.embed + +local basepoints = number.dimenfactors.bp + +local f_image = formatters["%.6F 0 0 %.6F 0 0 cm /%s Do"] + +directives.register("pdf.stripzeros",function() + f_image = formatters["%.6N 0 0 %.6N 0 0 cm /%s Do"] +end) + +local function package(image) -- see lpdf-u3d ** + local boundingbox = image.bbox + local imagetag = "Im" .. image.index -- this is not ok + local resources = pdfdictionary { + ProcSet = lpdf.procset(), + Resources = pdfdictionary { + XObject = pdfdictionary { + [imagetag] = pdfreference(image.objnum) + } + } + } + local width = boundingbox[3] + local height = boundingbox[4] + local xform = createimage { + attr = resources(), + stream = f_image(width,height,imagetag), + bbox = { 0, 0, width/basepoints, height/basepoints }, + } + embedimage(xform) + return xform +end + +-------------------------------------------------------------------------------------- + local activations = { click = "XA", page = "PO", @@ -65,7 +103,10 @@ local function insertswf(spec) local preview = checkedkey(display,"preview","string") local toolbar = checkedkey(display,"toolbar","boolean") - local embeddedreference = codeinjections.embedfile { file = filename } + local embeddedreference = codeinjections.embedfile { + file = filename, + compress = false, + } local flash = pdfdictionary { Subtype = pdfconstant("RichMediaConfiguration"), @@ -122,6 +163,7 @@ local function insertswf(spec) file = fullname, usedname = usedname, keepdir = true, + compress = false, } names[#names+1] = pdfstring(filename) names[#names+1] = embeddedreference @@ -275,7 +317,7 @@ local function insertswf(spec) end end if figure then - local image = img.package(figure.status.private) + local image = package(figure.status.private) appearance = pdfdictionary { N = pdfreference(image.objnum) } if trace_swf then report_swf("using preview %s",preview) diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua index f4ecfc8a601..0a2fe679ea8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-tag.lua @@ -13,7 +13,8 @@ local settings_to_hash = utilities.parsers.settings_to_hash local sortedhash = table.sortedhash local formatters = string.formatters -local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end) +local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end) +local trace_info = false trackers.register("structures.tags.info", function(v) trace_info = v end) local report_tags = logs.reporter("backend","tags") @@ -51,11 +52,9 @@ local a_tagged = attributes.private('tagged') local a_image = attributes.private('image') local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local nodepool = nuts.pool -local pdfpageliteral = nodepool.pdfpageliteral +local pageliteral = nodepool.pageliteral local register = nodepool.register local getid = nuts.getid @@ -68,17 +67,17 @@ local setlink = nuts.setlink local setlist = nuts.setlist local copy_node = nuts.copy -local traverse_nodes = nuts.traverse local tosequence = nuts.tosequence -local structure_stack = { } -local structure_kids = pdfarray() -local structure_ref = pdfreserveobject() -local parent_ref = pdfreserveobject() -local root = { pref = pdfreference(structure_ref), kids = structure_kids } +local nextnode = nuts.traversers.node + +local structure_kids -- delayed +local structure_ref -- delayed +local parent_ref -- delayed +local root -- delayed +local names -- delayed local tree = { } local elements = { } -local names = pdfarray() local structurestags = structures.tags local taglist = structurestags.taglist @@ -112,7 +111,7 @@ local usedmapping = { } -- end local function finishstructure() - if #structure_kids > 0 then + if root and #structure_kids > 0 then local nums, n = pdfarray(), 0 for i=1,#tree do n = n + 1 ; nums[n] = i - 1 @@ -171,6 +170,7 @@ local index, pageref, pagenum, list = 0, nil, 0, nil local pdf_mcr = pdfconstant("MCR") local pdf_struct_element = pdfconstant("StructElem") +local pdf_s = pdfconstant("S") local function initializepage() index = 0 @@ -183,6 +183,8 @@ end local function finishpage() -- flush what can be flushed addtopageattributes("StructParents",pagenum-1) + -- there might be more + addtopageattributes("Tabs",s) end -- here we can flush and free elements that are finished @@ -255,9 +257,10 @@ local function makeelement(fulltag,parent) AF = af, } local s = pdfreference(pdfflushobject(d)) - if id then - names[#names+1] = id - names[#names+1] = s + if id and names then + local size = #names + names[size+1] = id + names[size+2] = s end local kids = parent.kids kids[#kids+1] = s @@ -314,27 +317,35 @@ end -- no need to adapt head, as we always operate on lists local EMCliteral = nil +local visualize = nil function nodeinjections.addtags(head) if not EMCliteral then - EMCliteral = register(pdfpageliteral("EMC")) + EMCliteral = register(pageliteral("EMC")) end local last = nil local ranges = { } local range = nil - local head = tonut(head) + + if not root then + structure_kids = pdfarray() + structure_ref = pdfreserveobject() + parent_ref = pdfreserveobject() + root = { pref = pdfreference(structure_ref), kids = structure_kids } + names = pdfarray() + end local function collectranges(head,list) - for n in traverse_nodes(head) do - local id = getid(n) + for n, id in nextnode, head do if id == glyph_code then -- maybe also disc - local at = getattr(n,a_tagged) - if not at then - range = nil - elseif last ~= at then + local at = getattr(n,a_tagged) or false -- false: pagebody or so, so artifact + -- if not at then + -- range = nil + -- elseif ... + if last ~= at then range = { at, "glyph", n, n, list } -- attr id start stop list ranges[#ranges+1] = range last = at @@ -344,12 +355,12 @@ function nodeinjections.addtags(head) elseif id == hlist_code or id == vlist_code then local at = getattr(n,a_image) if at then - local at = getattr(n,a_tagged) - if not at then - range = nil - else + local at = getattr(n,a_tagged) or false -- false: pagebody or so, so artifact + -- if not at then + -- range = nil + -- else ranges[#ranges+1] = { at, "image", n, n, list } -- attr id start stop list - end + -- end last = nil else collectranges(getlist(n),n) @@ -379,89 +390,117 @@ function nodeinjections.addtags(head) local top = nil local noftop = 0 + + local function inject(start,stop,list,literal,left,right) + local prev = getprev(start) + if prev then + setlink(prev,literal) + end + if left then + setlink(literal,left,start) + else + setlink(literal,start) + end + if list and getlist(list) == start then + setlist(list,literal) + end + local literal = copy_node(EMCliteral) + -- use insert instead: + local next = getnext(stop) + if next then + setlink(literal,next) + end + if right then + setlink(stop,right,literal) + else + setlink(stop,literal) + end + end + for i=1,#ranges do - local range = ranges[i] - local attr = range[1] - local id = range[2] - local start = range[3] - local stop = range[4] - local list = range[5] - local specification = taglist[attr] - local taglist = specification.taglist - local noftags = #taglist - local common = 0 - if top then - for i=1,noftags >= noftop and noftop or noftags do - if top[i] == taglist[i] then - common = i - else - break + + local range = ranges[i] + local attr = range[1] + local id = range[2] + local start = range[3] + local stop = range[4] + local list = range[5] + + if attr then + + local specification = taglist[attr] + local taglist = specification.taglist + local noftags = #taglist + local common = 0 + local literal = nil + local ignore = false + + if top then + for i=1,noftags >= noftop and noftop or noftags do + if top[i] == taglist[i] then + common = i + else + break + end end end - end - local prev = common > 0 and elements[taglist[common]] or root - local ignore = false - local literal = nil - - for j=common+1,noftags do - local tag = taglist[j] - local prv = elements[tag] or makeelement(tag,prev) - if prv == false then - -- ignore this one - prev = false - ignore = true - break - elseif prv == true then - -- skip this one - else - prev = prv + local prev = common > 0 and elements[taglist[common]] or root + + for j=common+1,noftags do + local tag = taglist[j] + local prv = elements[tag] or makeelement(tag,prev) + if prv == false then + -- ignore this one + prev = false + ignore = true + break + elseif prv == true then + -- skip this one + else + prev = prv + end end - end - if prev then - literal = pdfpageliteral(makecontent(prev,id,specification)) - elseif ignore then - literal = pdfpageliteral(makeignore(specification)) - end - if literal then - local prev = getprev(start) if prev then - setlink(prev,literal) - end - setlink(literal,start) - if list and getlist(list) == start then - setlist(list,literal) + literal = pageliteral(makecontent(prev,id,specification)) + elseif ignore then + literal = pageliteral(makeignore(specification)) + else + -- maybe also ignore or maybe better: comment or so end - local literal = copy_node(EMCliteral) - -- use insert instead: - local next = getnext(stop) - if next then - setlink(literal,next) + + if literal then + local left,right + if trace_info then + local name = specification.tagname + if name then + if not visualize then + visualize = nodes.visualizers.register("tags") + end + left = visualize(name) + right = visualize() + end + end + inject(start,stop,list,literal,left,right) end - setlink(stop,literal) - end --- if literal then --- if list and getlist(list) == start then --- setlink(literal,start) --- setlist(list,literal) --- else --- setlink(getprev(start),literal,start) --- end --- -- use insert instead: --- local literal = copy_node(EMCliteral) --- setlink(stop,literal,getnext(stop)) --- end + top = taglist + noftop = noftags + + else + + local literal = pageliteral(makeignore(specification)) + + inject(start,stop,list,literal) + + end - top = taglist - noftop = noftags end finishpage() - head = tonode(head) - return head, true + return head end @@ -472,8 +511,7 @@ end -- local last, ranges, range = nil, { }, nil -- -- local function collectranges(head,list) --- for n in traverse_nodes(head) do --- local id = getid(n) -- 14: image, 8: literal (mp) +-- for n, id in nextnode, head do -- if id == glyph_code then -- local at = getattr(n,a_tagged) -- if not at then @@ -505,7 +543,6 @@ end -- -- initializepage() -- --- head = tonut(head) -- collectranges(head) -- -- if trace_tags then @@ -577,9 +614,9 @@ end -- end -- -- if r > 0 then --- local literal = pdfpageliteral(concat(result,"\n")) +-- local literal = pageliteral(concat(result,"\n")) -- -- use insert instead: --- local literal = pdfpageliteral(result) +-- local literal = pageliteral(result) -- local prev = getprev(start) -- if prev then -- setlink(prev,literal) @@ -601,7 +638,7 @@ end -- for i=1,noftop do -- result[i] = "EMC" -- end --- local literal = pdfpageliteral(concat(result,"\n")) +-- local literal = pageliteral(concat(result,"\n")) -- -- use insert instead: -- local next = getnext(last) -- if next then @@ -612,8 +649,7 @@ end -- -- finishpage() -- --- head = tonode(head) --- return head, true +-- return head -- -- end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua index dfd4c1b0686..f6897e92d20 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-u3d.lua @@ -27,7 +27,6 @@ local nodeinjections = backends.pdf.nodeinjections local pdfconstant = lpdf.constant local pdfboolean = lpdf.boolean -local pdfnumber = lpdf.number local pdfunicode = lpdf.unicode local pdfdictionary = lpdf.dictionary local pdfarray = lpdf.array @@ -39,6 +38,8 @@ local pdfflushstreamfileobject = lpdf.flushstreamfileobject local checkedkey = lpdf.checkedkey local limited = lpdf.limited +local embedimage = images.embed + local schemes = table.tohash { "Artwork", "None", "White", "Day", "Night", "Hard", "Primary", "Blue", "Red", "Cube", "CAD", "Headlamp", @@ -347,6 +348,12 @@ end local stored_js, stored_3d, stored_pr, streams = { }, { }, { }, { } +local f_image = formatters["q /GS gs %.6F 0 0 %.6F 0 0 cm /IM Do Q"] + +directives.register("pdf.stripzeros",function() + f_image = formatters["q /GS gs %.6N 0 0 %.6N 0 0 cm /IM Do Q"] +end) + local function insert3d(spec) -- width, height, factor, display, controls, label, foundname local width, height, factor = spec.width, spec.height, spec.factor or number.dimenfactors.bp @@ -431,7 +438,7 @@ local function insert3d(spec) -- width, height, factor, display, controls, label local tag = formatters["%s:%s:%s"](label,stream,preview) local ref = stored_pr[tag] if not ref then - local figure = img.immediatewrite { + local figure = embedimage { filename = preview, width = width, height = height @@ -440,13 +447,13 @@ local function insert3d(spec) -- width, height, factor, display, controls, label stored_pr[tag] = ref end if ref then -- see back-pdf ** .. here we have a local /IM ! - local zero, one = pdfnumber(0), pdfnumber(1) -- not really needed local pw = pdfdictionary { Type = pdfconstant("XObject"), Subtype = pdfconstant("Form"), - FormType = one, - BBox = pdfarray { zero, zero, pdfnumber(factor*width), pdfnumber(factor*height) }, - Matrix = pdfarray { one, zero, zero, one, zero, zero }, + FormType = 1, + BBox = pdfarray { 0, 0, pdfnumber(factor*width), pdfnumber(factor*height) }, + Matrix = pdfarray { 1, 0, 0, 1, 0, 0 }, + ProcSet = lpdf.procset(), Resources = pdfdictionary { XObject = pdfdictionary { IM = pdfreference(ref) @@ -455,13 +462,12 @@ local function insert3d(spec) -- width, height, factor, display, controls, label ExtGState = pdfdictionary { GS = pdfdictionary { Type = pdfconstant("ExtGState"), - CA = one, - ca = one, + CA = 1, + ca = 1, } }, - ProcSet = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") }, } - local pwd = pdfflushstreamobject(formatters["q /GS gs %.6F 0 0 %.6F 0 0 cm /IM Do Q"](factor*width,factor*height),pw) + local pwd = pdfflushstreamobject(f_image(factor*width,factor*height),pw) annot.AP = pdfdictionary { N = pdfreference(pwd) } diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua index 03febbf01e2..a929ed2ceb9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-wid.lua @@ -11,11 +11,11 @@ if not modules then modules = { } end modules ['lpdf-wid'] = { -- had renditions but they turned out to be unreliable from the start and look -- obsolete too or at least they are bound to the (obsolete) flash technology for -- rendering. They were already complex constructs. Now we have rich media which --- instead of providing a robust future proof framework fo rgeneral media types +-- instead of providing a robust future proof framework for general media types -- again seems to depend on viewers built in (yes, also kind of obsolete) flash -- technology, and we cannot expect this non-open technology to show up in open -- browsers. So, in the end we can best just use links to external resources to be --- future proof. Just look at the viewer prferences pane to see how fragile support +-- future proof. Just look at the viewer preferences pane to see how fragile support -- is. Interestingly u3d support is kind of built in, while e.g. mp4 support relies -- on wrapping in swf. We used to stay ahead of the pack with support of the fancy -- pdf features but it backfires and is not worth the trouble. And yes, for control @@ -29,7 +29,7 @@ local gmatch, gsub, find, lower = string.gmatch, string.gsub, string.find, strin local stripstring = string.strip local settings_to_array = utilities.parsers.settings_to_array local settings_to_hash = utilities.parsers.settings_to_hash -local sortedhash = table.sortedhash +local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys local report_media = logs.reporter("backend","media") local report_attachment = logs.reporter("backend","attachment") @@ -141,6 +141,10 @@ local attachment_symbols = { attachment_symbols.PushPin = attachment_symbols.Pushpin attachment_symbols.Default = attachment_symbols.Pushpin +function lpdf.attachmentsymbols() + return sortedkeys(comment_symbols) +end + local comment_symbols = { Comment = pdfconstant("Comment"), Help = pdfconstant("Help"), @@ -154,6 +158,10 @@ local comment_symbols = { comment_symbols.NewParagraph = Newparagraph comment_symbols.Default = Note +function lpdf.commentsymbols() + return sortedkeys(comment_symbols) +end + local function analyzesymbol(symbol,collection) if not symbol or symbol == "" then return collection and collection.Default, nil @@ -239,10 +247,12 @@ local function flushembeddedfiles() e[#e+1] = pdfstring(tag) e[#e+1] = reference -- already a reference else - -- messy spec ... when annot not in named else twice in menu list acrobat + -- -- messy spec ... when annot not in named else twice in menu list acrobat end end - lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e }))) + if #e > 0 then + lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e }))) + end end end @@ -257,9 +267,13 @@ function codeinjections.embedfile(specification) local keepdir = specification.keepdir -- can change local usedname = specification.usedname local filetype = specification.filetype + local compress = specification.compress if filename == "" then filename = nil end + if compress == nil then + compress = true + end if data then local r = filestreams[hash] if r == false then @@ -314,7 +328,7 @@ function codeinjections.embedfile(specification) specification.data = true -- signal that still data but already flushed else local foundname = specification.foundname or filename - f = pdfflushstreamfileobject(foundname,a) + f = pdfflushstreamfileobject(foundname,a,compress) end local d = pdfdictionary { Type = pdfconstant("Filespec"), @@ -417,7 +431,8 @@ function codeinjections.attachmentid(filename) -- not used in context return filestreams[filename] end -local nofcomments, usepopupcomments = 0, false +local nofcomments = 0 +local usepopupcomments = false local defaultattributes = { ["xmlns"] = "http://www.w3.org/1999/xhtml", @@ -612,7 +627,8 @@ local function insertrendering(specification) local option = settings_to_hash(specification.option) if not mf[label] then local filename = specification.filename - local isurl = find(filename,"://",1,true) + local isurl = find(filename,"://",1,true) + local mimetype = specification.mimetype or specification.mime -- local start = pdfdictionary { -- Type = pdfconstant("MediaOffset"), -- S = pdfconstant("T"), -- time @@ -648,13 +664,17 @@ local function insertrendering(specification) if isurl then descriptor.FS = pdfconstant("URL") elseif option[v_embed] then - descriptor.EF = codeinjections.embedfile { file = filename } + descriptor.EF = codeinjections.embedfile { + file = filename, + mimetype = mimetype, -- yes or no + compress = false, + } end local clip = pdfdictionary { Type = pdfconstant("MediaClip"), S = pdfconstant("MCD"), N = label, - CT = specification.mime, + CT = mimetype, Alt = pdfarray { "", "file not found" }, -- language id + message D = pdfreference(pdfflushobject(descriptor)), -- P = pdfreference(pdfflushobject(parameters)), diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua index eb15a358287..508bb19976d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-xmp.lua @@ -11,6 +11,7 @@ local tostring, type = tostring, type local format, gsub = string.format, string.gsub local utfchar = utf.char local xmlfillin = xml.fillin +local md5HEX = md5.HEX local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end) local trace_info = false trackers.register("backend.info", function(v) trace_info = v end) @@ -33,7 +34,7 @@ local pdfgetmetadata = lpdf.getmetadata -- XMP-Toolkit-SDK-CC201607.zip. So we hardcode the id. local xpacket = format ( [[ - + %%s @@ -46,7 +47,8 @@ local mapping = { ["ConTeXt.Url"] = { "context", "rdf:Description/pdfx:ConTeXt.Url" }, ["ConTeXt.Support"] = { "context", "rdf:Description/pdfx:ConTeXt.Support" }, ["ConTeXt.Version"] = { "context", "rdf:Description/pdfx:ConTeXt.Version" }, - ["TeX.Support"] = { "metadata", "rdf:Description/pdfx:TeX.Support" }, + ["ConTeXt.LMTX"] = { "context", "rdf:Description/pdfx:ConTeXt.LMTX" }, + ["TeX.Support"] = { "metadata","rdf:Description/pdfx:TeX.Support" }, ["LuaTeX.Version"] = { "metadata","rdf:Description/pdfx:LuaTeX.Version" }, ["LuaTeX.Functionality"] = { "metadata","rdf:Description/pdfx:LuaTeX.Functionality" }, ["LuaTeX.LuaVersion"] = { "metadata","rdf:Description/pdfx:LuaTeX.LuaVersion" }, @@ -89,7 +91,7 @@ local mapping = { ["CaptionWriter"] = { "metadata", "rdf:Description/photoshop:CaptionWriter" }, } -pdf.setsuppressoptionalinfo( +lpdf.setsuppressoptionalinfo ( 0 -- + 1 -- pdfnofullbanner + 2 -- pdfnofilename @@ -104,59 +106,62 @@ pdf.setsuppressoptionalinfo( ) local included = backends.included - -local pdfsettrailerid = pdf.settrailerid - -local lpdfid = lpdf.id +local lpdfid = lpdf.id function lpdf.id() -- overload of ini return lpdfid(included.date) end -pdf.disablecommand("settrailerid") +local settrailerid = lpdf.settrailerid -- this is the wrapped one + +local trailerid = nil +local dates = nil -function lpdf.settrailerid(v) - if v then - local b = toboolean(v) or v == "" +local function update() + if trailer_id then + local b = toboolean(trailer_id) or trailer_id == "" if b then - v = "This file is processed by ConTeXt and LuaTeX." + trailer_id = "This file is processed by ConTeXt and LuaTeX." else - v = tostring(v) + trailer_id = tostring(trailer_id) end - local h = md5.HEX(v) + local h = md5HEX(trailer_id) if b then report_info("using frozen trailer id") else - report_info("using hashed trailer id %a (%a)",v,h) + report_info("using hashed trailer id %a (%a)",trailer_id,h) end - pdfsettrailerid(format("[<%s> <%s>]",h,h)) + settrailerid(format("[<%s> <%s>]",h,h)) end -end - -function lpdf.setdates(v) - local t = type(v) + -- + local t = type(dates) if t == "number" or t == "string" then - t = converters.totime(v) - if t then + local d = converters.totime(dates) + if d then included.date = true included.id = "fake" - report_info("forced date/time information %a will be used",lpdf.settime(t)) - lpdf.settrailerid(false) + report_info("forced date/time information %a will be used",lpdf.settime(d)) + settrailerid(false) return end - end - v = toboolean(v) - included.date = v - if v then - included.id = true - else - report_info("no date/time but fake id information will be added") - lpdf.settrailerid(true) - included.id = "fake" - -- maybe: lpdf.settime(231631200) -- 1975-05-05 % first entry of knuth about tex mentioned in DT + if t == "string" then + dates = toboolean(dates) + included.date = dates + if dates ~= false then + included.id = true + else + report_info("no date/time but fake id information will be added") + settrailerid(true) + included.id = "fake" + end + end end end +function lpdf.settrailerid(v) trailerid = v end +function lpdf.setdates (v) dates = v end + +lpdf.registerdocumentfinalizer(update,"trailer id and dates",1) directives.register("backend.trailerid", lpdf.settrailerid) directives.register("backend.date", lpdf.setdates) @@ -313,7 +318,7 @@ local function flushxmpinfo() commands.poprandomseed() -- hack end --- his will be enabled when we can inhibit compression for a stream at the lua end +-- this will be enabled when we can inhibit compression for a stream at the lua end lpdf.registerdocumentfinalizer(flushxmpinfo,1,"metadata") diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv index b1af4da3ee9..0add4ce6926 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-bas.mkiv @@ -13,6 +13,7 @@ \writestatus{loading}{ConTeXt Lua Macros / Basic Lua Libraries} +\registerctxluafile{l-bit32} {} % before sandbox \registerctxluafile{l-lua} {} % before sandbox \registerctxluafile{l-macro} {} \registerctxluafile{l-sandbox} {} @@ -30,6 +31,7 @@ \registerctxluafile{l-file} {} \registerctxluafile{l-gzip} {} \registerctxluafile{l-md5} {} +\registerctxluafile{l-sha} {} \registerctxluafile{l-dir} {} \registerctxluafile{l-unicode} {optimize} %registerctxluafile{l-utils} {} diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua index 6fcfdc7f2ee..d3184e1af77 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cbk.lua @@ -121,6 +121,12 @@ if trace_calls then end +-- temporary, not public: + +callbacks.functions = { } + +-- till here + local reported = { } local function register_usercall(what,name,func) diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua index b6ee15083da..0670d168418 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cnf.lua @@ -154,6 +154,8 @@ function texconfig.init() end +CONTEXTLMTXMODE = %s + -- we provide a qualified path callback.register('find_format_file',function(name) @@ -212,7 +214,7 @@ local function makestub() t[#t+1] = format("texconfig.%s=%s",v,tv) end end - io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable))) + io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable,tostring(CONTEXTLMTXMODE) or 0))) logs.newline() end diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua index 91bb7c2e168..dcb16c0dd72 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-cod.lua @@ -11,6 +11,10 @@ local match, gsub, find, format, gmatch = string.match, string.gsub, string.find local texconfig, lua = texconfig, lua +-- maybe pick up from commandline: +-- +-- texconfig.interaction: 0=batchmode 1=nonstopmode 2=scrollmode 3=errornonstopmode 4=normal + -- some basic housekeeping texconfig.kpse_init = false @@ -38,7 +42,7 @@ lua.bytedata = bytedata lua.bytedone = bytedone local setbytecode = lua.setbytecode -local getbytecode = lua.getbytecode +----- getbytecode = lua.getbytecode lua.firstbytecode = 501 lua.lastbytecode = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier @@ -49,9 +53,13 @@ end -- no file.* and utilities.parsers.* functions yet +local strip = false if arg then for i=-1,#arg do if arg[i] == "--c:strip" then strip = true break end end end + function lua.registercode(filename,options) local barename = gsub(filename,"%.[%a%d]+$","") - if barename == filename then filename = filename .. ".lua" end + if barename == filename then + filename = filename .. ".lua" + end local basename = match(barename,"^.+[/\\](.-)$") or barename if not bytedone[basename] then local opts = { } @@ -66,7 +74,11 @@ function lua.registercode(filename,options) if environment.initex then local n = lua.lastbytecode + 1 bytedata[n] = { name = barename, options = opts } - setbytecode(n,code) + if strip or opts.strip then + setbytecode(n,code,true) + else + setbytecode(n,code) + end lua.lastbytecode = n end elseif environment.initex then @@ -129,6 +141,18 @@ if LUATEXVERION == nil then + (tonumber(LUATEXVERSION) or (string.byte(LUATEXVERSION)-string.byte("a")+10))/1000 end +if CONTEXTLMTXMODE == nil then + if status.obj_ptr == nil then + CONTEXTLMTXMODE = 2 + else + CONTEXTLMTXMODE = 0 + for i=1,#arg do if arg[i] == "--c:lmtx" then + CONTEXTLMTXMODE, pdf, img = 1, nil, nil + break + end end + end +end + if LUATEXFUNCTIONALITY == nil then LUATEXFUNCTIONALITY = status.development_id or 6346 end @@ -143,7 +167,7 @@ end environment.luatexengine = LUATEXENGINE environment.luatexversion = LUATEXVERSION -environment.luatexfuncitonality = LUATEXFUNCTIONALITY +environment.luatexfunctionality = LUATEXFUNCTIONALITY environment.jitsupported = JITSUPPORTED environment.initex = INITEXMODE environment.initexmode = INITEXMODE @@ -151,12 +175,14 @@ environment.initexmode = INITEXMODE if not environment.luafilechunk then function environment.luafilechunk(filename) + local fullname = filename if sourcepath ~= "" then - filename = sourcepath .. "/" .. filename + fullname = sourcepath .. "/" .. filename end - local data = loadfile(filename) - texio.write("term and log","<",data and "+ " or "- ",filename,">") + local data = loadfile(fullname) + texio.write("term and log","<",data and "+ " or "- ",fullname,">") if data then +-- package.loaded[gsub(filename,"%..-$"] = data() end return data @@ -187,6 +213,21 @@ end -- a kpse error when disabled. This is an engine issue that will -- be sorted out in due time. +if not lfs.isfile then + + local attributes = lfs.attributes + + function lfs.isdir(name) + return attributes(name,"mode") == "directory" + end + + function lfs.isfile(name) + local a = attributes(name,"mode") + return a == "file" or a == "link" or nil + end + +end + local isfile = lfs.isfile local function source_file(name) @@ -229,6 +270,15 @@ local function open_read_file(name) } end +local function find_data_file(name) + return source_file(name) +end + +local open_data_file = open_read_file + callback.register('find_read_file' , find_read_file ) callback.register('open_read_file' , open_read_file ) callback.register('find_write_file', find_write_file) + +callback.register('find_data_file' , find_data_file ) +callback.register('open_data_file' , open_data_file ) diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua index 5b46b403622..e0c69d2079b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-env.lua @@ -11,7 +11,8 @@ -- sense. Much of this evolved before bytecode arrays were available and so a lot of -- code has disappeared already. -local rawset, rawget, loadfile, assert = rawset, rawget, loadfile, assert +local rawset, rawget, loadfile = rawset, rawget, loadfile +local gsub = string.gsub local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) @@ -123,7 +124,7 @@ function environment.loadluafile(filename, version) luaname = file.addsuffix(basename,luasuffixes.lua) lucname = file.addsuffix(basename,luasuffixes.luc) else - luaname = basename -- forced suffix + luaname = filename -- forced suffix lucname = nil end -- when not overloaded by explicit suffix we look for a luc file first @@ -136,7 +137,7 @@ function environment.loadluafile(filename, version) chunk = loadfile(fullname) -- this way we don't need a file exists check end if chunk then - assert(chunk)() + chunk() if version then -- we check of the version number of this chunk matches local v = version -- can be nil @@ -168,9 +169,24 @@ function environment.loadluafile(filename, version) report_lua("unknown file %a",filename) end else - assert(chunk)() + chunk() return true end end return false end + +environment.filenames = setmetatable( { }, { + __index = function(t,k) + local v = environment.files[k] + if v then + return (gsub(v,"%.+$","")) + end + end, + __newindex = function(t,k) + -- nothing + end, + __len = function(t) + return #environment.files + end, +} ) diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua index 806caefe621..2996ae66ab0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-fio.lua @@ -70,12 +70,16 @@ if not resolvers.initialized() then return okay or "" end + resolvers.findpk = findpk + -- register('process_jobname' , function(name) return name end, true) register('find_read_file' , function(id,name) return findtexfile(name) end, true) register('open_read_file' , function( name) return opentexfile(name) end, true) register('find_data_file' , function(name) return findbinfile(name,"tex") end, true) + register('open_data_file' , function(name) return opentexfile(name) end, true) + register('find_enc_file' , function(name) return findbinfile(name,"enc") end, true) register('find_font_file' , function(name) return findbinfile(name,"tfm") end, true) -- register('find_format_file' , function(name) return findbinfile(name,"fmt") end, true) diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua index 30c55eeccfd..1c9222d95d1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-fmt.lua @@ -19,9 +19,9 @@ local function primaryflags() if arguments.silent then flags[#flags+1] = "--interaction=batchmode" end - if arguments.jit then - flags[#flags+1] = "--jiton" - end + -- if arguments.jit then + -- flags[#flags+1] = "--jiton" + -- end return concat(flags," ") end @@ -48,10 +48,16 @@ local function secondaryflags() if arguments.ansi then flags[#flags+1] = "--c:ansi" end + if arguments.strip then + flags[#flags+1] = "--c:strip" + end + if arguments.lmtx then + flags[#flags+1] = "--c:lmtx" + end return concat(flags," ") end --- The silent option is Taco. It's a bit of a hack because we cannot yet mess +-- The silent option is for Taco. It's a bit of a hack because we cannot yet mess -- with directives. In fact, I could probably clean up the maker a bit by now. local template = [[--ini %primaryflags% --lua=%luafile% %texfile% %secondaryflags% %dump% %redirect%]] diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua index de725492200..ffd402c7752 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.lua @@ -25,15 +25,19 @@ if not global then global = _G end -LUATEXVERSION = status.luatex_version/100 - + tonumber(status.luatex_revision)/1000 +LUATEXVERSION = status.luatex_version/100 + + tonumber(status.luatex_revision)/1000 -LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) - or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") +LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) + or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") -JITSUPPORTED = LUATEXENGINE == "luajittex" or jit +LUATEXFUNCTIONALITY = status.development_id or 6346 -INITEXMODE = status.ini_version +JITSUPPORTED = LUATEXENGINE == "luajittex" or jit + +INITEXMODE = status.ini_version + +CONTEXTLMTXMODE = CONTEXTLMTXMODE or (status.obj_ptr == nil and 2 or 1) function os.setlocale() -- no need for a message diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv index 872d27e7726..da5a3a3109f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-ini.mkiv @@ -265,55 +265,84 @@ % \def\syst_helpers_checked_stripped_csname#1% % {\if\noexpand#1\letterbackslash\else#1\fi} -\normalprotected\def\installctxfunction#1#2% expandable - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installctxscanner#1#2% expandable - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installprotectedctxfunction#1#2% protected - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installprotectedctxscanner#1#2% protected - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} - -% not yet used - -\ifdefined\luafunctioncall \else - \protected\def\luafunctioncall{\luafunctioncall} -\fi +\ifdefined\normalluadef + + \normalprotected\def\installctxfunction#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax} + + \normalprotected\def\installctxscanner#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax} + + \normalprotected\def\installprotectedctxfunction#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\normalprotected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax} + + \normalprotected\def\installprotectedctxscanner#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\normalprotected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax} + + \normalprotected\def\resetctxscanner#1% + {\edef\m_syst_name{\csstring#1}% + \expandafter\glet\csname\m_syst_name\endcsname\relax} + + % \let\installctxfunctioncall \installctxfunction + % \let\installctxscannercall \installctxscanner + % \let\installprotectedctxfunctioncall\installprotectedctxfunction + % \let\installprotectedctxscannercall \installprotectedctxscanner + +\else + + \ifdefined\luafunctioncall \else + \normalprotected\def\luafunctioncall{\luafunction} + \fi + + \normalprotected\def\installctxfunction#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax + \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} + + \normalprotected\def\installctxscanner#1#2% expandable + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax + \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}} + + \normalprotected\def\installprotectedctxfunction#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax + \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} + + \normalprotected\def\installprotectedctxscanner#1#2% protected + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax + \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} + + \normalprotected\def\resetctxscanner#1% + {\edef\m_syst_name{\csstring#1}% + \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\zerocount + \expandafter\glet\csname\m_syst_name\endcsname\relax} + + % \normalprotected\def\installctxfunctioncall#1#2% + % {\edef\m_syst_name{\csstring#1}% + % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax + % \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} + % + % \normalprotected\def\installctxscannercall#1#2% + % {\edef\m_syst_name{\csstring#1}% + % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax + % \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} + % + % \normalprotected\def\installprotectedctxfunctioncall#1#2% + % {\edef\m_syst_name{\csstring#1}% + % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax + % \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} + % + % \normalprotected\def\installprotectedctxscannercall#1#2% + % {\edef\m_syst_name{\csstring#1}% + % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax + % \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} -\normalprotected\def\installctxfunctioncall#1#2% - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installctxscannercall#1#2% - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax - \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installprotectedctxfunctioncall#1#2% - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax - \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\installprotectedctxscannercall#1#2% - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax - \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}} - -\normalprotected\def\resetctxscanner#1% - {\edef\m_syst_name{\csstring#1}% - \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\zerocount - \global\expandafter\let\csname\m_syst_name\endcsname\relax} +\fi \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv index 0df31a4e54e..d5f6099ca79 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-lib.mkiv @@ -19,7 +19,7 @@ \registerctxluafile{util-sac}{optimize} \registerctxluafile{util-sto}{} % could also be done in trac-deb.mkiv \registerctxluafile{util-pck}{} -\registerctxluafile{util-seq}{} +% \registerctxluafile{util-seq}{} %registerctxluafile{util-mrg}{} % not needed in context itself, only mtxrun %registerctxluafile{util-lua}{} % moved \registerctxluafile{util-prs}{} @@ -35,11 +35,25 @@ \registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv \registerctxluafile{util-tpl}{} % needs tracker +\registerctxluafile{util-seq}{} \registerctxluafile{util-sta}{} \registerctxluafile{util-sbx}{} % needs tracker and templates +\registerctxluafile{util-soc-imp-reset} {} +\registerctxluafile{util-soc-imp-socket} {} +%registerctxluafile{util-soc-imp-copas} {} +\registerctxluafile{util-soc-imp-ltn12} {} +%registerctxluafile{util-soc-imp-mbox} {} +\registerctxluafile{util-soc-imp-mime} {} +\registerctxluafile{util-soc-imp-url} {} +\registerctxluafile{util-soc-imp-headers}{} +\registerctxluafile{util-soc-imp-http} {} +\registerctxluafile{util-soc-imp-tp} {} +%registerctxluafile{util-soc-imp-ftp} {} +%registerctxluafile{util-soc-imp-smtp} {} + \registerctxluafile{data-ini}{} \registerctxluafile{data-exp}{} \registerctxluafile{data-env}{} diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua index 59fb0b9371a..98f98177705 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-run.lua @@ -115,6 +115,29 @@ local function wrapup_synctex() synctex.wrapup() end +-- For Taco ... + +local sequencers = utilities.sequencers +local appendgroup = sequencers.appendgroup +local appendaction = sequencers.appendaction +local wrapupactions = sequencers.new { } + +appendgroup(wrapupactions,"system") +appendgroup(wrapupactions,"user") + +local function wrapup_run() + local runner = wrapupactions.runner + if runner then + runner() + end +end + +function luatex.wrapup(action) + appendaction(wrapupactions,"user",action) +end + +appendaction(wrapupactions,"system",synctex.wrapup) + -- this can be done later callbacks.register('start_run', start_run, "actions performed at the beginning of a run") @@ -126,20 +149,26 @@ callbacks.register('stop_run', stop_run, "actions perf callbacks.register('report_output_pages', report_output_pages, "actions performed when reporting pages") callbacks.register('report_output_log', report_output_log, "actions performed when reporting log file") -callbacks.register('start_page_number', start_shipout_page, "actions performed at the beginning of a shipout") -callbacks.register('stop_page_number', stop_shipout_page, "actions performed at the end of a shipout") +---------.register('start_page_number', start_shipout_page, "actions performed at the beginning of a shipout") +---------.register('stop_page_number', stop_shipout_page, "actions performed at the end of a shipout") + +callbacks.register('start_page_number', function() end, "actions performed at the beginning of a shipout") +callbacks.register('stop_page_number', function() end, "actions performed at the end of a shipout") callbacks.register('process_input_buffer', false, "actions performed when reading data") callbacks.register('process_output_buffer', false, "actions performed when writing data") callbacks.register("pre_dump", pre_dump_actions, "lua related finalizers called before we dump the format") -- comes after \everydump -if LUATEXFUNCTIONALITY and LUATEXFUNCTIONALITY > 6505 then - callbacks.register("finish_synctex", wrapup_synctex, "rename temporary synctex file") - callbacks.register('wrapup_run', false, "actions performed after closing files") -else - callbacks.register("finish_synctex_callback", wrapup_synctex, "rename temporary synctex file") -end +-- finish_synctex might go away (move to wrapup_run) + +callbacks.register("finish_synctex", wrapup_synctex, "rename temporary synctex file") +callbacks.register('wrapup_run', wrapup_run, "actions performed after closing files") + +-- temp hack for testing: + +callbacks.functions.start_page_number = start_shipout_page +callbacks.functions.stop_page_number = stop_shipout_page -- an example: @@ -176,14 +205,6 @@ luatex.registerstopactions(luatex.cleanuptempfiles) -- filenames -local types = { - "data", - "font map", - "image", - "font subset", - "full font", -} - local report_open = logs.reporter("open source") local report_close = logs.reporter("close source") local report_load = logs.reporter("load resource") @@ -199,15 +220,8 @@ function luatex.currentfile() return stack[#stack] or tex.jobname end -local function report_start(left,name) - if not left then - -- skip - elseif left ~= 1 then - if all then - -- report_load("%s > %s",types[left],name or "?") - report_load("type %a, name %a",types[left],name or "?") - end - elseif find(name,"virtual://",1,true) then +local function report_start(name) + if find(name,"virtual://",1,true) then insert(stack,false) else insert(stack,name) @@ -219,16 +233,47 @@ local function report_start(left,name) end end -local function report_stop(right) - if level == 1 or not right or right == 1 then - local name = remove(stack) - if name then - -- report_close("%i > %i > %s",level,total,name or "?") - report_close("level %i, order %i, name %a",level,total,name or "?") - level = level - 1 - synctex.setfilename(stack[#stack] or tex.jobname) +local function report_stop() + local name = remove(stack) + if name then + -- report_close("%i > %i > %s",level,total,name or "?") + report_close("level %i, order %i, name %a",level,total,name or "?") + level = level - 1 + synctex.setfilename(stack[#stack] or tex.jobname) + end +end + +if CONTEXTLMTXMODE < 2 then + + local types = { + "data", + "font map", + "image", + "font subset", + "full font", + } + + local do_report_start = report_start + local do_report_stop = report_stop + + report_start = function(left,name) + if not left then + -- skip + elseif left ~= 1 then + if all then + report_load("type %a, name %a",types[left],name or "?") + end + else + do_report_start(name) + end + end + + report_stop = function(right) + if level == 1 or not right or right == 1 then + do_report_stop() end end + end local function report_none() diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua deleted file mode 100644 index 9342a4b3375..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-soc.lua +++ /dev/null @@ -1,11 +0,0 @@ --- This is just a loader. The package handler knows about the TEX tree. - --- require "luatex/lua/socket.lua" --- require "luatex/lua/ltn12.lua" --- require "luatex/lua/mime.lua" --- require "luatex/lua/socket/http.lua" --- require "luatex/lua/socket/url.lua" --- require "luatex/lua/socket/tp.lua" --- require "luatex/lua/socket/ftp.lua" - --- "luatex/lua/socket/smtp.lua" diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-soc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-soc.mkiv new file mode 100644 index 00000000000..b2ce7048395 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-soc.mkiv @@ -0,0 +1,52 @@ +%D \module +%D [ file=luat-soc, +%D version=2018.08.05, +%D title=\CONTEXT\ Lua Macros, +%D subtitle=Socket Libraries, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Lua Macros / Socket Libraries} + +%D In \LUATEX\ we provide the socket library that is more or less the standard one +%D for \LUA. It has been around for a while and seems to be pretty stable. The +%D binary module is copmpiled into \LUATEX\ and the accompanying .lua files are +%D preloaded. These files are mostly written by Diego Nehab, Andre Carregal, Javier +%D Guerra, and Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall, +%D David Burgess, Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals +%D are part of and copyrighted by the Kepler project. +%D +%D Here we reload a slightly reworked version of these \type {.lua} files. We keep +%D the same (documented) interface but streamlined some fo the code. No more +%D modules, no more pre 5.2 \LUA, etc. Also, as it loads into the \CONTEXT +%D ecosystem, we plug in some logging. (and maybe tracing in the future). As we +%D don't support serial ports in \LUATEX, related code has been dropped. +%D +%D The files are reformatted so that we can more easilly add additional features +%D and|/|or tracing options. Any error introduced there is our fault! The url module +%D might be replaced by the one in \CONTEXT. When we need mbox a suitable variant +%D will be provided. + +%D Currently we preload the related \LUA\ code in \LUATEX, but that might change at +%D some point. We're prepared for that. + +% \registerctxluafile{util-soc-imp-reset} {} +% +% \registerctxluafile{util-soc-imp-socket} {} +% % registerctxluafile{util-soc-imp-copas} {} +% \registerctxluafile{util-soc-imp-ltn12} {} +% % registerctxluafile{util-soc-imp-mbox} {} +% \registerctxluafile{util-soc-imp-mime} {} +% \registerctxluafile{util-soc-imp-url} {} +% \registerctxluafile{util-soc-imp-headers}{} +% \registerctxluafile{util-soc-imp-http} {} +% \registerctxluafile{util-soc-imp-tp} {} +% % registerctxluafile{util-soc-imp-ftp} {} +% % registerctxluafile{util-soc-imp-smtp} {} + +\endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua index e67830b0db4..ce891765aa9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-sto.lua @@ -78,7 +78,7 @@ if environment.initex then dumped = concat({ definition, comment, dumped },"\n") local code = nil local name = formatters["slot %s (%s)"](max,name) - if LUAVERSION >= 5.3 and LUATEXFUNCTIONALITY >= 6454 then + if LUAVERSION >= 5.3 then local code = loadstring(dumped,name) setbytecode(max,code,strip) else diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua index ebcb0f0e82a..b49379bbf05 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.lua @@ -26,8 +26,6 @@ local io = io local os = os local lpeg = lpeg -local luanames = lua.name -- luatex itself - local setmetatableindex = table.setmetatableindex local load = load local xpcall = xpcall @@ -135,7 +133,6 @@ local function registername(name,message) messages[lnn] = message numbers[name] = lnn end - luanames[lnn] = instance_banner(message) local report = reporter("lua instance",message) local proxy = { -- we can access all via: diff --git a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv index 760de9f213f..f3868ccf4bc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/luat-usr.mkiv @@ -69,7 +69,7 @@ \obeyluatokens \csname\??luacode#1\endcsname}% % - \global\expandafter\let\csname\s!stop#1\s!code\endcsname\relax + \expandafter\glet\csname\s!stop#1\s!code\endcsname\relax % \normalexpanded{\xdef\csname\??luacode#1\endcsname##1\csname\s!stop#1\s!code\endcsname}% {\noexpand\expandafter\endgroup @@ -77,7 +77,7 @@ \expandafter\noexpand\csname clf_\fullname\endcsname \noexpand\expandafter{\noexpand\normalexpanded{##1}}}% % - \global\expandafter\let\csname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname + \expandafter\glet\csname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname \fi \fi \egroup} diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua index 78cf1d6bd58..ed0f03fd8c7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-aux.lua @@ -134,10 +134,12 @@ end function xml.collect_tags(root, pattern, nonamespace) local collected = xmlapplylpath(root,pattern) if collected then - local t, n = { }, 0 + local t = { } + local n = 0 for c=1,#collected do - local e = collected[c] - local ns, tg = e.ns, e.tg + local e = collected[c] + local ns = e.ns + local tg = e.tg n = n + 1 if nonamespace then t[n] = tg @@ -226,7 +228,7 @@ function xml.delete(root,pattern) if trace_manipulations then report('deleting',pattern,c,e) end - local d = p.dt + local d = p.dt local ni = e.ni if ni <= #d then if false then @@ -313,8 +315,10 @@ local function inject_element(root,pattern,whatever,prepend) local element = root and xmltoelement(whatever,root) local collected = element and xmlapplylpath(root,pattern) local function inject_e(e) - local r = e.__p__ - local d, k, rri = r.dt, e.ni, r.ri + local r = e.__p__ + local d = r.dt + local k = e.ni + local rri = r.ri local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt) if edt then local be, af @@ -354,7 +358,8 @@ local function insert_element(root,pattern,whatever,before) -- todo: element als local collected = element and xmlapplylpath(root,pattern) local function insert_e(e) local r = e.__p__ - local d, k = r.dt, e.ni + local d = r.dt + local k = e.ni if not before then k = k + 1 end @@ -860,8 +865,10 @@ function xml.separate(x,pattern) report_xml("warning: xml.separate changes root") x = d end - local t, n = { "\n" }, 1 - local i, nd = 1, #d + local t = { "\n" } + local n = 1 + local i = 1 + local nd = #d while i <= nd do while i <= nd do local di = d[i] diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua index 1787c53df18..b0f5c9b72f6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-css.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lxml-css'] = { license = "see context related readme files" } -local tonumber, rawset, type = tonumber, rawset, type +local tonumber, rawset, type, select = tonumber, rawset, type, select local lower, format, find, gmatch = string.lower, string.format, string.find, string.gmatch local topattern, is_empty = string.topattern, string.is_empty local P, S, C, R, Cb, Cg, Carg, Ct, Cc, Cf, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg, lpeg.Ct, lpeg.Cc, lpeg.Cf, lpeg.Cs @@ -118,24 +118,33 @@ css.padding = padding -- print(padding("0",pixel,hsize,exheight,emwidth)) --- local currentfont = font.current --- local texget = tex.get --- local hashes = fonts.hashes --- local quads = hashes.quads --- local xheights = hashes.xheights --- --- local function padding(str) --- local font = currentfont() --- local exheight = xheights[font] --- local emwidth = quads[font] --- local hsize = texget("hsize")/100 --- local pixel = emwidth/100 --- return padding(str,pixel,hsize,exheight,emwidth) --- end --- --- function css.simplepadding(str) --- context("%ssp",padding(str,pixel,hsize,exheight,emwidth)) --- end +local context = context + +if context then + + local currentfont = font.current + local texget = tex.get + local hashes = fonts.hashes + local quads = hashes.quads + local xheights = hashes.xheights + + local function todimension(str) + local font = currentfont() + local exheight = xheights[font] + local emwidth = quads[font] + local hsize = texget("hsize")/100 + local pixel = emwidth/100 + return dimension(str,pixel,hsize,exheight,emwidth) + end + + css.todimension = todimension + + function context.cssdimension(str) + -- context("%ssp",todimension(str)) + context(todimension(str) .. "sp") + end + +end local pattern = Cf( Ct("") * ( Cg( @@ -949,7 +958,7 @@ local someaction = skipspace * colon * skipspace * (somevalue/ctx_sprint) -- -- cache patterns (2.13): -local patterns= setmetatableindex(function(t,k) +local patterns = setmetatableindex(function(t,k) local v = P(k * someaction + 1)^0 t[k] = v return v @@ -993,3 +1002,91 @@ interfaces.implement { actions = css.mappedstylevalue, arguments = "3 strings", } + +-- more (for mm) + +local containsws = string.containsws +local classsplitter = lpeg.tsplitat(whitespace^1) + +function xml.functions.classes(e,class) -- cache + if class then + local at = e.at + local data = at[class] or at.class + if data then + return lpegmatch(classsplitter,data) or { } + end + end + return { } +end + +-- function xml.functions.hasclass(e,class,name) +-- if class then +-- local at = e.at +-- local data = at[class] or at.class +-- if data then +-- return data == name or containsws(data,name) +-- end +-- end +-- return false +-- end +-- +-- function xml.expressions.hasclass(attribute,name) +-- if attribute then +-- return attribute == name or containsws(attribute,name) +-- end +-- return false +-- end + +function xml.functions.hasclass(e,class,name,more,...) + if class and name then + local at = e.at + local data = at[class] or at.class + if not data or data == "" then + return false + end + if data == name or data == more then + return true + end + if containsws(data,name) then + return true + end + if not more then + return false + end + if containsws(data,more) then + return true + end + for i=1,select("#",...) do + if containsws(data,select(i,...)) then + return true + end + end + end + return false +end + +function xml.expressions.hasclass(data,name,more,...) + if data then + if not data or data == "" then + return false + end + if data == name or data == more then + return true + end + if containsws(data,name) then + return true + end + if not more then + return false + end + if containsws(data,more) then + return true + end + for i=1,select("#",...) do + if containsws(data,select(i,...)) then + return true + end + end + end + return false +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua index 8d99d627031..6fb64c0fef6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-inf.lua @@ -17,7 +17,8 @@ local getid = lxml.getid local status, stack local function get(e,d) - local ns, tg = e.ns, e.tg + local ns = e.ns + local tg = e.tg local name = tg if ns ~= "" then name = ns .. ":" .. tg end stack[d] = name diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv index 7c97ffb2c77..5cb4bb22d65 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-ini.mkiv @@ -36,11 +36,11 @@ % for now indirect -\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}} -\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange {#1}{#2}{#3}{#4}{\detokenize{#5}}} -\def\xmlload #1#2{\clf_xmlload {#1}{#2}{\directxmlparameter\c!compress}} -\def\xmlloadbuffer #1#2{\clf_xmlloadbuffer {#1}{#2}{\directxmlparameter\c!compress}} -\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}} +\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}} +\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}} +\def\xmlload #1#2{\clf_xmlload {#1}{#2}{\directxmlparameter\c!compress}} +\def\xmlloadbuffer #1#2{\clf_xmlloadbuffer {#1}{#2}{\directxmlparameter\c!compress}} +\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}} % aliased @@ -231,6 +231,7 @@ \unexpanded\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}} \unexpanded\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}} +\unexpanded\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply * \unexpanded\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2 \let\xmlregistersetup \xmlappendsetup @@ -240,7 +241,7 @@ \unexpanded\def\xmlregisteredsetups {\xmlstarttiming - \xmlflushsetups + \xmlflushsetups\xmldocument \xmldefaulttotext\xmldocument % after include \xmlstoptiming} @@ -260,8 +261,8 @@ %xmlpushdocument{#3}% #2{#3}{#4}% \setcatcodetable\notcatcodes - \doifelsenothing{#5} - {\xmlsetup{#3}{xml:process}} + \doifelsenothing{#5}% + {\xmlsetup{#3}{xml:process}}% {\xmlsetup{#3}{#5}}% %xmlpopdocument \endgroup} @@ -326,7 +327,7 @@ \fi \unexpanded\def\stopxmldisplayverbatim {\endofverbatimlines - \stoppacked} + \stoppacked}% \doinitializeverbatim \beginofverbatimlines} @@ -404,7 +405,7 @@ \c!entities=\v!no] % load big entity file \appendtoks - \doif{\directxmlparameter\c!entities}\clf_xmlloadentities + \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities \to \everysetupxml \def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua index bb6fb456816..392c1a4014e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-lpt.lua @@ -157,32 +157,47 @@ apply_axis['root'] = function(list) end apply_axis['self'] = function(list) ---~ local collected = { } ---~ for l=1,#list do ---~ collected[l] = list[l] ---~ end ---~ return collected + -- local collected = { } + -- for l=1,#list do + -- collected[l] = list[l] + -- end + -- return collected return list end apply_axis['child'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] local dt = ll.dt if dt then -- weird that this is needed - local en = 0 - for k=1,#dt do - local dk = dt[k] + local n = #dt + if n == 0 then + ll.en = 0 + elseif n == 1 then + local dk = dt[1] if dk.tg then c = c + 1 collected[c] = dk - dk.ni = k -- refresh - en = en + 1 - dk.ei = en + dk.ni = 1 -- refresh + dk.ei = 1 + ll.en = 1 end + else + local en = 0 + for k=1,#dt do + local dk = dt[k] + if dk.tg then + c = c + 1 + en = en + 1 + collected[c] = dk + dk.ni = k -- refresh + dk.ei = en + end + end + ll.en = en end - ll.en = en end end return collected @@ -191,25 +206,43 @@ end local function collect(list,collected,c) local dt = list.dt if dt then - local en = 0 - for k=1,#dt do - local dk = dt[k] + local n = #dt + if n == 0 then + list.en = 0 + elseif n == 1 then + local dk = dt[1] if dk.tg then c = c + 1 collected[c] = dk - dk.ni = k -- refresh - en = en + 1 - dk.ei = en + dk.ni = 1 -- refresh + dk.ei = 1 c = collect(dk,collected,c) + list.en = 1 + else + list.en = 0 end + else + local en = 0 + for k=1,n do + local dk = dt[k] + if dk.tg then + c = c + 1 + en = en + 1 + collected[c] = dk + dk.ni = k -- refresh + dk.ei = en + c = collect(dk,collected,c) + end + end + list.en = en end - list.en = en end return c end apply_axis['descendant'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do c = collect(list[l],collected,c) end @@ -219,24 +252,41 @@ end local function collect(list,collected,c) local dt = list.dt if dt then - local en = 0 - for k=1,#dt do - local dk = dt[k] + local n = #dt + if n == 0 then + list.en = 0 + elseif n == 1 then + local dk = dt[1] if dk.tg then c = c + 1 collected[c] = dk - dk.ni = k -- refresh - en = en + 1 - dk.ei = en + dk.ni = 1 -- refresh + dk.ei = 1 c = collect(dk,collected,c) + list.en = 1 end + else + local en = 0 + for k=1,#dt do + local dk = dt[k] + if dk.tg then + c = c + 1 + en = en + 1 + collected[c] = dk + dk.ni = k -- refresh + dk.ei = en + c = collect(dk,collected,c) + end + end + list.en = en end - list.en = en end return c end + apply_axis['descendant-or-self'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] if ll.special ~= true then -- catch double root @@ -249,7 +299,8 @@ apply_axis['descendant-or-self'] = function(list) end apply_axis['ancestor'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] while ll do @@ -264,7 +315,8 @@ apply_axis['ancestor'] = function(list) end apply_axis['ancestor-or-self'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] c = c + 1 @@ -281,7 +333,8 @@ apply_axis['ancestor-or-self'] = function(list) end apply_axis['parent'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local pl = list[l].__p__ if pl then @@ -301,45 +354,47 @@ apply_axis['namespace'] = function(list) end apply_axis['following'] = function(list) -- incomplete ---~ local collected, c = { }, 0 ---~ for l=1,#list do ---~ local ll = list[l] ---~ local p = ll.__p__ ---~ local d = p.dt ---~ for i=ll.ni+1,#d do ---~ local di = d[i] ---~ if type(di) == "table" then ---~ c = c + 1 ---~ collected[c] = di ---~ break ---~ end ---~ end ---~ end ---~ return collected + -- local collected, c = { }, 0 + -- for l=1,#list do + -- local ll = list[l] + -- local p = ll.__p__ + -- local d = p.dt + -- for i=ll.ni+1,#d do + -- local di = d[i] + -- if type(di) == "table" then + -- c = c + 1 + -- collected[c] = di + -- break + -- end + -- end + -- end + -- return collected return { } end apply_axis['preceding'] = function(list) -- incomplete ---~ local collected, c = { }, 0 ---~ for l=1,#list do ---~ local ll = list[l] ---~ local p = ll.__p__ ---~ local d = p.dt ---~ for i=ll.ni-1,1,-1 do ---~ local di = d[i] ---~ if type(di) == "table" then ---~ c = c + 1 ---~ collected[c] = di ---~ break ---~ end ---~ end ---~ end ---~ return collected + -- local collected = { } + -- local c = 0 + -- for l=1,#list do + -- local ll = list[l] + -- local p = ll.__p__ + -- local d = p.dt + -- for i=ll.ni-1,1,-1 do + -- local di = d[i] + -- if type(di) == "table" then + -- c = c + 1 + -- collected[c] = di + -- break + -- end + -- end + -- end + -- return collected return { } end apply_axis['following-sibling'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] local p = ll.__p__ @@ -356,7 +411,8 @@ apply_axis['following-sibling'] = function(list) end apply_axis['preceding-sibling'] = function(list) - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] local p = ll.__p__ @@ -373,7 +429,8 @@ apply_axis['preceding-sibling'] = function(list) end apply_axis['reverse-sibling'] = function(list) -- reverse preceding - local collected, c = { }, 0 + local collected = { } + local c = 0 for l=1,#list do local ll = list[l] local p = ll.__p__ @@ -400,7 +457,8 @@ local function apply_nodes(list,directive,nodes) -- ... currently ignored local maxn = #nodes if maxn == 3 then --optimized loop - local nns, ntg = nodes[2], nodes[3] + local nns = nodes[2] + local ntg = nodes[3] if not nns and not ntg then -- wildcard if directive then return list @@ -408,40 +466,47 @@ local function apply_nodes(list,directive,nodes) return { } end else - local collected, c, m, p = { }, 0, 0, nil + local collected = { } + local c = 0 + local m = 0 + local p = nil if not nns then -- only check tag for l=1,#list do - local ll = list[l] + local ll = list[l] local ltg = ll.tg if ltg then if directive then if ntg == ltg then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end elseif ntg ~= ltg then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end end end elseif not ntg then -- only check namespace for l=1,#list do - local ll = list[l] + local ll = list[l] local lns = ll.rn or ll.ns if lns then if directive then if lns == nns then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end elseif lns ~= nns then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end end end @@ -454,14 +519,16 @@ local function apply_nodes(list,directive,nodes) local ok = ltg == ntg and lns == nns if directive then if ok then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end elseif not ok then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end end end @@ -469,15 +536,19 @@ local function apply_nodes(list,directive,nodes) return collected end else - local collected, c, m, p = { }, 0, 0, nil + local collected = { } + local c = 0 + local m = 0 + local p = nil for l=1,#list do - local ll = list[l] + local ll = list[l] local ltg = ll.tg if ltg then local lns = ll.rn or ll.ns - local ok = false + local ok = false for n=1,maxn,3 do - local nns, ntg = nodes[n+1], nodes[n+2] + local nns = nodes[n+1] + local ntg = nodes[n+2] ok = (not ntg or ltg == ntg) and (not nns or lns == nns) if ok then break @@ -485,14 +556,16 @@ local function apply_nodes(list,directive,nodes) end if directive then if ok then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end elseif not ok then - local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end + local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end c = c + 1 - collected[c], ll.mi = ll, m + collected[c] = ll + ll.mi = m end end end @@ -503,7 +576,8 @@ end local quit_expression = false local function apply_expression(list,expression,order) - local collected, c = { }, 0 + local collected = { } + local c = 0 quit_expression = false for l=1,#list do local ll = list[l] @@ -900,7 +974,8 @@ local function tagstostring(list) local t = { } for i=1, #list do local li = list[i] - local ns, tg = li.ns, li.tg + local ns = li.ns + local tg = li.tg if not ns or ns == "" then ns = "*" end if not tg or tg == "" then tg = "*" end t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg) @@ -1365,7 +1440,8 @@ expressions.name = function(e,n) -- ns + tg if n == 0 then found = type(e) == "table" and e elseif n < 0 then - local d, k = e.__p__.dt, e.ni + local d = e.__p__.dt + local k = e.ni for i=k-1,1,-1 do local di = d[i] if type(di) == "table" then @@ -1378,7 +1454,8 @@ expressions.name = function(e,n) -- ns + tg end end else - local d, k = e.__p__.dt, e.ni + local d = e.__p__.dt + local k = e.ni for i=k+1,#d,1 do local di = d[i] if type(di) == "table" then @@ -1392,7 +1469,8 @@ expressions.name = function(e,n) -- ns + tg end end if found then - local ns, tg = found.rn or found.ns or "", found.tg + local ns = found.rn or found.ns or "" + local tg = found.tg if ns ~= "" then return ns .. ":" .. tg else @@ -1412,7 +1490,8 @@ expressions.tag = function(e,n) -- only tg if n == 0 then found = (type(e) == "table") and e -- seems to fail elseif n < 0 then - local d, k = e.__p__.dt, e.ni + local d = e.__p__.dt + local k = e.ni for i=k-1,1,-1 do local di = d[i] if type(di) == "table" then @@ -1425,7 +1504,8 @@ expressions.tag = function(e,n) -- only tg end end else - local d, k = e.__p__.dt, e.ni + local d = e.__p__.dt + local k = e.ni for i=k+1,#d,1 do local di = d[i] if type(di) == "table" then @@ -1592,8 +1672,8 @@ end -- local w = lpeg.patterns.whitespace -- local p = w^0 * lpeg.Cf(lpeg.Ct("") * lpeg.Cg(lpeg.C((1-w)^1) * lpeg.Cc(true) * w^0)^1,rawset) --- function xml.functions.classes(e) -- cache --- local class = e.at.class +-- function xml.functions.classes(e,class) -- cache +-- class = class and e.at[class] or e.at.class -- if class then -- return lpegmatch(p,class) -- else diff --git a/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua index b8280ba9c63..ae3edba5613 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/lxml-tex.lua @@ -92,6 +92,8 @@ local forceraw = false local p_texescape = patterns.texescape +local tokenizedcs = context.tokenizedcs + directives.enable("xml.path.keeplastmatch") -- tex entities @@ -499,13 +501,29 @@ function lxml.checkindex(name) return root and root.index or 0 end -function lxml.withindex(name,n,command) -- will change as name is always there now - local i, p = lpegmatch(splitter,n) - if p then - contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}") - else - contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}") +if tokenizedcs then + + function lxml.withindex(name,n,command) -- will change as name is always there now + local i, p = lpegmatch(splitter,n) + local w = tokenizedcs.xmlw + if p then + contextsprint(ctxcatcodes,w,"{",command,"}{",n,"}") + else + contextsprint(ctxcatcodes,w,"{",command,"}{",name,"::",n,"}") + end + end + +else + + function lxml.withindex(name,n,command) -- will change as name is always there now + local i, p = lpegmatch(splitter,n) + if p then + contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}") + else + contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}") + end end + end function lxml.getindex(name,n) -- will change as name is always there now @@ -728,21 +746,6 @@ end local default_element_handler = xml.gethandlers("verbose").functions["@el@"] --- local xmlw = setmetatableindex(function(t,k) --- local v = setmetatableindex(function(t,kk) --- local v --- if kk == false then --- v = "\\xmlw{" .. k .. "}{" --- else --- v = "\\xmlw{" .. k .. "}{" .. kk .. "::" --- end --- t[kk] = v --- return v --- end) --- t[k]= v --- return v --- end) - local setfilename = false local trace_name = false local report_name = logs.reporter("lxml") @@ -765,39 +768,80 @@ trackers.register("system.synctex.xml",function(v) trace_name = v end) -local function tex_element(e,handlers) - if setfilename then - syncfilename(e,"element") - end - local command = e.command - if command == nil then - default_element_handler(e,handlers) - elseif command == true then - -- text (no ) / so, no mkii fallback then - handlers.serialize(e.dt,handlers) - elseif command == false then - -- ignore - else - local tc = type(command) - if tc == "string" then - local rootname, ix = e.name, e.ix - if rootname then - if not ix then - addindex(rootname,false,true) - ix = e.ix +local tex_element + +if tokenizedcs then + + tex_element = function(e,handlers) + if setfilename then + syncfilename(e,"element") + end + local command = e.command + if command == nil then + default_element_handler(e,handlers) + elseif command == true then + -- text (no ) / so, no mkii fallback then + handlers.serialize(e.dt,handlers) + elseif command == false then + -- ignore + else + local tc = type(command) + if tc == "string" then + local rootname, ix = e.name, e.ix + local w = tokenizedcs.xmlw + if rootname then + if not ix then + addindex(rootname,false,true) + ix = e.ix + end + contextsprint(ctxcatcodes,w,"{",command,"}{",rootname,"::",ix,"}") + else + report_lxml("fatal error: no index for %a",command) + contextsprint(ctxcatcodes,w,"{",command,"}{",ix or 0,"}") end - -- faster than context.xmlw - contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}") - -- contextsprint(ctxcatcodes,xmlw[command][rootname],ix,"}") - else - report_lxml("fatal error: no index for %a",command) - contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}") - -- contextsprint(ctxcatcodes,xmlw[command][false],ix or 0,"}") + elseif tc == "function" then + command(e) + end + end + end + +else + + tex_element = function(e,handlers) + if setfilename then + syncfilename(e,"element") + end + local command = e.command + if command == nil then + default_element_handler(e,handlers) + elseif command == true then + -- text (no ) / so, no mkii fallback then + handlers.serialize(e.dt,handlers) + elseif command == false then + -- ignore + else + local tc = type(command) + if tc == "string" then + local rootname, ix = e.name, e.ix + if rootname then + if not ix then + addindex(rootname,false,true) + ix = e.ix + end + -- faster than context.xmlw + contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}") + -- contextsprint(ctxcatcodes,xmlw[command][rootname],ix,"}") + else + report_lxml("fatal error: no index for %a",command) + contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}") + -- contextsprint(ctxcatcodes,xmlw[command][false],ix or 0,"}") + end + elseif tc == "function" then + command(e) end - elseif tc == "function" then - command(e) end end + end -- @@ -1180,7 +1224,7 @@ function lxml.flushsetups(id,...) local sd = setups[document] if sd then for k=1,#sd do - local v= sd[k] + local v = sd[k] if not done[v] then if trace_loading then report_lxml("applying setup %02i : %a to %a",k,v,document) @@ -1442,29 +1486,63 @@ end -- the number of commands is often relative small but there can be many calls -- to this finalizer -local function command(collected,cmd,otherwise) - local n = collected and #collected - if n and n > 0 then - local wildcard = find(cmd,"*",1,true) - for c=1,n do -- maybe optimize for n=1 - local e = collected[c] - local ix = e.ix - local name = e.name - if name and not ix then - addindex(name,false,true) - ix = e.ix - end - if not ix or not name then - report_lxml("no valid node index for element %a using command %s",name or "?",cmd) - elseif wildcard then - contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}") - else - contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}") +local command + +if tokenizedcs then + + command = function(collected,cmd,otherwise) + local n = collected and #collected + local w = tokenizedcs.xmlw + if n and n > 0 then + local wildcard = find(cmd,"*",1,true) + for c=1,n do -- maybe optimize for n=1 + local e = collected[c] + local ix = e.ix + local name = e.name + if name and not ix then + addindex(name,false,true) + ix = e.ix + end + if not ix or not name then + report_lxml("no valid node index for element %a using command %s",name or "?",cmd) + elseif wildcard then + contextsprint(ctxcatcodes,w,"{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}") + else + contextsprint(ctxcatcodes,w,"{",cmd,"}{",name,"::",ix,"}") + end + end + elseif otherwise then + contextsprint(ctxcatcodes,w,"{",otherwise,"}{#1}") + end + end + +else + + command = function(collected,cmd,otherwise) + local n = collected and #collected + if n and n > 0 then + local wildcard = find(cmd,"*",1,true) + for c=1,n do -- maybe optimize for n=1 + local e = collected[c] + local ix = e.ix + local name = e.name + if name and not ix then + addindex(name,false,true) + ix = e.ix + end + if not ix or not name then + report_lxml("no valid node index for element %a using command %s",name or "?",cmd) + elseif wildcard then + contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}") + else + contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}") + end end + elseif otherwise then + contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}") end - elseif otherwise then - contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}") end + end -- local wildcards = setmetatableindex(function(t,k) @@ -1675,7 +1753,7 @@ local function concatrange(collected,start,stop,separator,lastseparator,textonly end end -local function concat(collected,separator,lastseparator,textonly) -- test this on mml +local function concatlist(collected,separator,lastseparator,textonly) -- test this on mml concatrange(collected,false,false,separator,lastseparator,textonly) end @@ -1697,14 +1775,12 @@ texfinalizers.context = ctxtext texfinalizers.position = position texfinalizers.match = match texfinalizers.index = index -texfinalizers.concat = concat +texfinalizers.concat = concatlist texfinalizers.concatrange = concatrange texfinalizers.chainattribute = chainattribute texfinalizers.chainpath = chainpath texfinalizers.default = all -- !! -local concat = table.concat - function texfinalizers.tag(collected,n) if collected then local nc = #collected @@ -1997,7 +2073,7 @@ do implement { name = "xmldoifatt", arguments = "3 strings", - actions = function(id,l,v) + actions = function(id,k,v) local e = getid(id) ctx_doif(e and e.at[k] == v or false) end @@ -2006,7 +2082,7 @@ do implement { name = "xmldoifnotatt", arguments = "3 strings", - actions = function(id,l,v) + actions = function(id,k,v) local e = getid(id) ctx_doifnot(e and e.at[k] == v or false) end @@ -2015,7 +2091,7 @@ do implement { name = "xmldoifelseatt", arguments = "3 strings", - actions = function(id,l,v) + actions = function(id,k,v) local e = getid(id) ctx_doifelse(e and e.at[k] == v or false) end @@ -2139,24 +2215,51 @@ function lxml.direct(id) end end -function lxml.command(id,pattern,cmd) - local i, p = getid(id,true) - local collected = xmlapplylpath(getid(i),pattern) - if collected then - local nc = #collected - if nc > 0 then - local rootname = p or i.name - for c=1,nc do - local e = collected[c] - local ix = e.ix - if not ix then - addindex(rootname,false,true) - ix = e.ix +if tokenizedcs then + + function lxml.command(id,pattern,cmd) + local i, p = getid(id,true) + local collected = xmlapplylpath(getid(i),pattern) + if collected then + local nc = #collected + if nc > 0 then + local rootname = p or i.name + local w = tokenizedcs.xmlw + for c=1,nc do + local e = collected[c] + local ix = e.ix + if not ix then + addindex(rootname,false,true) + ix = e.ix + end + contextsprint(ctxcatcodes,w,"{",cmd,"}{",rootname,"::",ix,"}") + end + end + end + end + +else + + function lxml.command(id,pattern,cmd) + local i, p = getid(id,true) + local collected = xmlapplylpath(getid(i),pattern) + if collected then + local nc = #collected + if nc > 0 then + local rootname = p or i.name + for c=1,nc do + local e = collected[c] + local ix = e.ix + if not ix then + addindex(rootname,false,true) + ix = e.ix + end + contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}") end - contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}") end end end + end -- loops @@ -2292,13 +2395,13 @@ function texfinalizers.lettered(collected) end end ---~ function texfinalizers.apply(collected,what) -- to be tested ---~ if collected then ---~ for c=1,#collected do ---~ contextsprint(ctxcatcodes,what(collected[c].dt[1])) ---~ end ---~ end ---~ end +-- function texfinalizers.apply(collected,what) -- to be tested +-- if collected then +-- for c=1,#collected do +-- contextsprint(ctxcatcodes,what(collected[c].dt[1])) +-- end +-- end +-- end function lxml.toparameters(id) local e = getid(id) @@ -2357,49 +2460,56 @@ end -- parameters -function lxml.setatt(id,name,value) - local e = getid(id) - if e then - local a = e.at - if a then - a[name] = value - else - e.at = { [name] = value } +do + + local function setatt(id,name,value) + local e = getid(id) + if e then + local a = e.at + if a then + a[name] = value + else + e.at = { [name] = value } + end end end -end -function lxml.setpar(id,name,value) - local e = getid(id) - if e then - local p = e.pa - if p then - p[name] = value - else - e.pa = { [name] = value } + local function setpar(id,name,value) + local e = getid(id) + if e then + local p = e.pa + if p then + p[name] = value + else + e.pa = { [name] = value } + end end end -end -function lxml.setattribute(id,pattern,name,value) - local collected = xmlapplylpath(getid(id),pattern) - if collected then - for i=1,#collected do - setatt(collected[i],name,value) + lxml.setatt = setatt + lxml.setpar = setpar + + function lxml.setattribute(id,pattern,name,value) + local collected = xmlapplylpath(getid(id),pattern) + if collected then + for i=1,#collected do + setatt(collected[i],name,value) + end end end -end -function lxml.setparameter(id,pattern,name,value) - local collected = xmlapplylpath(getid(id),pattern) - if collected then - for i=1,#collected do - setpar(collected[i],name,value) + function lxml.setparameter(id,pattern,name,value) + local collected = xmlapplylpath(getid(id),pattern) + if collected then + for i=1,#collected do + setpar(collected[i],name,value) + end end end -end -lxml.setparam = lxml.setparameter + lxml.setparam = lxml.setparameter + +end -- relatively new: @@ -2629,3 +2739,59 @@ function texfinalizers.xml(collected,name,setup) buffers.assign(name,strip(xmltostring(root))) context.xmlprocessbuffer(name,name,setup or (name..":setup")) end + +-- experiment + +do + + local xmltoelement = xml.toelement + local xmlreindex = xml.reindex + + function lxml.replace(root,pattern,whatever) + if type(root) == "string" then + root = lxml.getid(root) + end + local collected = xmlapplylpath(root,pattern) + if collected then + local isstring = type(whatever) == "string" + for c=1,#collected do + local e = collected[c] + local p = e.__p__ + if p then + local d = p.dt + local n = e.ni + local w = isstring and whatever or whatever(e) + if w then + local t = xmltoelement(w,root).dt + if t then + t.__p__ = p + if type(t) == "table" then + local t1 = t[1] + d[n] = t1 + t1.at.type = e.at.type or t1.at.type + for i=2,#t do + n = n + 1 + insert(d,n,t[i]) + end + else + d[n] = t + end + xmlreindex(d) -- probably not needed + end + end + end + end + end + end + + -- function document.mess_around(root) + -- lxml.replace( + -- root, + -- "p[@variant='foo']", + -- function(c) + -- return (string.gsub(tostring(c),"foo","%1")) + -- end + -- ) + -- end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/m-fonts-plugins.mkiv b/Master/texmf-dist/tex/context/base/mkiv/m-fonts-plugins.mkiv index b74b8c3d0d3..154e4780427 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/m-fonts-plugins.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/m-fonts-plugins.mkiv @@ -186,6 +186,7 @@ \definefontfeature [arabic-node] [arabic] + [salt=yes] % seems to be needed for husayni \definefontfeature [arabic-native] @@ -224,7 +225,7 @@ \getbuffer[#5-definitions] \showfontkerns \showmakeup[discretionary] - \enabletrackers[fonts.plugins.hb.colors]% + % \enabletrackers[fonts.plugins.hb.colors]% \testfeatureonce{1}{ \getbuffer[#5-text] } @@ -263,7 +264,7 @@ \title{#1 #3 #4} \start \getbuffer[#5-definitions] - \enabletrackers[fonts.plugins.hb.colors]% + % \enabletrackers[fonts.plugins.hb.colors]% \testfeatureonce{1}{ \setupalign[flushleft] % easier to compare \getbuffer[#5-text] diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-act.lua b/Master/texmf-dist/tex/context/base/mkiv/math-act.lua index 77a355b225f..07ef32746a4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-act.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-act.lua @@ -23,6 +23,12 @@ local mathematics = mathematics local texsetdimen = tex.setdimen local abs = math.abs +local helpers = fonts.helpers +local upcommand = helpers.commands.up +local rightcommand = helpers.commands.right +local charcommand = helpers.commands.char +local prependcommands = helpers.prependcommands + local sequencers = utilities.sequencers local appendgroup = sequencers.appendgroup local appendaction = sequencers.appendaction @@ -237,7 +243,6 @@ function mathematics.overloaddimensions(target,original,set) local factor = parameters.factor local hfactor = parameters.hfactor local vfactor = parameters.vfactor - local addprivate = fonts.helpers.addprivate -- to be sure target.type = "virtual" target.properties.virtualized = true @@ -257,7 +262,8 @@ function mathematics.overloaddimensions(target,original,set) local height = data.height local depth = data.depth if trace_defining and (width or height or depth) then - report_math("overloading dimensions of %C, width %a, height %a, depth %a",unicode,width,height,depth) + report_math("overloading dimensions of %C, width %p, height %p, depth %p", + unicode,width or 0,height or 0,depth or 0) end if width then character.width = width * hfactor end if height then character.height = height * vfactor end @@ -270,25 +276,26 @@ function mathematics.overloaddimensions(target,original,set) if d then xoffset = - d.boundingbox[1] * hfactor character.width = character.width + xoffset - xoffset = { "right", xoffset } + xoffset = rightcommand[xoffset] + else + xoffset = nil end - elseif xoffset then - xoffset = { "right", xoffset * hfactor } + elseif xoffset and xoffset ~= 0 then + xoffset = rightcommand[xoffset * hfactor] + else + xoffset = nil end - if yoffset then - yoffset = { "down", -yoffset * vfactor } + if yoffset and yoffset ~= 0 then + yoffset = upcommand[yoffset * vfactor] + else + yoffset = nil end if xoffset or yoffset then - if character.commands then - if yoffset then - insert(character.commands,1,yoffset) - end - if xoffset then - insert(character.commands,1,xoffset) - end + local commands = characters.commands + if commands then + prependcommands(commands,yoffset,xoffset) else - -- local slot = { "slot", 1, addprivate(target,nil,fastcopy(character)) } - local slot = { "slot", 0, addprivate(target,nil,fastcopy(character)) } + local slot = charcommand[unicode] if xoffset and yoffset then character.commands = { xoffset, yoffset, slot } elseif xoffset then @@ -297,7 +304,6 @@ function mathematics.overloaddimensions(target,original,set) character.commands = { yoffset, slot } end end - character.index = nil end elseif trace_defining then report_math("no overloading dimensions of %C, not in font",unicode) @@ -732,9 +738,9 @@ function mathematics.finishfallbacks(target,specification,fallbacks) done[unic] = true end end + local step = offset - start for unicode = start, stop do - local unic = unicode + offset - start - remap(unic,unicode,false) + remap(unicode + step,unicode,false) end if gaps then for unic, unicode in next, gaps do diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv index 083fb764540..ecfac68870f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-ali.mkiv @@ -321,11 +321,18 @@ \def\math_alignment_EQ {\NC=} +\installmacrostack\NC % maybe more to shared table definitions +\installmacrostack\NN % maybe more to shared table definitions +\installmacrostack\EQ % maybe more to shared table definitions +\installmacrostack\NR % maybe more to shared table definitions +\installmacrostack\BC % maybe more to shared table definitions +\installmacrostack\EC % maybe more to shared table definitions + \appendtoks - \pushmacro\NC - \pushmacro\NN - \pushmacro\EQ - \pushmacro\NR + \push_macro_NC + \push_macro_NN + \push_macro_EQ + \push_macro_NR \let\NC\math_alignment_NC \let\NN\math_alignment_NN \let\EQ\math_alignment_EQ @@ -334,10 +341,10 @@ \to \everymathalignment \appendtoks - \popmacro\NR - \popmacro\EQ - \popmacro\NN - \popmacro\NC + \pop_macro_NR + \pop_macro_EQ + \pop_macro_NN + \pop_macro_NC \to \everymathalignmentdone \let\math_alignment_snap_start\relax @@ -694,11 +701,11 @@ {\unskip \math_cases_end_math \aligntab - \global\let\math_cases_NC\math_cases_NC_first + \glet\math_cases_NC\math_cases_NC_first \dodirectdoubleempty\math_cases_NR} \def\math_cases_NC_first - {\global\let\math_cases_NC\math_cases_NC_second} + {\glet\math_cases_NC\math_cases_NC_second} \def\math_cases_NC_second {\math_cases_end_math\aligntab} @@ -722,7 +729,7 @@ \let\NC\math_cases_NC_zero \let\MC\math_cases_MC_zero \let\NR\math_cases_NR_zero - \global\let\math_cases_NC\math_cases_NC_first + \glet\math_cases_NC\math_cases_NC_first \normalbaselines \mathsurround\zeropoint \everycr\emptytoks diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv index a0dda66b9b7..2edb91465ff 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-arr.mkiv @@ -67,39 +67,46 @@ \def\math_arrows_construct#1#2#3#4#5% hm, looks like we do a double mathrel (a bit cleaned up .. needs checking) {\begingroup - \def\m_math_arrows_factor{1}% - \def\m_math_arrows_extra {0}% + \let\m_math_arrows_factor\!!plusone + \let\m_math_arrows_extra \!!zerocount \edef\p_math_spacing{#1}% \csname\??matharrowsettings \ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi \endcsname \mathsurround\zeropoint - \muskip0=\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax - \muskip2=\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax - \setbox0\hbox{\normalstartimath - \scriptstyle - \mkern\muskip0\relax - #5\relax - \mkern\muskip2\relax - \normalstopimath}% - \setbox2\hbox{\normalstartimath - \scriptstyle - \mkern\muskip0\relax - #4\relax - \mkern\muskip2\relax - \normalstopimath}% - \setbox4\hbox{#3\displaystyle}% - \dimen0\wd0\relax - \ifdim\wd2>\dimen0 - \dimen0\wd2\relax + \scratchmuskipone\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax + \scratchmuskiptwo\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax + \setbox\scratchboxone\hbox + {\normalstartimath + \scriptstyle + \mkern\scratchmuskipone\relax + #5\relax + \mkern\scratchmuskiptwo\relax + \normalstopimath}% + \setbox\scratchboxtwo\hbox + {\normalstartimath + \scriptstyle + \mkern\scratchmuskipone\relax + #4\relax + \mkern\scratchmuskiptwo\relax + \normalstopimath}% + \setbox\scratchboxthree\hbox{#3\displaystyle}% + \scratchdimenone\wd\scratchboxone\relax + \ifdim\wd\scratchboxtwo>\scratchdimenone + \scratchdimenone\wd\scratchboxtwo\relax \fi - \ifdim\wd4>\dimen0 - \dimen0\wd4\relax + \ifdim\wd\scratchboxthree>\scratchdimenone + \scratchdimenone\wd\scratchboxthree\relax \fi - \ifdim\wd4=\dimen0\else - \setbox4\hbox to \dimen0{#3\displaystyle}% + \ifdim\wd\scratchboxthree=\scratchdimenone\else + \setbox\scratchboxthree\hbox to \scratchdimenone{#3\displaystyle}% \fi - \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}% pack ? + \mathrel + {\mathop + {\hpack to \scratchdimenone{\hss\box\scratchboxthree\hss}}% pack ? copy ? + \limits + \normalsuperscript{\box\scratchboxone}% + \normalsubscript {\box\scratchboxtwo}}% \endgroup} \let\math_arrows_construct_single\math_arrows_construct diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua b/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua index 72b9d7e5037..eb7adb53f97 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-dim.lua @@ -157,7 +157,8 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled for variable, styles in next, defaults do local tt = { } for style, default in next, styles do - local one, two = default[1], default[2] + local one = default[1] + local two = default[2] local value = dimens[one] if value then tt[style] = value diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua index 759f1e79715..38aa44358e2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-dir.lua @@ -48,7 +48,9 @@ local vlist_code = nodecodes.vlist local nodepool = nuts.pool -local new_textdir = nodepool.textdir +local new_direction = nodepool.direction + +local lefttoright_code = nodes.dirvalues.lefttoright local chardirections = characters.directions local charmirrors = characters.mirrors @@ -60,16 +62,14 @@ local a_mathbidi = attributes.private('mathbidi') local function processmath(head) local current = head - local done = false local start = nil local stop = nil local function capsulate() - head = insert_node_before(head,start,new_textdir("+TLT")) - insert_node_after(head,stop,new_textdir("-TLT")) + head = insert_node_before(head,start,new_direction(lefttoright_code)) + insert_node_after(head,stop,new_direction(lefttoright_code,true)) if trace_directions then report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop)) end - done = true start = false stop = nil end @@ -100,7 +100,6 @@ local function processmath(head) if trace_directions then report_directions("mirrored: %C to %C",char,mirror) end - done = true end end end @@ -108,11 +107,8 @@ local function processmath(head) elseif not start then -- nothing if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) + local list = processmath(getlist(current)) setlist(current,list) - if d then - done = true - end end elseif start == stop then start = nil @@ -121,11 +117,8 @@ local function processmath(head) -- math can pack things into hlists .. we need to make sure we don't process -- too often: needs checking if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) + local list = processmath(getlist(current)) setlist(current,list) - if d then - done = true - end end end current = getnext(current) @@ -137,21 +130,18 @@ local function processmath(head) else capsulate() end - return head, done + return head end local enabled = false function directions.processmath(head) -- style, penalties if enabled then - local h = tonut(head) - local a = getattr(h,a_mathbidi) + local a = getattr(head,a_mathbidi) if a and a > 0 then - local head, done = processmath(h) - return tonode(head), done + return processmath(head) end end - return head, false end function directions.setmath(n) diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua index a4b8657136c..b923853f4a6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-ext.lua @@ -7,29 +7,30 @@ if not modules then modules = { } end modules ['math-ext'] = { } local rawget = rawget - -local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end) - local basename = file.basename +local sortedhash = table.sortedhash + +local mathematics = mathematics +local extras = mathematics.extras or { } +mathematics.extras = extras -local mathematics = mathematics -local characters = characters +local characters = characters +local chardata = characters.data +local mathpairs = characters.mathpairs -local report_math = logs.reporter("mathematics") +local trace_virtual = false +local report_math = logs.reporter("mathematics") -mathematics.extras = mathematics.extras or { } -local extras = mathematics.extras +trackers.register("math.virtual", function(v) trace_virtual = v end) -local mathplus = { } -local chardata = characters.data -local mathpairs = characters.mathpairs +local mathplus = { } -- todo: store them and skip storage if already stored -- todo: make a char-ctx.lua (or is this already side effect of save in format) local function addextra(unicode) local min = mathematics.extrabase - local max = mathematics.privatebase - 1 + local max = min + 0xFFF if unicode >= min and unicode <= max then if chardata[unicode] then mathplus[unicode] = true @@ -47,7 +48,7 @@ function extras.copy(target,original) local characters = target.characters local properties = target.properties local parameters = target.parameters - for unicode in table.sortedhash(mathplus) do + for unicode in sortedhash(mathplus) do local extradesc = chardata[unicode] local nextinsize = extradesc.nextinsize if nextinsize then diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua index 7aa8c437fa1..963461de5cf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-fbk.lua @@ -20,10 +20,22 @@ local sortedhash = table.sortedhash local fallbacks = { } mathematics.fallbacks = fallbacks +local helpers = fonts.helpers +local prependcommands = helpers.prependcommands +local charcommand = helpers.commands.char +local leftcommand = helpers.commands.left +local rightcommand = helpers.commands.right +local upcommand = helpers.commands.up +local downcommand = helpers.commands.down +local dummycommand = helpers.commands.dummy +local popcommand = helpers.commands.pop +local pushcommand = helpers.commands.push + local virtualcharacters = { } -local identifiers = fonts.hashes.identifiers -local lastmathids = fonts.hashes.lastmathids +local hashes = fonts.hashes +local identifiers = hashes.identifiers +local lastmathids = hashes.lastmathids -- we need a trick (todo): if we define scriptscript, script and text in -- that order we could use their id's .. i.e. we could always add a font @@ -115,6 +127,8 @@ function fallbacks.apply(target,original) } target.mathrelation = data -- + local fullname = trace_fallbacks and target.properties.fullname + -- for k, v in sortedhash(virtualcharacters) do if not characters[k] then local tv = type(v) @@ -132,7 +146,7 @@ function fallbacks.apply(target,original) -- something else end if trace_fallbacks and characters[k] then - report_fallbacks("extending math font %a with %U",target.properties.fullname,k) + report_fallbacks("extending math font %a with %U",fullname,k) end end end @@ -151,22 +165,21 @@ local function reference(index,char) if index then return { "slot", index, char } else - return { "char", char } + return charcommand[char] end end -local function raised(data,down) - local replacement = data.replacement - local character = data.scriptdata.characters[replacement] +local function raised(data,replacement,down) + local character = data.scriptdata.characters[replacement] if character then + local size = data.size return { width = character.width, height = character.height, depth = character.depth, commands = { - { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight + down and downcommand[size/4] or upcommand[size/2], reference(data.scriptindex,replacement) - -- { "slot", data.scriptindex or 0, char } -- hm, data.mathrelation.scriptindex } } end @@ -177,33 +190,18 @@ end -- virtualcharacters[0x208A] = 0x2212 -- virtualcharacters[0x208B] = 0x002B -virtualcharacters[0x207A] = function(data) - data.replacement = 0x002B - return raised(data) -end - -virtualcharacters[0x207B] = function(data) - data.replacement = 0x2212 - return raised(data) -end - -virtualcharacters[0x208A] = function(data) - data.replacement = 0x002B - return raised(data,true) -end - -virtualcharacters[0x208B] = function(data) - data.replacement = 0x2212 - return raised(data,true) -end +virtualcharacters[0x207A] = function(data) return raised(data,0x002B) end +virtualcharacters[0x207B] = function(data) return raised(data,0x2212) end +virtualcharacters[0x208A] = function(data) return raised(data,0x002B,true) end +virtualcharacters[0x208B] = function(data) return raised(data,0x2212,true) end -- local function repeated(data,char,n,fraction) -- local character = data.characters[char] -- if character then -- local width = character.width -- local delta = width - character.italic -- width * fraction --- local c = { "char", char } --- local r = { "right", right } +-- local c = charcommand[char] +-- local r = rightcommand[right] -- local commands = { } -- for i=1,n-1 do -- width = width + delta @@ -234,14 +232,9 @@ addextra(0xFE350) -- MATHEMATICAL DOUBLE ARROW LEFT END addextra(0xFE351) -- MATHEMATICAL DOUBLE ARROW MIDDLE PART addextra(0xFE352) -- MATHEMATICAL DOUBLE ARROW RIGHT END -local push = { "push" } -local pop = { "pop" } -local leftarrow = { "char", 0x2190 } -local relbar = { "char", 0x2212 } -local rightarrow = { "char", 0x2192 } --- local leftarrow = { "slot", 0, 0x2190 } --- local relbar = { "slot", 0, 0x2212 } --- local rightarrow = { "slot", 0, 0x2192 } +local leftarrow = charcommand[0x2190] +local relbar = charcommand[0x2212] +local rightarrow = charcommand[0x2192] virtualcharacters[0xFE350] = function(data) -- return combined(data,0x2190,0x2212) -- leftarrow relbar @@ -254,11 +247,11 @@ virtualcharacters[0xFE350] = function(data) height = size, depth = size, commands = { - push, - { "down", size/2 }, + pushcommand, + downcommand[size/2], leftarrow, - pop, - { "down", -size/2 }, + popcommand, + upcommand[size/2], relbar, } } @@ -275,11 +268,11 @@ virtualcharacters[0xFE351] = function(data) height = size, depth = size, commands = { - push, - { "down", size/2 }, + pushcommand, + downcommand[size/2], relbar, - pop, - { "down", -size/2 }, + popcommand, + upcommand[size/2], relbar, } } @@ -297,12 +290,12 @@ virtualcharacters[0xFE352] = function(data) height = size, depth = size, commands = { - push, - { "down", size/2 }, + pushcommand, + downcommand[size/2], relbar, - pop, - { "right", chartwo.width - charone.width }, - { "down", -size/2 }, + popcommand, + rightcommand[chartwo.width - charone.width], + upcommand[size/2], rightarrow, } } @@ -325,10 +318,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s height = height or 0 depth = depth or 0 end - local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height + (offset or 0)} + local oldheight = olddata.height or 0 + local correction = swap and + downcommand[oldheight - height] + or downcommand[oldheight + (offset or 0)] local newdata = { - commands = { correction, { "slot", 1, oldchr } }, - -- commands = { correction, { "slot", 0, oldchr } }, + commands = { correction, charcommand[oldchr] }, width = olddata.width, height = height, depth = depth, @@ -340,14 +335,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s local oldnextdata = characters[nextglyph] if oldnextdata then local newnextdata = { - commands = { correction, { "slot", 1, nextglyph } }, - -- commands = { correction, { "slot", 0, nextglyph } }, + commands = { correction, charcommand[nextglyph] }, width = oldnextdata.width, height = height, depth = depth, } --- local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata) - local newnextglyph = addprivate(target,nil,newnextdata) + local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata) newdata.next = newnextglyph local nextnextglyph = oldnextdata.next if nextnextglyph == nextglyph then @@ -372,14 +365,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s local olddata = characters[oldglyph] if olddata then local newdata = { - commands = { correction, { "slot", 1, oldglyph } }, - -- commands = { correction, { "slot", 0, oldglyph } }, + commands = { correction, charcommand[oldglyph] }, width = olddata.width, height = height, depth = depth, } --- hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata) - hvi.glyph = addprivate(target,nil,newdata) + hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata) else report_fallbacks("error in fallback: no valid horiz_variants, slot %X, index %i",oldglyph,i) end @@ -393,15 +384,16 @@ end virtualcharacters[0x203E] = function(data) local target = data.target - local height, depth = 0, 0 --- local mathparameters = target.mathparameters --- if mathparameters then --- height = mathparameters.OverbarVerticalGap --- depth = mathparameters.UnderbarVerticalGap --- else + local height = 0 + local depth = 0 + -- local mathparameters = target.mathparameters + -- if mathparameters then + -- height = mathparameters.OverbarVerticalGap + -- depth = mathparameters.UnderbarVerticalGap + -- else height = target.parameters.xheight/4 depth = height --- end + -- end return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E) end @@ -431,7 +423,7 @@ local function spacefraction(data,fraction) local width = fraction * data.target.parameters.space return { width = width, - commands = { { "right", width } } + commands = { rightcommand[width] } } end @@ -439,7 +431,7 @@ local function charfraction(data,char) local width = data.target.characters[char].width return { width = width, - commands = { { "right", width } } + commands = { rightcommand[width] } } end @@ -447,7 +439,7 @@ local function quadfraction(data,fraction) local width = fraction * data.target.parameters.quad return { width = width, - commands = { { "right", width } } + commands = { rightcommand[width] } } end @@ -527,9 +519,8 @@ local function smashed(data,unicode,optional) local shift = oldchar.height - height local newchar = { commands = { - { "down", shift }, - { "slot", 0, unicode }, --- { "char", unicode }, + downcommand[shift], + charcommand[unicode], }, height = height, width = oldchar.width, @@ -607,11 +598,11 @@ local function actuarian(data) width = basewidth + 4 * linewidth, unicode = 0x20E7, commands = { - { "right", 2 * linewidth }, - { "down", - baseheight - 3 * linewidth }, + rightcommand[2 * linewidth], + downcommand[- baseheight - 3 * linewidth], { "rule", linewidth, basewidth + 4 * linewidth }, - { "right", -linewidth }, - { "down", baseheight + 4 * linewidth }, + leftcommand[linewidth], + downcommand[baseheight + 4 * linewidth], { "rule", baseheight + 5 * linewidth, linewidth }, }, } @@ -629,11 +620,11 @@ local function equals(data,unicode,snippet,advance,n) -- mathpair needs them unicode = unicode, width = n*basechar.width + (n-1)*advance, commands = { - { "char", snippet }, - { "right", advance }, - { "char", snippet }, - n > 2 and { "right", advance } or nil, - n > 2 and { "char", snippet } or nil, + charcommand[snippet], + rightcommand[advance], + charcommand[snippet], + n > 2 and rightcommand[advance] or nil, + n > 2 and charcommand[snippet] or nil, }, } end @@ -657,11 +648,43 @@ virtualcharacters[0x2980] = function(data) return equals(data,0x2980,0x007C,-1/8 -- height = height, -- we cheat (no time now) -- depth = depth, -- we cheat (no time now) -- commands = { --- { "down", - height/2 }, -- sort of works --- { "char", 0x003D }, --- { "right", -width }, --- { "down", height }, -- sort of works --- { "char", 0x003D }, +-- upcommand[height/2], -- sort of works +-- charcommand[0x003D], +-- leftcommand[width], +-- downcommand[height], -- sort of works +-- charcommand[0x003D], -- }, -- } -- end + +-- lucida needs this + +virtualcharacters[0x305] = function(data) + local target = data.target + local height = target.parameters.xheight/8 + local width = target.parameters.emwidth/2 + local depth = height + local used = 0.8 * width + return { + width = width, + height = height, + depth = depth, + commands = { { "rule", height, width } }, + horiz_variants = { + { + advance = width, + ["end"] = used, + glyph = 0x305, + start = 0, + }, + { + advance = width, + ["end"] = 0, + extender = 1, + glyph = 0x305, + start = used, + }, + } + } +end + diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv index a32ea410e74..6c6724bf52e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-fen.mkiv @@ -65,14 +65,19 @@ % we need the direct use of \Udelimiter because of { etc -\newconditional\c_math_fenced_mirror \settrue\c_math_fenced_mirror +\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror +\newconditional\c_math_fenced_sized \setfalse\c_math_fenced_sized \unexpanded\def\math_fenced_inject#1#2#3#4% {\ifx#1\empty #2.% \else \edef\p_mathclass{\mathfenceparameter\c!mathclass}% - \edef\p_factor{\mathfenceparameter\c!factor}% + \ifconditional\c_math_fenced_sized + \let\p_factor\v!fixed + \else + \edef\p_factor{\mathfenceparameter\c!factor}% + \fi \ifx\p_factor\empty \ifx\p_mathclass\empty #2% @@ -97,7 +102,11 @@ \s!axis % #2% \else - \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax + \ifx\p_factor\v!fixed + \scratchdimen\scaledpoint + \else + \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax + \fi #3% \s!height\scratchdimen \s!depth\scratchdimen @@ -121,16 +130,14 @@ \mathfenceparameter\c!left \fi}% \math_fenced_color_push - % \normalleft\ifx\p_left\empty.\else\Udelimiter\plusfour\fam\p_left\relax\fi \math_fenced_inject\p_left\normalleft\Uleft\plusfour \math_fenced_color_pop} \def\math_fenced_middle {\edef\p_middle - {\mathfenceparameter\c!middle}% + {\mathfenceparameter\c!middle}% \mskip\thinmuskip \math_fenced_color_push - % \normalmiddle\ifx\p_middle\empty.\else\Udelimiter\plusfour\fam\p_middle\relax\fi \math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour \math_fenced_color_pop \mskip\thinmuskip} @@ -147,7 +154,6 @@ \mathfenceparameter\c!right \fi}% \math_fenced_color_push - % \normalright \ifx\p_right\empty.\else\Udelimiter\plusfive\fam\p_right\relax\fi \math_fenced_inject\p_right\normalright\Uright\plusfive \math_fenced_color_pop} @@ -194,16 +200,60 @@ \edef\currentmathfence{#1}% \dosingleempty\math_fenced_fenced_indeed} -\unexpanded\def\math_fenced_fenced_indeed[#1]#2% +\def\math_fenced_force_size#1#2% + {\attribute\mathsizeattribute\numexpr#1*\plushundred+#2\relax} + +% \unexpanded\def\math_fenced_fenced_indeed[#1]#2% +% {\iffirstargument\setupcurrentmathfence[#1]\fi +% \math_fenced_fenced_common +% \edef\p_size{\mathfenceparameter\c!size}% +% \ifx\p_size\empty +% \setfalse\c_math_fenced_sized +% \else +% \settrue\c_math_fenced_sized +% \math_fenced_force_size\bigmathdelimitervariant\p_size +% \fi +% \math_fenced_left +% #2% +% \math_fenced_right +% \stopusemathstyleparameter +% \endgroup +% \advance\c_math_fenced_nesting\minusone} + +\unexpanded\def\math_fenced_fenced_indeed[#1]% {\iffirstargument\setupcurrentmathfence[#1]\fi \math_fenced_fenced_common - \math_fenced_left - #2% - \math_fenced_right - \stopusemathstyleparameter + \edef\p_size{\mathfenceparameter\c!size}% + \ifx\p_size\empty + \expandafter\math_fenced_fenced_indeed_adapt + \else + \expandafter\math_fenced_fenced_indeed_fixed + \fi} + +\unexpanded\def\math_fenced_fenced_indeed_finish + {\stopusemathstyleparameter \endgroup \advance\c_math_fenced_nesting\minusone} +\unexpanded\def\math_fenced_fenced_indeed_fixed#1% + {\math_fenced_force_size\bigmathdelimitervariant\p_size + \settrue\c_math_fenced_sized + \math_fenced_left + \setfalse\c_math_fenced_sized + #1% + \settrue\c_math_fenced_sized + \math_fenced_right + \setfalse\c_math_fenced_sized + \math_fenced_fenced_indeed_finish} + +\unexpanded\def\math_fenced_fenced_indeed_adapt#1% + {\setfalse\c_math_fenced_sized + \math_fenced_left + #1% + \setfalse\c_math_fenced_sized + \math_fenced_right + \math_fenced_fenced_indeed_finish} + \appendtoks \let\fenced\math_fenced_fenced \to \everymathematics @@ -440,31 +490,31 @@ \installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts -\installmathfencepair . \Lnothing . \Rnothing -\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored +\installmathfencepair . \Lnothing . \Rnothing +\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored -\installmathfencepair [ \Lbracket ] \Rbracket -\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored +\installmathfencepair [ \Lbracket ] \Rbracket +\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored -\installmathfencepair ( \Lparenthesis ) \Rparenthesis -\installmathfencepair ) \Rparentmirrored ( \Lparentmirrored +\installmathfencepair ( \Lparenthesis ) \Rparenthesis +\installmathfencepair ) \Rparenthesismirrored ( \Lparenthesismirrored -\installmathfencepair < \Langle > \Rangle -\installmathfencepair > \Ranglemirrored < \Langlemirrored +\installmathfencepair < \Langle > \Rangle +\installmathfencepair > \Ranglemirrored < \Langlemirrored -\installmathfencepair / \Lsolidus / \Rsolidus -%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored +\installmathfencepair / \Lsolidus / \Rsolidus +%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored -\installmathfencepair | \Lbar | \Rbar -%installmathfencepair | \Rbarmirrored | \Lbarmirrored +\installmathfencepair | \Lbar | \Rbar +%installmathfencepair | \Rbarmirrored | \Lbarmirrored -\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor -\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored -\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling -\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored +\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor +\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored +\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling +\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored -\installmathfencepair ⟨ \Langle ⟩ \Rangle -\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored +\installmathfencepair ⟨ \Langle ⟩ \Rangle +\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored \installmathfencepair ⟪ \Ldoubleangle ⟫ \Rdoubleangle \installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored @@ -475,10 +525,10 @@ \installmathfencepair ⦀ \Ltriplebar ⦀ \Rtriplebar %installmathfencepair ⦀ \Rtriplebarmirrored ⦀ \Ltriplebarmirrored -% \installmathfencepair { \Lbrace } \Rbrace -% \installmathfencepair } \Rbracemirrored { \Lbracemirrored +% \installmathfencepair { \Lbrace } \Rbrace +% \installmathfencepair } \Rbracemirrored { \Lbracemirrored -\installmathfencepair ⦗ \Linterv ⦘ \Rinterv +\installmathfencepair ⦗ \Linterval ⦘ \Rinterval \appendtoks \ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox @@ -591,7 +641,7 @@ \ifcase\bigmathdelimitermethod \math_fenced_step#2\relax \or - \attribute\mathsizeattribute\numexpr\bigmathdelimitervariant*\plushundred+#1\relax + \math_fenced_force_size\bigmathdelimitervariant{#1}\relax \math_fenced_step#2\relax \else \math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}% @@ -621,7 +671,7 @@ \unexpanded\def\mathdelimiterstep#1#2% {\begingroup - \attribute\mathsizeattribute\numexpr\plushundred+#1\relax + \math_fenced_force_size\plusone{#1}% \math_fenced_step#2\relax \endgroup} diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua b/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua index 5c4879527d7..190c364101d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-frc.lua @@ -28,8 +28,8 @@ end) local ctx_normalatop = context.normalatop local ctx_normalover = context.normalover -local function mathfraction(how,left,right,width) -- of course we could use the scanners directly here which - if how == v_no then -- is faster but also less abstract ... maybe some day +local function mathfraction(how,left,right,width) + if how == v_no then if left == 0x002E and right == 0x002E then ctx_normalatop() else diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv index 9a5ce62b05d..97107a6bf91 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-frc.mkiv @@ -611,6 +611,46 @@ % \unexpanded\def\ShowMathFractions#1#2% % {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}} +%D More fracking (for Alan): + +\def\s!vfrac{vfrac} + +\unexpanded\def\math_frac_colored_vulgar#1#2% + {\savecolor + \colo_helpers_activate\p_math_fractions_color + {\restorecolor#1}\Uskewed/{\restorecolor#2}} + +\unexpanded\def\math_frac_normal_vulgar#1#2% + {{#1}\Uskewed/{#2}} + +\unexpanded\def\vfrac#1#2% + {\bgroup + \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}% + \ifx\p_math_fractions_color\empty + \expandafter\math_frac_normal_vulgar + \else + \expandafter\math_frac_colored_vulgar + \fi + {#1}% + {#2}% + \egroup} + +\appendtoks + \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}% + \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}% + \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle + \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle + \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle + \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle + \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle + \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle +\to \everysetupmathfraction + +\setupmathfraction + [\s!vfrac] + [\c!hfactor=.2, + \c!vfactor=.1] + \protect \endinput % I have no clue what \mthfrac and \mthsqrt are supposed to do but @@ -660,7 +700,7 @@ % \unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]} % \unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]} -% used for prototypine \Uskewed +% used for prototyping \Uskewed % % \unexpanded\def\skewedfractiona#1#2{% % \raise diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-inc.lua b/Master/texmf-dist/tex/context/base/mkiv/math-inc.lua new file mode 100644 index 00000000000..010d29a359a --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/math-inc.lua @@ -0,0 +1,87 @@ +if not modules then modules = { } end modules ['back-inc'] = { + version = 1.001, + comment = "companion to back-exp.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. If it's really useful then I'll make a more efficient +-- local export facility. + +local tonumber, next = tonumber, next +local utfbyte, utfchar, utfsplit = utf.byte, utf.char, utf.split +local match, gsub = string.match, string.gsub +local nspaces = string.nspaces +local concat = table.concat +local xmltext = xml.text +local undent = buffers.undent + +local f_entity = string.formatters["&x%X;"] +local f_blob = string.formatters['\n\n\n\n%s'] + +local all = nil +local back = nil + +local function unmath(s) + local t = utfsplit(s) + for i=1,#t do + local ti = t[i] + local bi = utfbyte(ti) + if bi > 0xFFFF then + local ch = back[bi] + t[i] = ch and utfchar(ch) or f_entity(bi) + end + end + s = concat(t) + return s +end + +local function beautify(s) + local b = match(s,"^( *)%s*$") + if b and e then + b = #b + e = #e + if e > b then + s = undent(nspaces[e-b] .. s) + elseif e < b then + s = undent((gsub(s,"^( *)",nspaces[b-e]))) + end + end + return s +end + +local function getblob(n) + if all == nil then + local name = file.nameonly(tex.jobname) + local full = name .. "-export/" .. name .. "-raw.xml" + if lfs.isfile(full) then + all = { } + back = { } + local root = xml.load(full) + for c in xml.collected(root,"formulacontent") do + local index = tonumber(c.at.n) + all[index] = f_blob(index,beautify(xmltext(c,"math") or "")) + end + local it = mathematics.alphabets.regular.it + for k, v in next, it.digits do back[v] = k end + for k, v in next, it.ucletters do back[v] = k end + for k, v in next, it.lcletters do back[v] = k end + else + all = false + end + end + if all == false then + return "" + end + return unmath(all[n] or "") +end + +interfaces.implement { + name = "xmlformulatobuffer", + arguments = { "integer", "string" }, + actions = function(n,target) + buffers.assign(target,getblob(n)) + end +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-inc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-inc.mkiv new file mode 100644 index 00000000000..2821580cbf1 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/math-inc.mkiv @@ -0,0 +1,69 @@ +%D \module +%D [ file=math-inc, +%D version=2018.06.23, +%D title=\CONTEXT\ Math Macros, +%D subtitle=XML inclusion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Math Macros / XML inclusion} + +\registerctxluafile{math-inc}{} + +%D I had some doubt about including this in \CONTEXT\ but it might serve some users +%D anyway. It's always the question to what extent one can be really roundtrip. I +%D might improve it when I need it. + +% Talking about creating from a source ... June Lee's transcription of +% Close to You by Jacob Collier is an amazing example: +% +% https://www.youtube.com/watch?v=hdBVN-HMuqI + +\unprotect + +\definesymbol[mmlattachment][{\infofont\darkred mml}] +\definesymbol[mmlcomment] [{\infofont\darkblue mml}] + +\unexpanded\def\lxml_add_mml_blob#1#2% + {\relax + \clf_xmlformulatobuffer\number\c_strc_formulas_n{temp-xml-export}% + #2% + [\c!symbol=#1,% + \c!space=\v!yes,% + \c!buffer=temp-xml-export,% + \c!name={formula-\number\c_strc_formulas_n.xml}]% + \relax} + +\unexpanded\def\xmlattachmml + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \lxml_add_mml_blob{mmlattachment}\attachment + \dostoptagged + \fi \fi \fi} + +\unexpanded\def\xmlcommentmml + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \lxml_add_mml_blob{mmlcomment}\comment + \dostoptagged + \fi \fi \fi} + +%D This kind of feature creep is not yet configurable, nor documented. + +\unexpanded\def\xmladdmmlsource + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \inleftmargin{% + \lxml_add_mml_blob{mmlattachment}\attachment + \quad + \lxml_add_mml_blob{mmlcomment}\comment + }% + \dostoptagged + \fi \fi \fi} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua index b79ef8c8cf4..7a841970209 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-ini.lua @@ -36,8 +36,8 @@ local report_math = logs.reporter("mathematics","initializing") mathematics = mathematics or { } local mathematics = mathematics -mathematics.extrabase = 0xFE000 -- here we push some virtuals -mathematics.privatebase = 0xFF000 -- here we push the ex +mathematics.extrabase = fonts.privateoffsets.mathextrabase -- here we push some virtuals +mathematics.privatebase = fonts.privateoffsets.mathbase -- here we push the ex local unsetvalue = attributes.unsetvalue local allocate = utilities.storage.allocate @@ -289,7 +289,8 @@ function mathematics.define(family) local data = characters.data for unicode, character in sortedhash(data) do local symbol = character.mathsymbol - local mset, dset = true, true + local mset = true + local dset = true if symbol then local other = data[symbol] local class = other.mathclass @@ -641,7 +642,7 @@ function mathematics.big(tfmdata,unicode,n,method) end end end - else + elseif method == 3 then local size = 1.33^n if method == 4 then size = tfmdata.parameters.size * size diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv index 17d900d74f2..50da1a400c8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-ini.mkiv @@ -123,9 +123,12 @@ \definesystemattribute[mathbidi] [public] \definesystemattribute[mathdomain] [public] \definesystemattribute[mathcollapsing] [public] +\definesystemattribute[mathunstack] [public] \definesystemattribute[displaymath] [public] +\mathflattenmode 31 + \appendtoks \attribute\mathmodeattribute\plusone \to \everydisplay @@ -217,18 +220,20 @@ \unexpanded\def\startmathematics % no grouping, if ever then also an optional second {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop} +\installmacrostack\currentmathematics + \unexpanded\def\math_mathematics_start_yes[#1]% - {\pushmacro\currentmathematics + {\push_macro_currentmathematics \edef\currentmathematics{#1}% check for valid \the\everyswitchmathematics} \unexpanded\def\math_mathematics_start_nop - {\pushmacro\currentmathematics + {\push_macro_currentmathematics \let\currentmathematics\empty \the\everyswitchmathematics} \unexpanded\def\stopmathematics - {\popmacro\currentmathematics + {\pop_macro_currentmathematics \the\everyswitchmathematics} \definemathematics[\v!default] % not needed, but nicer when nesting back to normal @@ -734,7 +739,6 @@ % % \def\math_op{\ifx\nexttoken\bgroup\else\nexttoken\egroup\fi} - % this one too: \letvalue{\??mathcodecommand op}\mathop ? \unexpanded\def\normalmbox @@ -750,17 +754,15 @@ {\ifmmode\normalmbox\else\normalhbox\fi} \unexpanded\def\enablembox - {\appendtoks\math_enable_mbox\to \everymathematics} - {\everymathematics\expandafter{\the\everymathematics\math_enable_mbox}} + {\toksapp\everymathematics{\math_enable_mbox}} \def\math_enable_mbox - {\ifdefined\normalhbox\else\let\normalhbox\hbox\fi % ? - \let\hbox\mbox} + {\let\hbox\mbox} \unexpanded\def\snappedmath#1% sort of \struttedbox {\dontleavehmode \begingroup - \setbox\scratchbox\hbox\bgroup + \setbox\scratchbox\normalhbox\bgroup \startimath#1\stopimath \egroup \ht\scratchbox\strutht @@ -1077,8 +1079,8 @@ % most math fonts have messed up primes, just test this: $\prime^{\prime^{\prime}}$ -{ \catcode\circumflexasciicode\othercatcode \global\let\othercircumflextoken ^ } -{ \catcode\circumflexasciicode\superscriptcatcode \global\let\superscriptcircumflextoken^ } +{ \catcode\circumflexasciicode\othercatcode \glet\othercircumflextoken ^ } +{ \catcode\circumflexasciicode\superscriptcatcode \glet\superscriptcircumflextoken^ } \ifdefined \prime \else \Umathchardef\prime "0 "0 "2032 @@ -1273,9 +1275,13 @@ %D Memory saver: +\def\math_basics_check_compact + {\doifelse{\mathematicsparameter\c!compact}\v!yes + \enabledirectives\disabledirectives[math.virtual.optional]} + \appendtoks \ifx\currentmathematics\empty - \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]% + \math_basics_check_compact % less tracing \fi \to \everysetupmathematics @@ -1311,18 +1317,31 @@ %D \HL %D \stoptabulate +% We will use proper constants when we go numbers instead of XXX. + \newconditional\c_math_right_to_left +\installcorenamespace{mathaligndirection} + +\setvalue{\??mathaligndirection r2l}{\settrue\c_math_right_to_left} +\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left} + \appendtoks - \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left + \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname + \lastnamedcs + \else + \setfalse\c_math_right_to_left + \fi \to \everyswitchmathematics \unexpanded\def\math_basics_synchronize_direction - {\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T} + {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi} + +% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode +% kludge now (should be a property of beginmath nodes and passed to callbacks). \appendtoks \math_basics_synchronize_direction -%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now (should be a property of beginmath nodes and passed to callbacks) \to \everyswitchmathematics % experimental (needed for an article) @@ -1337,11 +1356,6 @@ \letvalue{\??mathbidi\v!yes}\math_bidi_enable \letvalue{\??mathbidi\v!no }\math_bidi_disable -% \appendtoks -% \edef\p_bidi{\mathematicsparameter\c!bidi}% -% \csname\??mathbidi\ifcsname\??mathbidi\p_bidi\endcsname\p_bidi\else\v!no\fi\endcsname -% \to \everysetupmathematics - \appendtoks \edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ? \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi @@ -1434,7 +1448,7 @@ \def\math_collapsing_initialize {\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else \clf_initializemathcollapsing % one time - \global\let\math_collapsing_initialize\relax + \glet\math_collapsing_initialize\relax \fi} \appendtoks @@ -1471,7 +1485,7 @@ \def\math_italics_initialize {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else \clf_initializemathitalics % one time - \global\let\math_italics_initialize\relax + \glet\math_italics_initialize\relax \fi} \appendtoks @@ -1511,7 +1525,7 @@ \def\math_kernpairs_initialize {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else \clf_initializemathkernpairs % one time - \global\let\math_kernpairs_initialize\relax + \glet\math_kernpairs_initialize\relax \fi} \appendtoks @@ -2343,7 +2357,7 @@ % \c_math_styles_state_cramped\zerocount % \c_math_styles_state_size \zerocount % \rawprocesscommacommand[\m_math_style_asked]\math_style_collect -% \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% +% \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% % \csname\??mathstylecache\m_math_style_asked\endcsname} \def\math_style_set_indeed @@ -2365,7 +2379,7 @@ \c_math_styles_state_cramped\zerocount \c_math_styles_state_size \zerocount \rawprocesscommacommand[\m_math_style_asked]\math_style_collect - \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% + \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}% \csname\??mathstylecache\m_math_style_asked\endcsname} \letvalue{\??mathstyle \??mathstyle }\math_style_set_mathstyle_mathstyle % still needed? @@ -2468,10 +2482,12 @@ % I need to decide: % -%mathscriptboxmode\zerocount % no kerning -%mathscriptboxmode\plusone % lists -\mathscriptboxmode\plustwo % lists and boxes -%mathscriptboxmode\plusthree % lists and boxes with \boundary=1 (also for testing and demo) +%mathscriptboxmode \zerocount % no kerning +%mathscriptboxmode \plusone % lists +\mathscriptboxmode \plustwo % lists and boxes +\mathscriptcharmode \plusone % lists and boxes +%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo) +\mathrulethicknessmode\plusone % adaptive \unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox} \unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox} @@ -2529,7 +2545,7 @@ % this can become an option: \unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop - {\global\let\math_display_align_hack_indeed\math_display_align_hack_remove_skip + {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip \math_openup\displayopenupvalue % was \math_openup\jot \everycr{\noalign{\math_display_align_hack_indeed}}} @@ -2537,7 +2553,7 @@ {\ifdim\prevdepth>-\thousandpoint \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax \fi - \global\let\math_display_align_hack_indeed\math_display_align_hack_insert_penalty} + \glet\math_display_align_hack_indeed\math_display_align_hack_insert_penalty} \def\math_display_align_hack_insert_penalty {\penalty\interdisplaylinepenalty} @@ -2767,7 +2783,7 @@ \def\math_domain_initialize {\ifnum\c_math_domain_attribute=\attributeunsetvalue \else \clf_initializemathdomain % one time - \global\let\math_domain_initialize\relax + \glet\math_domain_initialize\relax \fi} \appendtoks @@ -2791,7 +2807,7 @@ \installcorenamespace{mathrules} -\unexpanded\def\enablemathrules{\global\letvalue{\??mathrules\fontclass}\plusone} +\unexpanded\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone} \appendtoks \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname @@ -2802,6 +2818,70 @@ \mathrulesfam\zerocount \to \everymathematics +%D Maybe: + +% \starttabulate[|||c|c|] +% \BC positive \BC negative \BC text \BC math \NC \NR +% \NC \tex {f1} \tex {hairspace} \tex{,} \NC \tex {b1} \tex {neghairspace} \NC {\darkred\vl}\f1{\darkblue\vl} \NC ${\darkred\vl}\f1{\darkblue\vl}$ \NC \NR +% \NC \tex {f2} \tex {thinspace} \tex{:} \NC \tex {b2} \tex {negthinspace} \tex{!} \NC {\darkred\vl}\f2{\darkblue\vl} \NC ${\darkred\vl}\f2{\darkblue\vl}$ \NC \NR +% \NC \tex {f3} \tex {medspace} \tex{;} \NC \tex {b3} \tex {negmedspace} \NC {\darkred\vl}\f3{\darkblue\vl} \NC ${\darkred\vl}\f3{\darkblue\vl}$ \NC \NR +% \NC \tex {f4} \tex {thickspace} \NC \tex {b4} \tex {negthickspace} \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR +% \NC \tex {f5} \tex {enspace} \NC \tex {b5} \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR +% \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR +% \stoptabulate + +% \unexpanded\def\negenspace{\kern-.5\emwidth} +% \unexpanded\def\negemspace{\kern- \emwidth} +% +% \unexpanded\def\math_f#1% +% {\ifcase#1\or +% \hairspace +% \or +% \thinspace +% \or +% \medspace +% \or +% \thickspace +% \or +% \enspace +% \or +% \emspace +% \fi} +% +% \unexpanded\def\math_b#1% +% {\ifcase#1\or +% \neghairspace +% \or +% \negthinspace +% \or +% \negmedspace +% \or +% \negthickspace +% \or +% \negenspace +% \or +% \negemspace +% \fi} +% +% \appendtoks +% \let\f\math_f +% \let\b\math_b +% \to \everymathematics + +%D Experiment + +\unexpanded\def\math_scripts_stack + {\attribute\mathunstackattribute\attributeunsetvalue} + +\unexpanded\def\math_scripts_unstack + {\clf_enablescriptunstacking + \attribute\mathunstackattribute\plusone} + +\appendtoks + \let\stackscripts \math_scripts_stack + \let\unstackscripts\math_scripts_unstack +\to \everymathematics + \protect \endinput % % not used (yet) diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua b/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua index 529837cfaa6..ea758358754 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-noa.lua @@ -19,7 +19,7 @@ if not modules then modules = { } end modules ['math-noa'] = { -- 20D6 -> 2190 -- 20D7 -> 2192 --- todo: most is math_char so we can have simple dedicated loops +-- todo: most is mathchar_code so we can have simple dedicated loops -- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types) @@ -31,177 +31,184 @@ local insert, remove = table.insert, table.remove local div = math.div local bor, band = bit32.bor, bit32.band -local fonts = fonts -local nodes = nodes -local node = node -local mathematics = mathematics -local context = context - -local otf = fonts.handlers.otf -local otffeatures = fonts.constructors.features.otf -local registerotffeature = otffeatures.register - -local privateattribute = attributes.private -local registertracker = trackers.register -local registerdirective = directives.register -local logreporter = logs.reporter -local setmetatableindex = table.setmetatableindex - -local colortracers = nodes.tracers.colors - -local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end) -local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end) -local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end) -local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end) -local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end) -local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end) -local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end) -local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end) -local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end) -local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end) -local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end) -local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end) -local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end) -local trace_families = false registertracker("math.families", function(v) trace_families = v end) -local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end) - -local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end) - -local report_processing = logreporter("mathematics","processing") -local report_remapping = logreporter("mathematics","remapping") -local report_normalizing = logreporter("mathematics","normalizing") -local report_collapsing = logreporter("mathematics","collapsing") -local report_fixing = logreporter("mathematics","fixing") -local report_patching = logreporter("mathematics","patching") -local report_goodies = logreporter("mathematics","goodies") -local report_variants = logreporter("mathematics","variants") -local report_alternates = logreporter("mathematics","alternates") -local report_italics = logreporter("mathematics","italics") -local report_kernpairs = logreporter("mathematics","kernpairs") -local report_domains = logreporter("mathematics","domains") -local report_families = logreporter("mathematics","families") -local report_fences = logreporter("mathematics","fences") - -local a_mathrendering = privateattribute("mathrendering") -local a_exportstatus = privateattribute("exportstatus") - -local nuts = nodes.nuts -local nodepool = nuts.pool -local tonut = nuts.tonut -local tonode = nuts.tonode -local nutstring = nuts.tostring - -local setfield = nuts.setfield -local setlink = nuts.setlink -local setlist = nuts.setlist -local setnext = nuts.setnext -local setprev = nuts.setprev -local setchar = nuts.setchar -local setfam = nuts.setfam -local setsubtype = nuts.setsubtype -local setattr = nuts.setattr -local setattrlist = nuts.setattrlist - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getboth = nuts.getboth -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getfont = nuts.getfont -local getfam = nuts.getfam -local getattr = nuts.getattr -local getlist = nuts.getlist - -local getnucleus = nuts.getnucleus -local getsub = nuts.getsub -local getsup = nuts.getsup - -local setnucleus = nuts.setnucleus -local setsub = nuts.setsub -local setsup = nuts.setsup - -local flush_node = nuts.flush -local copy_node = nuts.copy -local slide_nodes = nuts.slide -local set_visual = nuts.setvisual - -local mlist_to_hlist = nodes.mlist_to_hlist - -local font_of_family = node.family_font - -local new_kern = nodepool.kern -local new_submlist = nodepool.submlist -local new_noad = nodepool.noad -local new_delimiter = nodepool.delimiter -local new_fence = nodepool.fence - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local fontcharacters = fonthashes.characters -local fontitalics = fonthashes.italics - -local variables = interfaces.variables -local texsetattribute = tex.setattribute -local texgetattribute = tex.getattribute -local unsetvalue = attributes.unsetvalue -local implement = interfaces.implement - -local v_reset = variables.reset - -local chardata = characters.data - -noads = noads or { } -- todo: only here -local noads = noads - -noads.processors = noads.processors or { } -local processors = noads.processors - -noads.handlers = noads.handlers or { } -local handlers = noads.handlers - -local tasks = nodes.tasks -local enableaction = tasks.enableaction -local setaction = tasks.setaction - -local nodecodes = nodes.nodecodes -local noadcodes = nodes.noadcodes -local fencecodes = nodes.fencecodes - -local noad_ord = noadcodes.ord -local noad_rel = noadcodes.rel -local noad_bin = noadcodes.bin -local noad_open = noadcodes.open -local noad_close = noadcodes.close -local noad_punct = noadcodes.punct -local noad_opdisplaylimits = noadcodes.opdisplaylimits -local noad_oplimits = noadcodes.oplimits -local noad_opnolimits = noadcodes.opnolimits -local noad_inner = noadcodes.inner - -local math_noad = nodecodes.noad -- attr nucleus sub sup -local math_accent = nodecodes.accent -- attr nucleus sub sup accent -local math_radical = nodecodes.radical -- attr nucleus sub sup left degree -local math_fraction = nodecodes.fraction -- attr nucleus sub sup left right -local math_subbox = nodecodes.subbox -- attr list -local math_submlist = nodecodes.submlist -- attr list -local math_char = nodecodes.mathchar -- attr fam char -local math_textchar = nodecodes.mathtextchar -- attr fam char -local math_delim = nodecodes.delim -- attr small_fam small_char large_fam large_char ------ math_style = nodecodes.style -- attr style -local math_choice = nodecodes.choice -- attr display text script scriptscript -local math_fence = nodecodes.fence -- attr subtype - -local left_fence_code = fencecodes.left -local middle_fence_code = fencecodes.middle -local right_fence_code = fencecodes.right +local fonts = fonts +local nodes = nodes +local node = node +local mathematics = mathematics +local context = context + +local otf = fonts.handlers.otf +local otffeatures = fonts.constructors.features.otf +local registerotffeature = otffeatures.register + +local privateattribute = attributes.private +local registertracker = trackers.register +local registerdirective = directives.register +local logreporter = logs.reporter +local setmetatableindex = table.setmetatableindex + +local colortracers = nodes.tracers.colors + +local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end) +local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end) +local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end) +local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end) +local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end) +local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end) +local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end) +local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end) +local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end) +local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end) +local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end) +local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end) +local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end) +local trace_families = false registertracker("math.families", function(v) trace_families = v end) +local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end) +local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end) + +local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end) + +local report_processing = logreporter("mathematics","processing") +local report_remapping = logreporter("mathematics","remapping") +local report_normalizing = logreporter("mathematics","normalizing") +local report_collapsing = logreporter("mathematics","collapsing") +local report_fixing = logreporter("mathematics","fixing") +local report_patching = logreporter("mathematics","patching") +local report_goodies = logreporter("mathematics","goodies") +local report_variants = logreporter("mathematics","variants") +local report_alternates = logreporter("mathematics","alternates") +local report_italics = logreporter("mathematics","italics") +local report_kernpairs = logreporter("mathematics","kernpairs") +local report_domains = logreporter("mathematics","domains") +local report_families = logreporter("mathematics","families") +local report_fences = logreporter("mathematics","fences") +local report_unstacking = logreporter("mathematics","unstack") + +local a_mathrendering = privateattribute("mathrendering") +local a_exportstatus = privateattribute("exportstatus") + +local nuts = nodes.nuts +local nodepool = nuts.pool +local tonut = nuts.tonut +local nutstring = nuts.tostring + +local setfield = nuts.setfield +local setlink = nuts.setlink +local setlist = nuts.setlist +local setnext = nuts.setnext +local setprev = nuts.setprev +local setchar = nuts.setchar +local setfam = nuts.setfam +local setsubtype = nuts.setsubtype +local setattr = nuts.setattr +local setattrlist = nuts.setattrlist +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth + +local getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getboth = nuts.getboth +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local getfont = nuts.getfont +local getfam = nuts.getfam +local getattr = nuts.getattr +local getlist = nuts.getlist +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup + +local setnucleus = nuts.setnucleus +local setsub = nuts.setsub +local setsup = nuts.setsup + +local flush_node = nuts.flush +local copy_node = nuts.copy +local slide_nodes = nuts.slide +local set_visual = nuts.setvisual + +local mlist_to_hlist = nuts.mlist_to_hlist + +local font_of_family = node.family_font + +local new_kern = nodepool.kern +local new_submlist = nodepool.submlist +local new_noad = nodepool.noad +local new_delimiter = nodepool.delimiter +local new_fence = nodepool.fence + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontcharacters = fonthashes.characters +local fontitalics = fonthashes.italics + +local variables = interfaces.variables +local texsetattribute = tex.setattribute +local texgetattribute = tex.getattribute +local unsetvalue = attributes.unsetvalue +local implement = interfaces.implement + +local v_reset = variables.reset + +local chardata = characters.data + +noads = noads or { } -- todo: only here +local noads = noads + +noads.processors = noads.processors or { } +local processors = noads.processors + +noads.handlers = noads.handlers or { } +local handlers = noads.handlers + +local tasks = nodes.tasks +local enableaction = tasks.enableaction +local setaction = tasks.setaction + +local nodecodes = nodes.nodecodes +local noadcodes = nodes.noadcodes +local fencecodes = nodes.fencecodes + +local ordnoad_code = noadcodes.ord +local relnode_code = noadcodes.rel +local binnoad_code = noadcodes.bin +local opennoad_code = noadcodes.open +local closenoad_code = noadcodes.close +local punctnoad_code = noadcodes.punct +local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits +local oplimitsnoad_code = noadcodes.oplimits +local opnolimitsnoad_code = noadcodes.opnolimits +local innernoad_code = noadcodes.inner + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +----- style_code = nodecodes.style -- attr style +local math_choice = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local leftfence_code = fencecodes.left +local middlefence_code = fencecodes.middle +local rightfence_code = fencecodes.right -- local mathclasses = mathematics.classes -- local fenceclasses = { --- [left_fence_code] = mathclasses.open, --- [middle_fence_code] = mathclasses.middle, --- [right_fence_code] = mathclasses.close, +-- [leftfence_code] = mathclasses.open, +-- [middlefence_code] = mathclasses.middle, +-- [rightfence_code] = mathclasses.close, -- } -- this initial stuff is tricky as we can have removed and new nodes with the same address @@ -211,6 +218,7 @@ local right_fence_code = fencecodes.right -- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st local function process(start,what,n,parent) + if n then n = n + 1 else @@ -224,9 +232,9 @@ local function process(start,what,n,parent) while start do local id = getid(start) if trace_processing then - if id == math_noad then + if id == noad_code then report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)]) - elseif id == math_char then + elseif id == mathchar_code then local char = getchar(start) local font = getfont(start) local fam = getfam(start) @@ -256,16 +264,16 @@ local function process(start,what,n,parent) -- report_processing("stop processing") end end - elseif id == math_noad then + elseif id == noad_code then -- single characters are like this local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list noad = getsup (start) if noad then process(noad,what,n,start) end -- list noad = getsub (start) if noad then process(noad,what,n,start) end -- list - elseif id == math_char or id == math_textchar or id == math_delim then + elseif id == mathchar_code or id == mathtextchar_code or id == delim_code then break - elseif id == math_subbox or id == math_submlist then + elseif id == subbox_code or id == submlist_code then local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !) - elseif id == math_fraction then + elseif id == fraction_code then local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter @@ -275,21 +283,21 @@ local function process(start,what,n,parent) noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list - elseif id == math_fence then + elseif id == fence_code then local noad = getfield(start,"delim") if noad then process(noad,what,n,start) end -- delimiter - elseif id == math_radical then + elseif id == radical_code then local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list noad = getsup (start) if noad then process(noad,what,n,start) end -- list noad = getsub (start) if noad then process(noad,what,n,start) end -- list noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list - elseif id == math_accent then + elseif id == accent_code then local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list noad = getsup (start) if noad then process(noad,what,n,start) end -- list noad = getsub (start) if noad then process(noad,what,n,start) end -- list noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list - -- elseif id == math_style then + -- elseif id == style_code then -- -- has a next -- else -- -- glue, penalty, etc @@ -297,20 +305,20 @@ local function process(start,what,n,parent) start = getnext(start) end if not parent then - return initial, true -- only first level -- for now + return initial -- only first level -- for now end end local function processnested(current,what,n) local noad = nil local id = getid(current) - if id == math_noad then + if id == noad_code then noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list noad = getsup (current) if noad then process(noad,what,n,current) end -- list noad = getsub (current) if noad then process(noad,what,n,current) end -- list - elseif id == math_subbox or id == math_submlist then + elseif id == subbox_code or id == submlist_code then noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !) - elseif id == math_fraction then + elseif id == fraction_code then noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter @@ -320,15 +328,15 @@ local function processnested(current,what,n) noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list - elseif id == math_fence then + elseif id == fence_code then noad = getfield(current,"delim") if noad then process(noad,what,n,current) end -- delimiter - elseif id == math_radical then + elseif id == radical_code then noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list noad = getsup (current) if noad then process(noad,what,n,current) end -- list noad = getsub (current) if noad then process(noad,what,n,current) end -- list noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list - elseif id == math_accent then + elseif id == accent_code then noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list noad = getsup (current) if noad then process(noad,what,n,current) end -- list noad = getsub (current) if noad then process(noad,what,n,current) end -- list @@ -340,13 +348,13 @@ end local function processstep(current,process,n,id) local noad = nil local id = id or getid(current) - if id == math_noad then + if id == noad_code then noad = getnucleus(current) if noad then process(noad,n,current) end -- list noad = getsup (current) if noad then process(noad,n,current) end -- list noad = getsub (current) if noad then process(noad,n,current) end -- list - elseif id == math_subbox or id == math_submlist then + elseif id == subbox_code or id == submlist_code then noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !) - elseif id == math_fraction then + elseif id == fraction_code then noad = getfield(current,"num") if noad then process(noad,n,current) end -- list noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter @@ -356,15 +364,15 @@ local function processstep(current,process,n,id) noad = getfield(current,"text") if noad then process(noad,n,current) end -- list noad = getfield(current,"script") if noad then process(noad,n,current) end -- list noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list - elseif id == math_fence then + elseif id == fence_code then noad = getfield(current,"delim") if noad then process(noad,n,current) end -- delimiter - elseif id == math_radical then + elseif id == radical_code then noad = getnucleus(current) if noad then process(noad,n,current) end -- list noad = getsup (current) if noad then process(noad,n,current) end -- list noad = getsub (current) if noad then process(noad,n,current) end -- list noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list - elseif id == math_accent then + elseif id == accent_code then noad = getnucleus(current) if noad then process(noad,n,current) end -- list noad = getsup (current) if noad then process(noad,n,current) end -- list noad = getsub (current) if noad then process(noad,n,current) end -- list @@ -374,15 +382,14 @@ local function processstep(current,process,n,id) end local function processnoads(head,actions,banner) - local h, d if trace_processing then report_processing("start %a",banner) - h, d = process(tonut(head),actions) + head = process(head,actions) report_processing("stop %a",banner) else - h, d = process(tonut(head),actions) + head = process(head,actions) end - return h and tonode(h) or head, d == nil and true or d + return head end noads.process = processnoads @@ -456,7 +463,35 @@ do "pseudobold", } - families[math_char] = function(pointer) + families[fraction_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[noad_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[mathchar_code] = function(pointer) if getfam(pointer) == 0 then local a = getattr(pointer,a_mathfamily) if a and a > 0 then @@ -501,8 +536,7 @@ do end end end - - families[math_delim] = function(pointer) + families[delim_code] = function(pointer) if getfield(pointer,"small_fam") == 0 then local a = getattr(pointer,a_mathfamily) if a and a > 0 then @@ -534,7 +568,7 @@ do -- will become: - -- families[math_delim] = function(pointer) + -- families[delim_code] = function(pointer) -- if getfam(pointer) == 0 then -- local a = getattr(pointer,a_mathfamily) -- if a and a > 0 then @@ -556,11 +590,11 @@ do -- end -- end - families[math_textchar] = families[math_char] + families[mathtextchar_code] = families[mathchar_code] function handlers.families(head,style,penalties) processnoads(head,families,"families") - return true + return true -- not needed end end @@ -604,7 +638,7 @@ do end end - relocate[math_char] = function(pointer) + relocate[mathchar_code] = function(pointer) local g = getattr(pointer,a_mathgreek) or 0 local a = getattr(pointer,a_mathalphabet) or 0 local char = getchar(pointer) @@ -671,13 +705,13 @@ do end end - relocate[math_textchar] = function(pointer) + relocate[mathtextchar_code] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:init") end end - relocate[math_delim] = function(pointer) + relocate[delim_code] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:fina") end @@ -685,7 +719,7 @@ do function handlers.relocate(head,style,penalties) processnoads(head,relocate,"relocate") - return true + return true -- not needed end end @@ -698,7 +732,7 @@ do local rendersets = mathematics.renderings.numbers or { } -- store - render[math_char] = function(pointer) + render[mathchar_code] = function(pointer) local attr = getattr(pointer,a_mathrendering) if attr and attr > 0 then local char = getchar(pointer) @@ -719,7 +753,7 @@ do function handlers.render(head,style,penalties) processnoads(head,render,"render") - return true + return true -- not needed end end @@ -739,51 +773,46 @@ do local a_mathsize = privateattribute("mathsize") -- this might move into other fence code local resize = { } - resize[math_fence] = function(pointer) + resize[fence_code] = function(pointer) local subtype = getsubtype(pointer) - if subtype == left_fence_code or subtype == right_fence_code then + if subtype == leftfence_code or subtype == rightfence_code then local a = getattr(pointer,a_mathsize) if a and a > 0 then - local method, size = div(a,100), a % 100 + local method = div(a,100) + local size = a % 100 setattr(pointer,a_mathsize,0) local delimiter = getfield(pointer,"delim") - local chr = getfield(delimiter,"small_char") + local chr = getchar(delimiter) if chr > 0 then - local fam = getfield(delimiter,"small_fam") + local fam = getfam(delimiter) local id = font_of_family(fam) if id > 0 then - setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method)) + local data = fontdata[id] + local char = mathematics.big(data,chr,size,method) + local ht = getheight(pointer) + local dp = getdepth(pointer) + if ht == 1 or dp == 1 then -- 1 scaled point is a signal + local chardata = data.characters[char] + if ht == 1 then + setheight(pointer,chardata.height) + end + if dp == 1 then + setdepth(pointer,chardata.depth) + end + end + if trace_fences then + report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size) + end + setchar(delimiter,char) end end end end end - -- will become: - - -- resize[math_fence] = function(pointer) - -- local subtype = getsubtype(pointer) - -- if subtype == left_fence_code or subtype == right_fence_code then - -- local a = getattr(pointer,a_mathsize) - -- if a and a > 0 then - -- local method, size = div(a,100), a % 100 - -- setattr(pointer,a_mathsize,0) - -- local delimiter = getfield(pointer,"delim") - -- local chr = getchar(delimiter) - -- if chr > 0 then - -- local fam = getfam(delimiter) - -- local id = font_of_family(fam) - -- if id > 0 then - -- setchar(delimiter,mathematics.big(fontdata[id],chr,size,method)) - -- end - -- end - -- end - -- end - -- end - function handlers.resize(head,style,penalties) processnoads(head,resize,"resize") - return true + return true -- not needed end end @@ -797,8 +826,8 @@ do local dummyfencechar = 0x2E local function makefence(what,char) - local d = new_delimiter() - local f = new_fence() + local d = new_delimiter() -- todo: attr + local f = new_fence() -- todo: attr if char then local sym = getnucleus(char) local chr = getchar(sym) @@ -821,8 +850,8 @@ do -- will become -- local function makefence(what,char) - -- local d = new_delimiter() - -- local f = new_fence() + -- local d = new_delimiter() -- todo: attr + -- local f = new_fence() -- todo: attr -- if char then -- local sym = getnucleus(char) -- local chr = getchar(sym) @@ -843,7 +872,7 @@ do local function makelist(noad,f_o,o_next,c_prev,f_c,middle) local list = new_submlist() setlist(list,f_o) - setsubtype(noad,noad_inner) + setsubtype(noad,innernoad_code) setnucleus(noad,list) setlink(f_o,o_next) setlink(c_prev,f_c) @@ -854,7 +883,7 @@ do local m = middle[current] if m then local next = getnext(current) - local fence = makefence(middle_fence_code,current) + local fence = makefence(middlefence_code,current) setnucleus(current) flush_node(current) middle[current] = nil @@ -876,8 +905,8 @@ do if o_next == close then return close else - local f_o = makefence(left_fence_code,open) - local f_c = makefence(right_fence_code,close) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code,close) makelist(open,f_o,o_next,c_prev,f_c,middle) setnucleus(close) flush_node(close) @@ -890,8 +919,8 @@ do end local function convert_open(open,last,middle) - local f_o = makefence(left_fence_code,open) - local f_c = makefence(right_fence_code) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code) local o_prev, o_next = getboth(open) local l_prev, l_next = getboth(last) makelist(open,f_o,o_next,last,f_c,middle) @@ -903,8 +932,8 @@ do end local function convert_close(close,first,middle) - local f_o = makefence(left_fence_code) - local f_c = makefence(right_fence_code,close) + local f_o = makefence(leftfence_code) + local f_c = makefence(rightfence_code,close) local c_prev = getprev(close) makelist(close,f_o,first,c_prev,f_c,middle) return close @@ -922,7 +951,7 @@ do local middle = nil -- todo: use properties while current do local id = getid(current) - if id == math_noad then + if id == noad_code then local a = getattr(current,a_autofence) if a and a > 0 then local stack = stacks[n] @@ -1009,7 +1038,7 @@ do function handlers.autofences(head,style,penalties) if enabled then -- tex.modes.c_math_fences_auto -- inspect(nodes.totree(head)) - processfences(tonut(head),1) + processfences(head,1) -- inspect(nodes.totree(head)) end end @@ -1031,9 +1060,9 @@ do local next = getnext(pointer) local start_super, stop_super, start_sub, stop_sub local mode = "unset" - while next and getid(next) == math_noad do + while next and getid(next) == noad_code do local nextnucleus = getnucleus(next) - if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then + if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then local char = getchar(nextnucleus) local s = superscripts[char] if s then @@ -1088,6 +1117,18 @@ do setnext(stop_super) end if start_sub then + +-- if mode == "sub" then +-- local sup = getsup(pointer) +-- if sup and not getsub(pointer) then +-- local nxt = getnext(pointer) +-- local new = new_noad(pointer) +-- setnucleus(new,new_submlist()) +-- setlink(pointer,new,nxt) +-- pointer = new +-- end +-- end + if start_sub == stop_sub then setsub(pointer,getnucleus(start_sub)) else @@ -1103,16 +1144,57 @@ do -- we could return stop end - unscript[math_char] = replace -- not noads as we need to recurse + unscript[mathchar_code] = replace -- not noads as we need to recurse function handlers.unscript(head,style,penalties) processnoads(head,unscript,"unscript") - -- processnoads(head,checkers,"checkers") - return true + return true -- not needed end end +do + + local unstack = { } noads.processors.unstack = unstack + local enabled = false + local a_unstack = privateattribute("mathunstack") + + unstack[noad_code] = function(pointer) + if getattr(pointer,a_unstack) then + local sup = getsup(pointer) + local sub = getsub(pointer) + if sup and sub then + -- if trace_unstacking then + -- report_unstacking() -- todo ... what to show ... + -- end + local nxt = getnext(pointer) + local new = new_noad(pointer) + setnucleus(new,new_submlist()) + setsub(pointer) + setsub(new,sub) + setlink(pointer,new,nxt) + end + end + end + + function handlers.unstack(head,style,penalties) + if enabled then + processnoads(head,unstack,"unstack") + return true -- not needed + end + end + + implement { + name = "enablescriptunstacking", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.unstack") + enabled = true + end + } + +end + do local function collected(list) @@ -1306,7 +1388,7 @@ do arguments = { "integer", "string" } } - alternate[math_char] = function(pointer) -- slow + alternate[mathchar_code] = function(pointer) -- slow local a = getattr(pointer,a_mathalternate) if a and a > 0 then setattr(pointer,a_mathalternate,0) @@ -1347,7 +1429,7 @@ do function handlers.alternates(head,style,penalties) processnoads(head,alternate,"alternate") - return true + return true -- not needed end end @@ -1365,7 +1447,7 @@ end -- in opentype the italic correction of a limop is added to the width and luatex does -- some juggling that we want to avoid but we need to do something here (in fact, we could --- better fix the width of the character +-- better fix the width of the character) do @@ -1382,8 +1464,8 @@ do local c_negative_d = "trace:dr" local function insert_kern(current,kern) - local sub = new_submlist() - local noad = new_noad() + local sub = new_submlist() -- todo: attr + local noad = new_noad() -- todo: attr setlist(sub,kern) setnext(kern,noad) setnucleus(noad,current) @@ -1393,7 +1475,7 @@ do registertracker("math.italics.visualize", function(v) if v then italic_kern = function(k) - local n = new_kern(k) + local n = new_kern(k) -- todo: attr set_visual(n,"italic") return n end @@ -1454,7 +1536,7 @@ do end - italics[math_char] = function(pointer,what,n,parent) + italics[mathchar_code] = function(pointer,what,n,parent) local method = getattr(pointer,a_mathitalics) if method and method > 0 and method < 100 then local char = getchar(pointer) @@ -1485,7 +1567,7 @@ do function handlers.italics(head,style,penalties) processnoads(head,italics,"italics") - return true + return true -- not needed end local enable = function() @@ -1582,7 +1664,7 @@ do -- no correction after prime because that moved to a superscript - kernpairs[math_char] = function(pointer,what,n,parent) + kernpairs[mathchar_code] = function(pointer,what,n,parent) if getattr(pointer,a_kernpairs) == 1 then local font = getfont(pointer) local list = hash[font] @@ -1591,7 +1673,7 @@ do local found = list[first] if found then local next = getnext(parent) - if next and getid(next) == math_noad then + if next and getid(next) == noad_code then pointer = getnucleus(next) if pointer then if getfont(pointer) == font then @@ -1602,7 +1684,7 @@ do if trace_kernpairs then report_kernpairs("adding %p kerning between %C and %C",kern,first,second) end - setlink(parent,new_kern(kern),getnext(parent)) + setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr end end end @@ -1614,7 +1696,7 @@ do function handlers.kernpairs(head,style,penalties) processnoads(head,kernpairs,"kernpairs") - return true + return true -- not needed end end @@ -1629,20 +1711,20 @@ do local collapse = { } local mathlists = characters.mathlists local validpair = { - [noad_ord] = true, - [noad_rel] = true, - [noad_bin] = true, -- new - [noad_open] = true, -- new - [noad_close] = true, -- new - [noad_punct] = true, -- new - [noad_opdisplaylimits] = true, - [noad_oplimits] = true, - [noad_opnolimits] = true, + [ordnoad_code] = true, + [relnode_code] = true, + [binnoad_code] = true, -- new + [opennoad_code] = true, -- new + [closenoad_code] = true, -- new + [punctnoad_code] = true, -- new + [opdisplaylimitsnoad_code] = true, + [oplimitsnoad_code] = true, + [opnolimitsnoad_code] = true, } local reported = setmetatableindex("table") - collapse[math_char] = function(pointer,what,n,parent) + collapse[mathchar_code] = function(pointer,what,n,parent) if parent and mathlists[getchar(pointer)] then local found, last, lucleus, lsup, lsub, category @@ -1727,7 +1809,7 @@ do function noads.handlers.collapse(head,style,penalties) processnoads(head,collapse,"collapse") - return true + return true -- not needed end local enable = function() @@ -1784,7 +1866,7 @@ do -- local function movesubscript(parent,current_nucleus,oldchar,newchar) -- local prev = getprev(parent) - -- if prev and getid(prev) == math_noad then + -- if prev and getid(prev) == noad_code then -- local psup = getsup(prev) -- local psub = getsub(prev) -- if not psup and not psub then @@ -1827,7 +1909,7 @@ do setnucleus(parent,dummy) end - fixscripts[math_char] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off + fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off if parent then local oldchar = getchar(pointer) local newchar = movesub[oldchar] @@ -1846,7 +1928,7 @@ do -- print("[char] --- sup") else local prev = getprev(parent) - if prev and getid(prev) == math_noad then + if prev and getid(prev) == noad_code then local psub = getsub(prev) local psup = getsup(prev) if psub then @@ -1875,7 +1957,7 @@ do function noads.handlers.fixscripts(head,style,penalties) processnoads(head,fixscripts,"fixscripts") - return true + return true -- not needed end end @@ -1901,14 +1983,14 @@ do [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, } - variants[math_char] = function(pointer,what,n,parent) -- also set export value + variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value local char = getchar(pointer) local selector = validvariants[char] if selector then local next = getnext(parent) - if next and getid(next) == math_noad then + if next and getid(next) == noad_code then local nucleus = getnucleus(next) - if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then + if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then local variant local tfmdata = fontdata[getfont(pointer)] local mathvariants = tfmdata.resources.variants -- and variantdata @@ -1939,7 +2021,7 @@ do function handlers.variants(head,style,penalties) processnoads(head,variants,"unicode variant") - return true + return true -- not needed end end @@ -1950,25 +2032,25 @@ do local classes = { } local colors = { - [noad_rel] = "trace:dr", - [noad_ord] = "trace:db", - [noad_bin] = "trace:dg", - [noad_open] = "trace:dm", - [noad_close] = "trace:dm", - [noad_punct] = "trace:dc", - -- [noad_opdisplaylimits] = "", - -- [noad_oplimits] = "", - -- [noad_opnolimits] = "", - -- [noad_inner = "", - -- [noad_under = "", - -- [noad_over = "", - -- [noad_vcenter = "", + [relnode_code] = "trace:dr", + [ordnoad_code] = "trace:db", + [binnoad_code] = "trace:dg", + [opennoad_code] = "trace:dm", + [closenoad_code] = "trace:dm", + [punctnoad_code] = "trace:dc", + -- [opdisplaylimitsnoad_code] = "", + -- [oplimitsnoad_code] = "", + -- [opnolimitsnoad_code] = "", + -- [innernoad_code = "", + -- [undernoad_code] = "", + -- [overnoad_code] = "", + -- [vcenternoad_code] = "", } local setcolor = colortracers.set local resetcolor = colortracers.reset - classes[math_char] = function(pointer,what,n,parent) + classes[mathchar_code] = function(pointer,what,n,parent) local color = colors[getsubtype(parent)] if color then setcolor(pointer,color) @@ -1979,7 +2061,7 @@ do function handlers.classes(head,style,penalties) processnoads(head,classes,"classes") - return true + return true -- not needed end registertracker("math.classes",function(v) @@ -2006,11 +2088,11 @@ do local a_mathdomain = privateattribute("mathdomain") mathematics.domains = categories local permitted = { - ordinary = noad_ord, - binary = noad_bin, - relation = noad_rel, - punctuation = noad_punct, - inner = noad_inner, + ordinary = ordnoad_code, + binary = binnoad_code, + relation = relnode_code, + punctuation = punctnoad_code, + inner = innernoad_code, } function mathematics.registerdomain(data) @@ -2113,7 +2195,7 @@ do return hash end - domains[math_char] = function(pointer,what,n,parent) + domains[mathchar_code] = function(pointer,what,n,parent) local attr = getattr(pointer,a_mathdomain) if attr then local domain = numbers[attr] @@ -2140,7 +2222,7 @@ do function handlers.domains(head,style,penalties) processnoads(head,domains,"domains") - return true + return true -- not needed end end @@ -2148,7 +2230,7 @@ end -- just for me function handlers.showtree(head,style,penalties) - inspect(nodes.totree(head)) + inspect(nodes.totree(tonut(head))) end registertracker("math.showtree",function(v) @@ -2163,7 +2245,7 @@ do local visual = false function handlers.makeup(head) - applyvisuals(tonut(head),visual) + applyvisuals(head,visual) end registertracker("math.makeup",function(v) @@ -2184,9 +2266,15 @@ do -- end) function builders.kernel.mlist_to_hlist(head,style,penalties) - return mlist_to_hlist(head,style,force_penalties or penalties), true + return mlist_to_hlist(head,style,force_penalties or penalties) end + -- function builders.kernel.mlist_to_hlist(head,style,penalties) + -- local h = mlist_to_hlist(head,style,force_penalties or penalties) + -- inspect(nodes.totree(h,true,true,true)) + -- return h + -- end + implement { name = "setmathpenalties", arguments = "integer", @@ -2197,41 +2285,15 @@ do end --- function builders.kernel.mlist_to_hlist(head,style,penalties) --- print("!!!!!!! BEFORE",penalties) --- for n in node.traverse(head) do print(n) end --- print("!!!!!!!") --- head = mlist_to_hlist(head,style,penalties) --- print("!!!!!!! AFTER") --- for n in node.traverse(head) do print(n) end --- print("!!!!!!!") --- return head, true --- end - -tasks.new { - name = "math", - arguments = 2, - processor = utilities.sequencers.nodeprocessor, - sequence = { - "before", - "normalizers", - "builders", - "after", - }, -} - -tasks.freezegroup("math", "normalizers") -- experimental -tasks.freezegroup("math", "builders") -- experimental - local actions = tasks.actions("math") -- head, style, penalties local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming function processors.mlist_to_hlist(head,style,penalties) starttiming(noads) - local head, done = actions(head,style,penalties) + head = actions(head,style,penalties) stoptiming(noads) - return head, done + return head end callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list") diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv index d0e7e377d12..1003444b86b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/math-pln.mkiv @@ -171,7 +171,7 @@ \crcr \noalign\bgroup \kern\scratchdimentwo - \global\let\cr\endline + \glet\cr\endline \egroup }% \ialign{% diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-spa.lua b/Master/texmf-dist/tex/context/base/mkiv/math-spa.lua index 92ee662b9a6..33d9501d818 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-spa.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-spa.lua @@ -8,24 +8,23 @@ if not modules then modules = { } end modules ['math-spa'] = { -- for the moment (when testing) we use a penalty 1 -local penalty_code = nodes.nodecodes.penalty -local glue_code = nodes.nodecodes.glue +local penalty_code = nodes.nodecodes.penalty +local glue_code = nodes.nodecodes.glue -local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode -local getid = nuts.getid -local getnext = nuts.getnext -local getwidth = nuts.getwidth -local setglue = nuts.setglue -local getpenalty = nuts.getpenalty -local setpenalty = nuts.setpenalty +local nuts = nodes.nuts +local tonut = nodes.tonut +local tonode = nodes.tonode -local traverse_id = nuts.traverse_id -local get_dimensions = nuts.dimensions +local getid = nuts.getid +local getnext = nuts.getnext +local getwidth = nuts.getwidth +local setglue = nuts.setglue +local getpenalty = nuts.getpenalty +local setpenalty = nuts.setpenalty +local getdimensions = nuts.dimensions +local nextglue = nuts.traversers.glue - -local texsetdimen = tex.setdimen +local texsetdimen = tex.setdimen local v_none = interfaces.variables.none local v_auto = interfaces.variables.auto @@ -33,9 +32,8 @@ local v_auto = interfaces.variables.auto local method = v_none local distance = 0 -function noads.handlers.align(l) +function noads.handlers.align(h) if method ~= v_none then - local h = tonut(l) if method == v_auto then local s = h while s do @@ -47,7 +45,7 @@ function noads.handlers.align(l) s = n n = getnext(s) end - local w = get_dimensions(h,n) + distance + local w = getdimensions(h,n) + distance texsetdimen("global","d_strc_math_indent",w) break end @@ -56,13 +54,12 @@ function noads.handlers.align(l) else texsetdimen("global","d_strc_math_indent",distance) end - for n in traverse_id(glue_code,h) do + for n in nextglue, h do setglue(n,getwidth(n),0,0) end else -- texsetdimen("global","d_strc_math_indent",0) end - return l, true end interfaces.implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi b/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi index c9d469d617c..92325d0afd0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/math-stc.mkvi @@ -413,13 +413,13 @@ \fi % \ifdim\wd\scratchboxone<\scratchwidth - \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work + \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work \fi \ifdim\wd\scratchboxtwo<\scratchwidth - \setbox\scratchboxtwo\hbox to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}% + \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}% \fi \ifdim\wd\scratchboxthree<\scratchwidth - \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}% + \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}% \fi % \ifcsname\??mathstackerslocation\p_location\endcsname @@ -448,7 +448,7 @@ \fi % \ifzeropt\scratchdistance\else - \setbox\scratchboxthree\hbox{\lower\scratchdistance\box\scratchboxthree}% + \setbox\scratchboxthree\hpack{\lower\scratchdistance\box\scratchboxthree}% \fi % \math_stackers_normalize_three @@ -603,7 +603,7 @@ \advance\scratchwidth2\scratchhoffset % \setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname - \setbox\scratchboxthree\hbox to \scratchwidth{\hss\box\scratchboxthree\hss}% + \setbox\scratchboxthree\hpack to \scratchwidth{\hss\box\scratchboxthree\hss}% % \scratchunicode#codeextra\relax \ifcase\scratchunicode\else @@ -803,10 +803,10 @@ \advance\scratchwidth2\scratchhoffset % \ifdim\wd\scratchboxone<\scratchwidth - \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}% + \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% \fi \ifdim\wd\scratchboxthree<\scratchwidth - \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}% + \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}% \fi % \math_stackers_normalize_three diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua index d1ed90d389b..03f9e70bbbb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua @@ -14,90 +14,92 @@ if not modules then modules = { } end modules ['math-tag'] = { local find, match = string.find, string.match local insert, remove, concat = table.insert, table.remove, table.concat -local attributes = attributes -local nodes = nodes - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getchar = nuts.getchar -local getfont = nuts.getfont -local getlist = nuts.getlist -local getfield = nuts.getfield -local getdisc = nuts.getdisc -local getsubtype = nuts.getsubtype -local getattr = nuts.getattr -local setattr = nuts.setattr -local getcomponents = nuts.getcomponents -local getwidth = nuts.getwidth - -local getnucleus = nuts.getnucleus -local getsub = nuts.getsub -local getsup = nuts.getsup - -local set_attributes = nuts.setattributes -local traverse_nodes = nuts.traverse - -local nodecodes = nodes.nodecodes - -local math_noad_code = nodecodes.noad -- attr nucleus sub sup -local math_accent_code = nodecodes.accent -- attr nucleus sub sup accent -local math_radical_code = nodecodes.radical -- attr nucleus sub sup left degree -local math_fraction_code = nodecodes.fraction -- attr nucleus sub sup left right -local math_box_code = nodecodes.subbox -- attr list -local math_sub_code = nodecodes.submlist -- attr list -local math_char_code = nodecodes.mathchar -- attr fam char -local math_textchar_code = nodecodes.mathtextchar -- attr fam char -local math_delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char -local math_style_code = nodecodes.style -- attr style -local math_choice_code = nodecodes.choice -- attr display text script scriptscript -local math_fence_code = nodecodes.fence -- attr subtype - -local accentcodes = nodes.accentcodes - -local math_fixed_top = accentcodes.fixedtop -local math_fixed_bottom = accentcodes.fixedbottom -local math_fixed_both = accentcodes.fixedboth - -local kerncodes = nodes.kerncodes - -local fontkern_code = kerncodes.fontkern -local italickern_code = kerncodes.italickern - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local math_code = nodecodes.math - -local processnoads = noads.process - -local a_tagged = attributes.private('tagged') -local a_mathcategory = attributes.private('mathcategory') -local a_mathmode = attributes.private('mathmode') - -local tags = structures.tags - -local start_tagged = tags.start -local restart_tagged = tags.restart -local stop_tagged = tags.stop -local taglist = tags.taglist - -local chardata = characters.data - -local getmathcodes = tex.getmathcodes -local mathcodes = mathematics.codes -local ordinary_code = mathcodes.ordinary -local variable_code = mathcodes.variable - -local fromunicode16 = fonts.mappings.fromunicode16 -local fontcharacters = fonts.hashes.characters - -local report_tags = logs.reporter("structure","tags") +local attributes = attributes +local nodes = nodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getid = nuts.getid +local getchar = nuts.getchar +local getfont = nuts.getfont +local getlist = nuts.getlist +local getfield = nuts.getfield +local getdisc = nuts.getdisc +local getsubtype = nuts.getsubtype +local getattr = nuts.getattr +local getattrlist = nuts.getattrlist +local setattr = nuts.setattr +local getcomponents = nuts.getcomponents -- not really needed +local getwidth = nuts.getwidth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup + +local set_attributes = nuts.setattributes + +local nextnode = nuts.traversers.node + +local nodecodes = nodes.nodecodes + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +local style_code = nodecodes.style -- attr style +local choice_code = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local accentcodes = nodes.accentcodes + +local fixedtopaccent_code = accentcodes.fixedtop +local fixedbottomaccent_code = accentcodes.fixedbottom +local fixedbothaccent_code = accentcodes.fixedboth + +local kerncodes = nodes.kerncodes + +local fontkern_code = kerncodes.fontkern +local italickern_code = kerncodes.italickern + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local math_code = nodecodes.math + +local processnoads = noads.process + +local a_tagged = attributes.private('tagged') +local a_mathcategory = attributes.private('mathcategory') +local a_mathmode = attributes.private('mathmode') + +local tags = structures.tags + +local start_tagged = tags.start +local restart_tagged = tags.restart +local stop_tagged = tags.stop +local taglist = tags.taglist + +local chardata = characters.data + +local getmathcodes = tex.getmathcodes +local mathcodes = mathematics.codes +local ordinary_mathcode = mathcodes.ordinary +local variable_mathcode = mathcodes.variable + +local fromunicode16 = fonts.mappings.fromunicode16 +local fontcharacters = fonts.hashes.characters + +local report_tags = logs.reporter("structure","tags") local process @@ -154,12 +156,19 @@ local fencesstack = { } -- glyph nodes and such can happen in under and over stuff +-- local function getunicode(n) -- instead of getchar +-- local char = getchar(n) +-- -- local font = font_of_family(getfield(n,"fam")) -- font_of_family +-- local font = getfont(n) +-- local data = fontcharacters[font][char] +-- return data.unicode or char +-- end + local function getunicode(n) -- instead of getchar - local char = getchar(n) - -- local font = font_of_family(getfield(n,"fam")) -- font_of_family - local font = getfont(n) + -- local char, font = isglyph(n) -- no, we have a mathchar + local char, font = getchar(n), getfont(n) local data = fontcharacters[font][char] - return data.unicode or char + return data.unicode or char -- can be a table but unlikely for math characters end ------------------- @@ -167,7 +176,7 @@ end local content = { } local found = false -content[math_char_code] = function() found = true end +content[mathchar_code] = function() found = true end local function hascontent(head) found = false @@ -177,18 +186,25 @@ end -------------------- -local function showtag(n,id) - local attr = getattr(n,a_tagged) - report_tags("%s = %s",nodecodes[id or getid(n)],attr and taglist[attr].tagname or "?") -end +-- todo: use properties + +-- local function showtag(n,id,old) +-- local attr = getattr(n,a_tagged) +-- local curr = tags.current() +-- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)", +-- old and "before" or "after ", +-- nodecodes[id], +-- getattrlist(n), +-- attr or "?",attr and taglist[attr].tagname or "?", +-- curr or "?",curr and taglist[curr].tagname or "?" +-- ) +-- end process = function(start) -- we cannot use the processor as we have no finalizers (yet) local mtexttag = nil while start do local id = getid(start) - --- showtag(start,id) - + -- showtag(start,id,true) if id == glyph_code or id == disc_code then if not mtexttag then mtexttag = start_tagged("mtext") @@ -201,11 +217,11 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() mtexttag = nil end - if id == math_char_code then + if id == mathchar_code then local char = getchar(start) local code = getmathcodes(char) local tag - if code == ordinary_code or code == variable_code then + if code == ordinary_mathcode or code == variable_mathcode then local ch = chardata[char] local mc = ch and ch.mathclass if mc == "number" then @@ -225,8 +241,9 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory end stop_tagged() + -- showtag(start,id,false) break -- okay? - elseif id == math_textchar_code then -- or id == glyph_code + elseif id == mathtextchar_code then -- or id == glyph_code -- check for code local a = getattr(start,a_mathcategory) if a then @@ -235,116 +252,127 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged("ms")) -- mtext end stop_tagged() + -- showtag(start,id,false) break - elseif id == math_delim_code then + elseif id == delim_code then -- check for code setattr(start,a_tagged,start_tagged("mo")) stop_tagged() + -- showtag(start,id,false) break - elseif id == math_style_code then + elseif id == style_code then -- has a next - elseif id == math_noad_code then + elseif id == noad_code then + -- setattr(start,a_tagged,tags.current()) processsubsup(start) - elseif id == math_box_code or id == hlist_code or id == vlist_code then - -- keep an eye on math_box_code and see what ends up in there + elseif id == dubbox_code or id == hlist_code or id == vlist_code then + -- keep an eye on subbox_code and see what ends up in there local attr = getattr(start,a_tagged) -if not attr then - -- just skip -else - local specification = taglist[attr] - if specification then - local tag = specification.tagname - if tag == "formulacaption" then - -- skip - elseif tag == "mstacker" then - local list = getlist(start) - if list then - process(list) - end - else - if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then - tag = "mtext" - end - local text = start_tagged(tag) - setattr(start,a_tagged,text) - local list = getlist(start) - if not list then - -- empty list - elseif not attr then - -- box comes from strange place - set_attributes(list,a_tagged,text) -- only the first node ? + if not attr then + -- just skip + else + local specification = taglist[attr] + if specification then + local tag = specification.tagname + if tag == "formulacaption" then + -- skip + elseif tag == "mstacker" then + local list = getlist(start) + if list then + process(list) + end else - -- Beware, the first node in list is the actual list so we definitely - -- need to nest. This approach is a hack, maybe I'll make a proper - -- nesting feature to deal with this at another level. Here we just - -- fake structure by enforcing the inner one. - -- - -- todo: have a local list with local tags that then get appended - -- - local tagdata = specification.taglist - local common = #tagdata + 1 - local function runner(list,depth) -- quite inefficient - local cache = { } -- we can have nested unboxed mess so best local to runner - local keep = nil - -- local keep = { } -- win case we might need to move keep outside - for n in traverse_nodes(list) do - local id = getid(n) - local mth = id == math_code and getsubtype(n) - if mth == 0 then - -- insert(keep,text) - keep = text - text = start_tagged("mrow") - common = common + 1 - end - local aa = getattr(n,a_tagged) - if aa then - local ac = cache[aa] - if not ac then - local tagdata = taglist[aa].taglist - local extra = #tagdata - if common <= extra then - for i=common,extra do - ac = restart_tagged(tagdata[i]) -- can be made faster - end - for i=common,extra do - stop_tagged() -- can be made faster + if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then + tag = "mtext" + end + local text = start_tagged(tag) + setattr(start,a_tagged,text) + local list = getlist(start) + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) -- only the first node ? + else + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + -- + -- todo: have a local list with local tags that then get appended + -- + local tagdata = specification.taglist + local common = #tagdata + 1 + local function runner(list,depth) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + local keep = nil + -- local keep = { } -- win case we might need to move keep outside + for n, id, subtype in nextnode, list do + local mth = id == math_code and subtype + if mth == 0 then -- hm left_code + -- insert(keep,text) + keep = text + text = start_tagged("mrow") + common = common + 1 + end + local aa = getattr(n,a_tagged) + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa].taglist + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster + end + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text end - else - ac = text + cache[aa] = ac end - cache[aa] = ac + setattr(n,a_tagged,ac) + else + setattr(n,a_tagged,text) + end + if id == hlist_code or id == vlist_code then + runner(getlist(n),depth+1) + elseif id == glyph_code then + -- this should not be needed + local components = getcomponents(n) -- unlikely set + if components then + runner(getcomponent,depth+1) + end + elseif id == disc_code then + -- this should not be needed + local pre, post, replace = getdisc(n) + if pre then + runner(pre,depth+1) + end + if post then + runner(post,depth+1) + end + if replace then + runner(replace,depth+1) + end + end + if mth == 1 then + stop_tagged() + -- text = remove(keep) + text = keep + common = common - 1 end - setattr(n,a_tagged,ac) - else - setattr(n,a_tagged,text) - end - - if id == hlist_code or id == vlist_code then - runner(getlist(n),depth+1) - elseif id == glyph_code then - -- this should not be needed (todo: use tounicode info) - runner(getcomponents(n),depth+1) - elseif id == disc_code then - local pre, post, replace = getdisc(n) - runner(pre,depth+1) -- idem - runner(post,depth+1) -- idem - runner(replace,depth+1) -- idem - end - if mth == 1 then - stop_tagged() - -- text = remove(keep) - text = keep - common = common - 1 end end + runner(list,0) end - runner(list,0) + stop_tagged() end - stop_tagged() end end -end - elseif id == math_sub_code then -- normally a hbox + elseif id == submlistcode then -- normally a hbox local list = getlist(start) if list then local attr = getattr(start,a_tagged) @@ -370,7 +398,7 @@ end end elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then -- looks like it gets processed twice --- do we still end up here ? + -- do we still end up here ? setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute process(list) stop_tagged() @@ -385,7 +413,7 @@ end stop_tagged() end end - elseif id == math_fraction_code then + elseif id == fraction_code then local num = getfield(start,"num") local denom = getfield(start,"denom") local left = getfield(start,"left") @@ -404,7 +432,7 @@ end process(right) stop_tagged() end - elseif id == math_choice_code then + elseif id == choice_code then local display = getfield(start,"display") local text = getfield(start,"text") local script = getfield(start,"script") @@ -421,7 +449,7 @@ end if scriptscript then process(scriptscript) end - elseif id == math_fence_code then + elseif id == fence_code then local delim = getfield(start,"delim") local subtype = getfield(start,"subtype") if subtype == 1 then @@ -478,7 +506,7 @@ end else -- can't happen end - elseif id == math_radical_code then + elseif id == radical_code then local left = getfield(start,"left") local degree = getfield(start,"degree") if left then @@ -496,7 +524,7 @@ end processsubsup(start) stop_tagged() end - elseif id == math_accent_code then + elseif id == accent_code then local accent = getfield(start,"accent") local bot_accent = getfield(start,"bot_accent") local subtype = getsubtype(start) @@ -506,8 +534,8 @@ end accent = true, top = getunicode(accent), bottom = getunicode(bot_accent), - topfixed = subtype == math_fixed_top or subtype == math_fixed_both, - bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both, + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, })) processsubsup(start) process(bot_accent) @@ -517,7 +545,7 @@ end setattr(start,a_tagged,start_tagged("munder", { accent = true, bottom = getunicode(bot_accent), - bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both, + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, })) processsubsup(start) process(bot_accent) @@ -527,7 +555,7 @@ end setattr(start,a_tagged,start_tagged("mover", { accent = true, top = getunicode(accent), - topfixed = subtype == math_fixed_top or subtype == math_fixed_both, + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, })) processsubsup(start) process(accent) @@ -544,6 +572,7 @@ end stop_tagged() end end +-- showtag(start,id,false) start = getnext(start) end if mtexttag then @@ -552,12 +581,10 @@ end end function noads.handlers.tags(head,style,penalties) - head = tonut(head) - local v_mode = getattr(head,a_mathmode) - local v_math = start_tagged("math", { mode = v_mode == 1 and "display" or "inline" }) + start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" }) +-- start_tagged("mrow") setattr(head,a_tagged,start_tagged("mrow")) process(head) stop_tagged() stop_tagged() - return true end diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua b/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua index 4767ffa90f6..ed6f69f41d9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-vfu.lua @@ -46,9 +46,18 @@ fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vecto local vfmath = allocate() fonts.handlers.vf.math = vfmath +local helpers = fonts.helpers +local vfcommands = helpers.commands +local rightcommand = vfcommands.right +local leftcommand = vfcommands.left +local downcommand = vfcommands.down +local upcommand = vfcommands.up +local push = vfcommands.push +local pop = vfcommands.pop + local shared = { } --- local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 } +-- local back = { "slot", 1, 0x2215 } -- -- local function negate(main,characters,id,size,unicode,basecode) -- if not characters[unicode] then @@ -64,8 +73,8 @@ local shared = { } -- commands = { -- { "slot", 1, basecode }, -- push, --- { "down", ht/5}, --- { "right", - wd/2}, +-- downcommand[ht/5], +-- leftcommand[wd/2], -- back, -- push, -- } @@ -139,107 +148,96 @@ local function parent(main,characters,id,size,unicode,first,rule,last) end end -local push, pop, step = { "push" }, { "pop" }, 0.2 -- 0.1 is nicer but gives larger files +local step = 0.2 -- 0.1 is nicer but gives larger files local function make(main,characters,id,size,n,m) local old = 0xFF000 + n - local c = characters[old] + local c = characters[old] if c then - local upslot, dnslot, uprule, dnrule = 0xFF100 + n, 0xFF200 + n, 0xFF300 + m, 0xFF400 + m - local xu = main.parameters.x_height + 0.3*size - local xd = 0.3*size - local w, h, d = c.width, c.height, c.depth + local upslot = 0xFF100 + n + local dnslot = 0xFF200 + n + local uprule = 0xFF300 + m + local dnrule = 0xFF400 + m + local xu = main.parameters.x_height + 0.3*size + local xd = 0.3*size + local w = c.width or 0 + local h = c.height or 0 + local d = c.depth or 0 local thickness = h - d local rulewidth = step*size -- we could use an overlap - local slot = { "slot", id, old } - local rule = { "rule", thickness, rulewidth } - local up = { "down", -xu } - local dn = { "down", xd } - local ht, dp = xu + 3*thickness, 0 + local slot = { "slot", id, old } + local rule = { "rule", thickness, rulewidth } + local up = upcommand[xu] + local dn = downcommand[xd] + local ht = xu + 3*thickness + local dp = 0 if not characters[uprule] then - characters[uprule] = { width = rulewidth, height = ht, depth = dp, commands = { push, up, rule, pop } } + characters[uprule] = { + width = rulewidth, + height = ht, + depth = dp, + commands = { push, up, rule, pop }, + } end - characters[upslot] = { width = w, height = ht, depth = dp, commands = { push, up, slot, pop } } - local ht, dp = 0, xd + 3*thickness + characters[upslot] = { + width = w, + height = ht, + depth = dp, + commands = { push, up, slot, pop }, + } + local ht = 0 + local dp = xd + 3*thickness if not characters[dnrule] then - characters[dnrule] = { width = rulewidth, height = ht, depth = dp, commands = { push, dn, rule, pop } } + characters[dnrule] = { + width = rulewidth, + height = ht, + depth = dp, + commands = { push, dn, rule, pop } + } end - characters[dnslot] = { width = w, height = ht, depth = dp, commands = { push, dn, slot, pop } } + characters[dnslot] = { + width = w, + height = ht, + depth = dp, + commands = { push, dn, slot, pop }, + } end end local function clipped(main,characters,id,size,unicode,original) -- push/pop needed? local minus = characters[original] if minus then - local mu = size/18 - local step = 3*mu + local mu = size/18 + local step = 3*mu local width = minus.width if width > step then width = width - step - step = step / 2 + step = step / 2 else width = width / 2 - step = width + step = width end characters[unicode] = { width = width, height = minus.height, depth = minus.depth, - commands = { push, { "right", -step }, { "slot", id, original }, pop } + commands = { + push, + leftcommand[step], + { "slot", id, original }, + pop, + } } end end --- fails: pdf:page: pdf:direct: ... some funny displacement - --- this does not yet work ... { "scale", 2, 0, 0, 3 } .. commented code --- --- this does not work ... no interpretation going on here --- --- local nodeinjections = backends.nodeinjections --- { "node", nodeinjections.save() }, --- { "node", nodeinjections.transform(.7,0,0,.7) }, --- commands[#commands+1] = { "node", nodeinjections.restore() } - --- local done = { } --- --- local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess --- local raised = characters[private] --- if raised then --- if not done[unicode] then --- report_virtual("temporary too large %U due to issues in luatex backend",unicode) --- done[unicode] = true --- end --- local up = 0.85 * main.parameters.x_height --- local slot = { "slot", id, private } --- local commands = { --- push, --- { "down", - up }, --- -- { "scale", .7, 0, 0, .7 }, --- slot, --- } --- for i=2,n do --- commands[#commands+1] = slot --- end --- commands[#commands+1] = pop --- characters[unicode] = { --- width = .7 * n * raised.width, --- height = .7 * (raised.height + up), --- depth = .7 * (raised.depth - up), --- commands = commands, --- } --- end --- end - local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess local raised = fonts.hashes.characters[main.fonts[id_of_smaller].id][private] -- characters[private] if raised then - local up = 0.85 * main.parameters.x_height + local up = 0.85 * main.parameters.x_height local slot = { "slot", id_of_smaller, private } local commands = { - push, - { "down", - up }, - slot, + push, upcommand[up], slot, } for i=2,n do commands[#commands+1] = slot @@ -258,65 +256,85 @@ end local function dots(main,characters,id,size,unicode) local c = characters[0x002E] if c then - local w, h, d = c.width, c.height, c.depth - local mu = size/18 - local right3mu = { "right", 3*mu } - local right1mu = { "right", 1*mu } - local up1size = { "down", -.1*size } - local up4size = { "down", -.4*size } - local up7size = { "down", -.7*size } - local right2muw = { "right", 2*mu + w } - local slot = { "slot", id, 0x002E } + local w = c.width + local h = c.height + local d = c.depth + local mu = size/18 + local right3mu = rightcommand[3*mu] + local right1mu = rightcommand[1*mu] + local up1size = upcommand[.1*size] + local up4size = upcommand[.4*size] + local up7size = upcommand[.7*size] + local right2muw = rightcommand[2*mu + w] + local slot = { "slot", id, 0x002E } if unicode == 0x22EF then local c = characters[0x022C5] if c then - local w, h, d = c.width, c.height, c.depth - local slot = { "slot", id, 0x022C5 } + local width = c.width + local height = c.height + local depth = c.depth + local slot = { "slot", id, 0x022C5 } characters[unicode] = { - width = 3*w + 2*3*mu, height = h, depth = d, - commands = { push, slot, right3mu, slot, right3mu, slot, pop } + width = 3*width + 2*3*mu, + height = height, + depth = depth, + commands = { + push, slot, right3mu, slot, right3mu, slot, pop, + } } end elseif unicode == 0x22EE then -- weird height ! characters[unicode] = { - width = w, height = h+(1.4)*size, depth = 0, - commands = { push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop } + width = w, + height = h+(1.4)*size, + depth = 0, + commands = { + push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop, + } } elseif unicode == 0x22F1 then characters[unicode] = { - width = 3*w + 6*size/18, height = 1.5*size, depth = 0, + width = 3*w + 6*size/18, + height = 1.5*size, + depth = 0, commands = { push, - right1mu, - push, up7size, slot, pop, - right2muw, - push, up4size, slot, pop, - right2muw, - push, up1size, slot, pop, - right1mu, + right1mu, + push, up7size, slot, pop, + right2muw, + push, up4size, slot, pop, + right2muw, + push, up1size, slot, pop, + right1mu, pop } } elseif unicode == 0x22F0 then characters[unicode] = { - width = 3*w + 6*size/18, height = 1.5*size, depth = 0, + width = 3*w + 6*size/18, + height = 1.5*size, + depth = 0, commands = { push, - right1mu, - push, up1size, slot, pop, - right2muw, - push, up4size, slot, pop, - right2muw, - push, up7size, slot, pop, - right1mu, + right1mu, + push, up1size, slot, pop, + right2muw, + push, up4size, slot, pop, + right2muw, + push, up7size, slot, pop, + right1mu, pop } } else characters[unicode] = { - width = 3*w + 2*3*mu, height = h, depth = d, - commands = { push, slot, right3mu, slot, right3mu, slot, pop } + width = 3*w + 2*3*mu, + height = h, + depth = d, + commands = { + push, slot, right3mu, slot, right3mu, slot, pop, + } } end end @@ -331,21 +349,23 @@ local function vertbar(main,characters,id,size,parent,scale,unicode) width = cp.width, height = cp.height + sc, depth = cp.depth + sc, + next = cp.next, -- can be extensible commands = { - push, { "down", -sc }, pc, pop, - push, { "down", sc }, pc, pop, + push, upcommand [sc], pc, pop, + push, downcommand[sc], pc, pop, pc, }, - next = cp.next -- can be extensible } cp.next = unicode end end local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what) - local c1, c2 = characters[u1], characters[u2] + local c1 = characters[u1] + local c2 = characters[u2] if c1 and c2 then - local w1, w2 = c1.width, c2.width + local w1 = c1.width + local w2 = c2.width local mu = size/18 characters[unicode] = { width = w1 + w2 - d12 * mu, @@ -353,7 +373,7 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what) depth = max(c1.depth or 0, c2.depth or 0), commands = { { "slot", id, u1 }, - { "right", -d12*mu } , + leftcommand[d12*mu], { "slot", id, u2 }, }, } @@ -361,19 +381,23 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what) end local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3) - local c1, c2, c3 = characters[u1], characters[u2], characters[u3] + local c1 = characters[u1] + local c2 = characters[u2] + local c3 = characters[u3] if c1 and c2 and c3 then - local w1, w2, w3 = c1.width, c2.width, c3.width + local w1 = c1.width + local w2 = c2.width + local w3 = c3.width local mu = size/18 characters[unicode] = { width = w1 + w2 + w3 - d12*mu - d23*mu, height = max(c1.height or 0, c2.height or 0, c3.height or 0), - depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0), + depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0), commands = { { "slot", id, u1 }, - { "right", - d12*mu } , + leftcommand[d12*mu], { "slot", id, u2 }, - { "right", - d23*mu }, + leftcommand[d23*mu], { "slot", id, u3 }, } } @@ -381,24 +405,32 @@ local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3) end local function stack(main,characters,id,size,unicode,u1,d12,u2) - local c1, c2 = characters[u1], characters[u2] - if c1 and c2 then - local w1, w2 = c1.width, c2.width - local h1, h2 = c1.height, c2.height - local d1, d2 = c1.depth, c2.depth - local mu = size/18 - characters[unicode] = { - width = w1, - height = h1 + h2 + d12, - depth = d1, - commands = { - { "slot", id, u1 }, - { "right", - w1/2 - w2/2 } , - { "down", -h1 + d2 -d12*mu } , - { "slot", id, u2 }, - } - } + local c1 = characters[u1] + if not c1 then + return + end + local c2 = characters[u2] + if not c2 then + return end + local w1 = c1.width or 0 + local h1 = c1.height or 0 + local d1 = c1.depth or 0 + local w2 = c2.width or 0 + local h2 = c2.height or 0 + local d2 = c2.depth or 0 + local mu = size/18 + characters[unicode] = { + width = w1, + height = h1 + h2 + d12, + depth = d1, + commands = { + { "slot", id, u1 }, + leftcommand[w1/2 + w2/2], + downcommand[-h1 + d2 -d12*mu], + { "slot", id, u2 }, + } + } end local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- math-fbk.lua @@ -406,16 +438,14 @@ local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- if c then local width = c.width local italic = fraction*width -- c.italic or 0 -- larger ones have funny italics - local tc = { "slot", id, u } - local tr = { "right", -italic } -- see hack elsewhere + local tc = { "slot", id, u } + local tr = leftcommand[italic] -- see hack elsewhere local commands = { } for i=1,n-1 do commands[#commands+1] = tc commands[#commands+1] = tr end commands[#commands+1] = tc --- inspect(c) --- inspect(commands) local next = c.next if next then repeated(main,characters,id,size,private,next,n,private+1,fraction) @@ -589,7 +619,8 @@ setmetatableindex(reverse, function(t,name) if trace_virtual then report_virtual("initializing math vector %a",name) end - local m, r = mathencodings[name], { } + local m = mathencodings[name] + local r = { } for u, i in next, m do r[i] = u end @@ -597,6 +628,10 @@ setmetatableindex(reverse, function(t,name) return r end) +-- use char and font hash +-- +-- commands = { { "font", slot }, { "char", unicode } }, + local function copy_glyph(main,target,original,unicode,slot) local addprivate = fonts.helpers.addprivate local olddata = original[unicode] @@ -623,7 +658,6 @@ local function copy_glyph(main,target,original,unicode,slot) } local newnextglyph = addprivate(main,formatters["M-N-%H"](nextglyph),newnextdata) newdata.next = newnextglyph --- report_virtual("copied next: %X",newdata.next) local nextnextglyph = oldnextdata.next if nextnextglyph == nextglyph then break @@ -649,7 +683,6 @@ local function copy_glyph(main,target,original,unicode,slot) commands = { { "slot", slot, oldglyph } }, } hvi.glyph = addprivate(main,formatters["M-H-%H"](oldglyph),newdata) --- report_virtual("copied h variant: %X at index %i",hvi.glyph,i) end end local vv = olddata.vert_variants @@ -668,7 +701,6 @@ local function copy_glyph(main,target,original,unicode,slot) commands = { { "slot", slot, oldglyph } }, } vvi.glyph = addprivate(main,formatters["M-V-%H"](oldglyph),newdata) --- report_virtual("copied v variant: %X at index %i",vvi.glyph,i) end end return newdata @@ -678,13 +710,17 @@ end vfmath.copy_glyph = copy_glyph function vfmath.define(specification,set,goodies) - local name = specification.name -- symbolic name - local size = specification.size -- given size - local loaded, fontlist, names, main = { }, { }, { }, nil - local start = (trace_virtual or trace_timings) and os.clock() - local okset, n = { }, 0 + local name = specification.name -- symbolic name + local size = specification.size -- given size + local loaded = { } + local fontlist = { } + local names = { } + local main = nil + local start = (trace_virtual or trace_timings) and os.clock() + local okset = { } + local n = 0 for s=1,#set do - local ss = set[s] + local ss = set[s] local ssname = ss.name if add_optional and ss.optional then if trace_virtual then @@ -828,11 +864,11 @@ function vfmath.define(specification,set,goodies) elseif add_optional and ss.optional then -- skip, redundant else - local newparameters = fs.parameters + local newparameters = fs.parameters local newmathparameters = fs.mathparameters if newmathparameters then if not parameters_done or ss.parameters then - mathparameters = newmathparameters + mathparameters = newmathparameters parameters_done = true end elseif not newparameters then @@ -867,7 +903,7 @@ function vfmath.define(specification,set,goodies) -- report_virtual("loading and virtualizing font %a at size %p, setting sy parameters",name,size) end if ss.overlay then - local fc = fs.characters + local fc = fs.characters local first = ss.first if first then local last = ss.last or first @@ -882,12 +918,14 @@ function vfmath.define(specification,set,goodies) else local vectorname = ss.vector if vectorname then - local offset = 0xFF000 - local vector = mathencodings[vectorname] - local rotcev = reverse[vectorname] + local offset = 0xFF000 + local vector = mathencodings[vectorname] + local rotcev = reverse[vectorname] local isextension = ss.extension if vector and rotcev then - local fc, fd, si = fs.characters, fs.descriptions, shared[s] + local fc = fs.characters + local fd = fs.descriptions + local si = shared[s] local skewchar = ss.skewchar for unicode, index in next, vector do local fci = fc[index] @@ -913,8 +951,8 @@ function vfmath.define(specification,set,goodies) ref = { { 'slot', s, index } } si[index] = ref end - local kerns = fci.kerns - local width = fci.width + local kerns = fci.kerns + local width = fci.width local italic = fci.italic if italic and italic > 0 then -- int_a^b diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-blb.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-blb.lua new file mode 100644 index 00000000000..e1c0de74f37 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-blb.lua @@ -0,0 +1,322 @@ +if not modules then modules = { } end modules ['meta-blb'] = { + version = 1.001, + comment = "companion to mlib-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +-- This could be integrated in other modules but for me it also serves +-- as an example of usign the plugin mechanism. + +local tonumber = tonumber + +local setmetatableindex = table.setmetatableindex +local insert, remove = table.insert, table.remove +local formatters = string.formatters + +local topoints = number.topoints +local mpprint = mp.print +local mpinteger = mp.integer +local mppoints = mp.points +local mptriplet = mp.triplet +local mptripletpoints = mp.tripletpoints + +local nuts = nodes.nuts +local hpack = nuts.hpack +local setbox = nuts.setbox +local getwhd = nuts.getwhd +local getwidth = nuts.getwidth +local toutf = nuts.toutf + +local trace = false +local report = logs.reporter("metapost","blobs") + +trackers.register("metapost.blobs", function(v) trace = v end) + +local allblobs = { } + +local function newcategory(t,k) + if trace then + report("new category %a",k) + end + local v = { + name = k, + text = "", + blobs = { }, + } + t[k] = v + return v +end + +local texblobs = setmetatableindex(newcategory) + +local function blob_raw_reset(category) + -- we need to keep the allblobs + if category then + if trace then + report("reset category %a",category) + end + texblobs[category] = nil + else + if trace then + report("reset all") + end + texblobs = setmetatableindex(newcategory) + end +end + +local function blob_raw_dimensions(i) + local blob = allblobs[i] + if blob then + return getwhd(blob) + else + return 0, 0, 0 + end +end + +local function blob_raw_content(i) + return allblobs[i] +end + +local function blob_raw_toutf(i) + return toutf(allblobs[i]) +end + +local function blob_raw_wipe(i) + allblobs[i] = false +end + +mp.mf_blob_raw_dimensions = blob_raw_dimensions +mp.mf_blob_raw_content = blob_raw_content +mp.mf_blob_raw_reset = blob_raw_reset +mp.mf_blob_raw_wipe = blob_raw_wipe +mp.mf_blob_raw_toutf = blob_raw_toutf + +function mp.mf_blob_new(category,text) + if trace then + report("category %a, text %a",category,text) + end + texblobs[category].text = text +end + +function mp.mf_blob_add(category,blob) + local tb = texblobs[category].blobs + local tn = #allblobs + 1 + blob = hpack(blob) + allblobs[tn] = blob + tb[#tb+1] = tn + if trace then + report("category %a, blob %a set, content %a",category,tn,blob_raw_toutf(tn)) + end +end + +function mp.mf_blob_width(category,i) + local index = texblobs[category].blobs[i] + local blob = allblobs[index] + if blob then + mppoints(getwidth(blob) or 0) + else + mpinteger(0) + end +end + +function mp.mf_blob_size(category,i) + mpprint(#texblobs[category].blobs or 0) +end + +function mp.mf_blob_index(category,i) + mpprint(texblobs[category].blobs[i] or 0) +end + +function mp.mf_blob_dimensions(category,i) + local index = texblobs[category].blobs[i] + local blob = allblobs[index] + if blob then + mptripletpoints(getwhd(blob)) + else + mptriplet(0,0,0) + end +end + +local sxsy = metapost.sxsy +local cm = metapost.cm + +local f_f = formatters["%.6F"] + +directives.register("pdf.stripzeros",function() + f_f = formatters["%.6N"] +end) + +local function injectblob(object,blob) + local sx, rx, ry, sy, tx, ty = cm(object) + local wd, ht, dp = blob_raw_dimensions(blob) + if wd then + object.path = false + object.color = false + object.grouped = true + object.istext = true + return function() + if trace then + report("injecting blob %a, width %p, heigth %p, depth %p, text %a",blob,wd,ht,dp,blob_raw_toutf(blob)) + end + context.MPLIBgetblobscaledcm(blob, + f_f(sx), f_f(rx), f_f(ry), + f_f(sy), f_f(tx), f_f(ty), + sxsy(wd,ht,dp)) + end + end +end + +-- mp.mf_blob_inject = injectblob + +local function getblob(box,blob) + setbox(box,blob_raw_content(blob)) + blob_raw_wipe(blob) +end + +interfaces.implement { + name = "mpgetblob", + actions = getblob, + arguments = { "integer", "integer" }, +} + +-- the plug: + + +local function reset() + blob_raw_reset() +end + +local function process(object,prescript,before,after) +-- if prescript.tb_stage == "inject" then + local tb_blob = tonumber(prescript.tb_blob) + if tb_blob then + before[#before+1] = injectblob(object,tb_blob) + end +-- end +end + +metapost.installplugin { + name = "texblob", + reset = reset, + process = process, +} + +-- Here follows an example of usage of the above: a more modern +-- version of followokens (in meta-imp-txt.mkiv). + +local nodecodes = nodes.nodecodes +local kerncodes = nodes.kerncodes + +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern + +local fontkern_code = kerncodes.fontkern +local italickern_code = kerncodes.italickern + +local a_fontkern = attributes.private("fontkern") + +local nuts = nodes.nuts +local takebox = nuts.takebox +local getlist = nuts.getlist +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local setlink = nuts.setlink +local setlist = nuts.setlist +local getnext = nuts.getnext +local flatten_list = nuts.flatten_discretionaries +local remove_node = nuts.remove +local flush_node = nuts.flush + +local addblob = mp.mf_blob_add +local newblob = mp.mf_blob_new + +local visible_codes = { + [nodecodes.glyph] = true, + [nodecodes.glue] = true, + [nodecodes.hlist] = true, + [nodecodes.vlist] = true, + [nodecodes.rule] = true, +} + +local function initialize(category,box) + local wrap = takebox(box) + if wrap then + local head = getlist(wrap) + local tail = nil + local temp = nil + if head then + local n = { } + local s = 0 + head = flatten_list(head) + local current = head + while current do + local id = getid(current) + if visible_codes[id] then + head, current, tail = remove_node(head,current) + s = s + 1 + n[s] = tail + elseif id == kern_code then + local subtype = getsubtype(current) + if subtype == fontkern_code or subtype == italickern_code then -- or current[a_fontkern] + head, current, temp = remove_node(head,current) + setlink(tail,temp) + else + head, current, temp = remove_node(head,current) + s = s + 1 + n[s] = temp + end + elseif id == glue_code then + head, current, temp = remove_node(head,current) + s = s + 1 + n[s] = temp + else + current = getnext(current) + end + end + for i=1,s do + n[i] = addblob(category,n[i]) + end + setlist(wrap,head) + end + flush_node(wrap) + end +end + +interfaces.implement { + name = "MPLIBconvertfollowtext", + arguments = { "integer","integer" }, + actions = initialize, +} + +local mp_category = 0 +local mp_str = "" + +function mp.mf_inject_blob(category,str) + newblob(category,str) -- only for tracing + mp_category = category + mp_str = str + tex.runtoks("mpblobtext") +end + +interfaces.implement { + name = "mpblobtext", + actions = function() + context.MPLIBfollowtext(mp_category,mp_str) + end +} + +local process = function(object,prescript,before,after) + if prescript.ft_category then + object.path = false + object.color = false + object.grouped = true + object.istext = true + end +end + +metapost.installplugin { + name = "followtext", + process = process, +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-blb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-blb.mkiv new file mode 100644 index 00000000000..4a5381dfc43 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-blb.mkiv @@ -0,0 +1,56 @@ +%D \module +%D [ file=meta-blb, +%D version=2018.04.12, +%D title=\METAPOST\ Graphics, +%D subtitle=Blobs, +%D author=Hans Hagen, +%D date=\ currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{MetaPost Graphics / Blobs} + +\registerctxluafile{meta-blb}{} + +\unprotect + +\unexpanded\def\MPLIBgetblobscaledcm#1#2#3#4#5#6#7#8#9% + {\clf_mpgetblob\MPtextbox#1\relax + \setbox\MPbox\hpack\bgroup + \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}% + \vpack to \zeropoint\bgroup + \vss + \hpack to \zeropoint \bgroup + % \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}% + \fastsxsy{#8}{#9}{\box\MPtextbox}% + \hss + \egroup + \egroup + \egroup + \smashbox\MPbox + \box\MPbox} + +%D An example of usage: + +\definefontfeature[followtext][liga=no] + +\unexpanded\def\MPLIBfollowtext#1#2% + {\begingroup + \scratchcounter#1\relax + \setbox\scratchbox\hbox{\addff{followtext}#2}% + \clf_MPLIBconvertfollowtext\scratchcounter\scratchbox + \endgroup} + +% \def\reversedtext#1% +% {\cldcontext{table.concat(table.reverse(utf.totable(\!!bs#1\!!es)))}} + +%D New: + +\newtoks\mpblobtext + +\mpblobtext{\global\setbox\mptextbox\vbox{\clf_mpblobtext}} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua index d061c926a57..69212d08c79 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-fnt.lua @@ -108,19 +108,17 @@ local function process(mpxformat,name,instances,scalefactor) for i=1,instances do characters = { } descriptions = { } - metapost.process( - mpxformat, - { + metapost.process { + mpx = mpxformat, + flusher = flusher, + askedfig = "all", + -- incontext = false, + data = { formatters["randomseed := %s ;"](i*10), formatters["charscale := %s ;"](scalefactor), data, }, - false, - flusher, - false, - false, - "all" - ) + } lists[i] = { characters = characters, descriptions = descriptions, @@ -191,9 +189,9 @@ statistics.register("metapost font generation", function() if total > 0 then local time = statistics.elapsedtime(flusher) if total > 0 then - return format("%i glyphs, %.3f seconds runtime, %.1f glyphs/second", total, time, total/time) + return format("%i glyphs, %s seconds runtime, %.1f glyphs/second", total, time, total/tonumber(time)) else - return format("%i glyphs, %.3f seconds runtime", total, time) + return format("%i glyphs, %s seconds runtime", total, time) end end end) @@ -202,9 +200,9 @@ statistics.register("metapost font loading",function() if variants > 0 then local time = statistics.elapsedtime(metapost.fonts) if variants > 0 then - return format("%.3f seconds, %i instances, %.3f instances/second", time, variants, variants/time) + return format("%s seconds, %i instances, %.3f instances/second", time, variants, variants/tonumber(time)) else - return format("%.3f seconds, %i instances", time, variants) + return format("%s seconds, %i instances", time, variants) end end end) diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv index e6ccc234c6d..481afe82a54 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-dum.mkiv @@ -59,7 +59,7 @@ % clip currentpicture to p ; % \stopuseMPgraphic -\startuseMPgraphic{figure:placeholder}{width,height,reduction,color} +\startuseMPgraphic{minifun::figure:placeholder}{width,height,reduction,color} begingroup ; save w, h, d, r, p, c, b ; numeric w, h, d, r ; path p ; @@ -88,7 +88,7 @@ \defineoverlay [figure:placeholder:graphic] [\useMPgraphic - {figure:placeholder}% + {minifun::figure:placeholder}% {width=\figurewidth,% height=\figureheight,% reduction=\externalfigureparameter\c!reduction,% diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mat.mkiv index 19a5ba38539..495864a9eeb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mat.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-mat.mkiv @@ -15,8 +15,16 @@ % % / for cambria -\startMPextensions +%D We need this for Alan, who nests math in \METAPOST: + +\unprotect + +\setupmathstackers + [\c!mp=minifun::math:stacker:\number\scratchunicode] +\protect + +\startMPextensions vardef math_stacker_bracket_shape(expr delta, rotate) = image ( draw @@ -129,55 +137,55 @@ enddef ; \stopMPextensions -\startuniqueMPgraphic{math:stacker:\number"FE3B4}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3B4}{axis,ex,em} math_stacker_draw_accent(math_stacker_bracket_shape(OverlayHeight,false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE3B5}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3B5}{axis,ex,em} math_stacker_draw_accent(math_stacker_bracket_shape(OverlayDepth,true)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE3DC}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DC}{axis,ex,em} math_stacker_draw_accent(math_stacker_parent_shape(OverlayHeight,false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE3DD}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DD}{axis,ex,em} math_stacker_draw_accent(math_stacker_parent_shape(OverlayDepth,true)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE3DE}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DE}{axis,ex,em} math_stacker_draw_accent(math_stacker_brace_shape(OverlayHeight,false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE3DF}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DF}{axis,ex,em} math_stacker_draw_accent(math_stacker_brace_shape(OverlayDepth,true)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE33E}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE33E}{axis,ex,em} math_stacker_draw_accent(math_stacker_bar_shape(false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"FE33F}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"FE33F}{axis,ex,em} math_stacker_draw_accent(math_stacker_bar_shape(true)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"2190}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"2190}{axis,ex,em} math_stacker_draw_arrow(math_stacker_arrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"2192}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"2192}{axis,ex,em} math_stacker_draw_arrow(math_stacker_arrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},true)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"2194}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"2194}{axis,ex,em} math_stacker_draw_arrow(math_stacker_leftrightarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"27F7}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"27F7}{axis,ex,em} math_stacker_draw_arrow(math_stacker_leftrightarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ; \stopuniqueMPgraphic -\startuniqueMPgraphic{math:stacker:\number"21C4}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:stacker:\number"21C4}{axis,ex,em} math_stacker_draw_arrow(math_stacker_rightoverleftarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ; \stopuniqueMPgraphic @@ -193,7 +201,7 @@ enddef ; \stopMPextensions -\startuniqueMPgraphic{math:radical:default}{axis,ex,em} +\startuniqueMPgraphic{minifun::math:radical:default}{axis,ex,em} draw math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset) withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30 diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv index e9660b3a7e2..d4329cd6ffd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-imp-txt.mkiv @@ -202,7 +202,10 @@ \stopMPdefinitions \startluacode + local context = context + local nodecodes = nodes.nodecodes + local kerncodes = nodes.kerncodes local visible_code = { [nodecodes.glyph] = true, @@ -212,72 +215,66 @@ [nodecodes.rule] = true, } - local disc_code = nodecodes.disc - local kern_code = nodecodes.kern - - local c_userkern = nodes.kerncodes.userkern + local kern_code = nodecodes.kern + local c_userkern = kerncodes.userkern local a_fontkern = attributes.private("fontkern") + local copynode = nodes.copy + local freenode = nodes.free + + local topoints = number.topoints + local mpprint = mp.print + local n = nil local s = 0 function mp.follow_reset() - r = nil + for i=1,#n do + freenode(n[i]) + end + n = nil s = 0 end function mp.follow_initialize(b) - if not r then - local l = tex.takebox(b).list - n = { } - s = 0 - while l do - local c = l - l = l.next - local id = c.id - if visible_code[id] then - s = s + 1 - n[s] = c - c.prev = nil - c.next = nil - elseif id == kern_code then - if c.subtype == c_userkern and not c[a_fontkern] then + if not n then + local head = tex.takebox(b).list + if head then + n = { } + s = 0 + head = node.flatten_discretionaries(head) + local current = head + while current do + local id = current.id + if visible_code[id] then s = s + 1 - n[s] = c - c.prev = nil - else - n[s].next = c - c.prev = n[s] - end - c.next = nil - elseif id == disc_code then - local r = c.replace - while r do + head, current, n[s] = nodes.remove(head,current) + elseif id == kern_code and current.subtype == c_userkern and not current[a_fontkern] then s = s + 1 - n[s] = r - r = r.next - r.prev = nil - r.next = nil + head, current, n[s] = nodes.remove(head,current) + else + current = current.next end end + nodes.flush_list(head) end end end function mp.follow_size() - mp.print(s) + mpprint(s) end function mp.follow_slot(i) - mp.print('textext("\\getfollowtoken{' .. i .. '}")') + mpprint('textext("\\getfollowtoken{' .. i .. '}")') end function mp.follow_text(s) - context(n[s]) + context(copynode(n[s])) end function mp.follow_width(i) - mp.print(number.topoints(n[i].width)) + mpprint(topoints(n[i].width)) end \stopluacode @@ -373,9 +370,8 @@ [medium] \startuniqueMPgraphic{EnglishRule}{height,width,color} - height = \MPvar{height} ; x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ; - y1 = y3 = 0 ; y2 = -y4 = height/2 ; + y1 = y3 = 0 ; y2 = -y4 = \MPvar{height}/2 ; fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ; \stopuniqueMPgraphic diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua index 6c4768671f1..f320efe2046 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.lua @@ -117,23 +117,23 @@ do local data = false - function mp.start_saving_data(n) + function mp.mf_start_saving_data(n) data = { } end - function mp.stop_saving_data() + function mp.mf_stop_saving_data() if data then -- nothing end end - function mp.finish_saving_data() + function mp.mf_finish_saving_data() if data then -- nothing end end - function mp.save_data(str) + function mp.mf_save_data(str) if data then data[#data+1] = str end diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv index 61e3523e667..89c7699deb5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-ini.mkiv @@ -97,7 +97,7 @@ \ifx\currentMPinstance\empty \let\currentMPinstance\defaultMPinstance \fi - \global\t_meta_definitions\expandafter{\the\t_meta_definitions#2}% + \gtoksapp\t_meta_definitions{#2}% \let\currentMPinstance\m_meta_saved_instance} \let\stopMPdefinitions\relax @@ -111,7 +111,7 @@ \let\stopMPextensions\relax \unexpanded\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled - {\global\t_meta_initializations\expandafter{\the\t_meta_initializations#1}} + {\gtoksapp\t_meta_initializations{#1}} \let\stopMPinitializations\relax @@ -131,7 +131,7 @@ \ifx\m_meta_option\!!plustoken \else \global\t_meta_inclusions\emptytoks \fi - \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}% + \gtoksapp\t_meta_inclusions{#2}% \let\currentMPinstance\m_meta_saved_instance} \let\stopMPinclusions\relax @@ -152,7 +152,7 @@ \ifx\m_meta_option\!!plustoken \else \global\t_meta_inclusions\emptytoks \fi - \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}% + \gtoksapp\t_meta_inclusions{#2}% \let\currentMPinstance\m_meta_saved_instance} \installcommandhandler \??mpinstance {MPinstance} \??mpinstance @@ -211,6 +211,7 @@ \def\currentMPformat {\currentMPinstance} \defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] +\defineMPinstance[minifun] [\s!format=minifun,\s!extensions=\v!yes,\s!initializations=\v!yes] \defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes] \defineMPinstance[lessfun] [\s!format=metafun] \defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double] @@ -275,11 +276,13 @@ \endgroup} \def\meta_process_graphic_start - {\setbox\b_meta_graphic\hpack\bgroup} + {\pushMPboundingbox + \setbox\b_meta_graphic\hpack\bgroup} \def\meta_process_graphic_stop {\egroup - \meta_place_graphic} + \meta_place_graphic + \popMPboundingbox} \unexpanded\def\meta_process_graphic_instance#1% {\edef\currentMPinstance{#1}% @@ -365,12 +368,12 @@ \let\MPdrawingdata\empty \unexpanded\def\resetMPdrawing - {\global\let\MPdrawingdata\empty + {\glet\MPdrawingdata\empty \global\MPdrawingdonefalse} \unexpanded\def\pushMPdrawing {\globalpushmacro\MPdrawingdata - \global\let\MPdrawingdata\empty} + \glet\MPdrawingdata\empty} \unexpanded\def\popMPdrawing {\globalpopmacro\MPdrawingdata} @@ -728,7 +731,7 @@ % \def\meta_start_use_graphic#1#2#3\stopuseMPgraphic % %{\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} % %{\setxvalue{\??mpgraphic#1}{\noexpand\meta_handle_use_graphic{#1}{\normalunexpanded{#2}}{\normalunexpanded{#3}}}} -% {\global\expandafter\gdef\csname\??mpgraphic#1\expandafter\endcsname\expandafter{\expandafter\meta_handle_use_graphic\expandafter{\normalexpanded{#1}}{#2}{#3}}} +% {\expandafter\gdef\csname\??mpgraphic#1\expandafter\endcsname\expandafter{\expandafter\meta_handle_use_graphic\expandafter{\normalexpanded{#1}}{#2}{#3}}} % % cleaner: @@ -785,11 +788,28 @@ \unexpanded\def\useMPgraphic {\dodoublegroupempty\meta_use_graphic} +% \def\meta_use_graphic#1#2% +% {\meta_begin_graphic_group{#1}% +% %\doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}% +% \doifsomething{#2}{\setupMPvariables[#1][#2]}% +% \csname\??mpgraphic#1\endcsname\empty +% \meta_end_graphic_group} + \def\meta_use_graphic#1#2% {\meta_begin_graphic_group{#1}% -% \doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}% - \doifsomething{#2}{\setupMPvariables[#1][#2]}% - \csname\??mpgraphic#1\endcsname\empty + \ifcsname\??mpgraphic#1\endcsname + \edef\usedMPgraphicname{#1}% + \else\ifcsname\??mpgraphic\currentMPgraphicname\endcsname + \let\usedMPgraphicname\currentMPgraphicname + \else + \let\usedMPgraphicname\empty + \fi\fi + \ifx\usedMPgraphicname\empty + % message + \else + \doifsomething{#2}{\setupMPvariables[\usedMPgraphicname][#2]}% + \csname\??mpgraphic\usedMPgraphicname\endcsname + \fi \meta_end_graphic_group} \let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed @@ -861,19 +881,6 @@ {\meta_prepare_instance_variable{#1}% \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}} -%D \macros -%D {MPdatafile} -%D -%D We redefine a macro from \type {supp-mps.tex}: - -% This will change ... - -\def\MPdataMPYfile{\jobname-mpgraph.mpy} - -\startMPextensions - def data_mpy_file = "\noexpand\MPdataMPYfile" enddef ; -\stopMPextensions - \unexpanded\def\getMPdata {\clf_getMPdata} \let\rawMPdata \clf_getMPdata diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-nod.lua new file mode 100644 index 00000000000..422b4ee14d2 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-nod.lua @@ -0,0 +1,81 @@ +if not modules then modules = { } end modules ['meta-nod'] = { + version = 1.001, + comment = "companion to meta-nod.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local tonumber = tonumber +local P, R, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.Cs, lpeg.match + +local references = { } +local trace = false +local report = logs.reporter("metapost","nodes") + +local context = context +local implement = interfaces.implement + +trackers.register("metapost.nodes", function(v) trace = v end) + +local word = R("AZ","az","__")^1 + +local pattern = Cs ( + ( + word / function(s) return references[s] or s end + + P("{") / "[" + + P("}") / "]" + + P(1) + )^1 +) + +implement { + name = "grph_nodes_initialize", + actions = function() + references = { } + end +} + +implement { + name = "grph_nodes_reset", + actions = function() + references = { } + end +} + +implement { + name = "grph_nodes_register", + arguments = { "string", "integer" }, + actions = function(s,r) + if not tonumber(s) then + if trace then + report("register %i as %a",t,s) + end + references[s] = r + end + end +} + +implement { + name = "grph_nodes_resolve", + arguments = "string", + actions = function(s) + local r = references[s] + if r then + if trace then + report("resolve %a to %i",s,r) + end + context(r) + return + end + local n = lpegmatch(pattern,s) + if s ~= n then + if trace then + report("resolve '%s' to %s",s,n) + end + context(n) + return + end + context(s) + end +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-nod.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-nod.mkiv index 5c7b3d503dd..9f966349c15 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-nod.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-nod.mkiv @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +\registerctxluafile{meta-nod}{} + \unprotect \defineMPinstance @@ -105,6 +107,11 @@ \let\stopnodes\relax +%D Hm, we started out simple but it now quickly becomes the usual mess of +%D \TEX, \METAPOST\ and \LUA. Hard to understand. + +\newcount\c_meta_nodes_n + \unexpanded\def\startnodes {\dosingleempty\meta_nodes_start} @@ -116,10 +123,12 @@ \edef\p_meta_option{\metanodesparameter\c!option}% \edef\p_meta_alternative{\metanodesparameter\c!alternative}% \the\t_every_meta_nodes + \c_meta_nodes_n\zerocount \t_meta_nodes\emptytoks #2\removeunwantedspaces % for alan, will be commented: \writestatus{metanodes}{\detokenize\expandafter{\the\t_meta_nodes}}% + \clf_grph_nodes_initialize \startMPcode mfun_node_init(% \the\dimexpr\metanodesparameter\c!dx\relax,% @@ -129,11 +138,9 @@ \the\t_meta_nodes ; mfun_node_flush ; \stopMPcode + \clf_grph_nodes_reset \egroup} -% \unexpanded\def\grph_nodes_node[#1,#2]#3% -% {\etoksapp\t_meta_nodes{mfun_node_make(\number#1,\number#2,"\metanodesparameter\c!command{#3}");}} - \unexpanded\def\grph_nodes_node {\dodoubleempty\grph_nodes_node_two} @@ -146,13 +153,20 @@ \setupcurrentmetanodes[#3]% \fi \edef\p_label{#4}% + \edef\p_reference{\metanodesparameter\c!reference}% + \ifx\p_reference\empty\else + \clf_grph_nodes_register{\p_reference}\c_meta_nodes_n\relax + \fi \normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{% mfun_node_make(\number#1,\number#2% - \ifx\p_label\empty \else + \ifx\p_label\empty + ,""% + \else ,"\metanodesparameter\c!command{\p_label}"% \fi );% - }}} + }}% + \advance\c_meta_nodes_n\plusone} \appendtoks \let\placenode\grph_nodes_node @@ -199,8 +213,11 @@ \space mfun_nodes_fromto\begincsname\??metanodesposition\metanodesparameter\c!position\endcsname(% \metanodesparameter\c!offset,% - \number#1,\number#2% - \ifx\p_label\empty \else + % \number#1,\number#2% + \clf_grph_nodes_resolve{#1},\clf_grph_nodes_resolve{#2}% + \ifx\p_label\empty + ,""% + \else ,"\ifx\p_command\empty\p_label\else\p_command{\p_label}\fi"% \fi )% diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua index 4a185cebd4d..5bcd161c02f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdf.lua @@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = { license = "see context related readme files" } +-- This module is not used in practice but we keep it around for historic +-- reasons. + -- Finally we used an optimized version. The test code can be found in -- meta-pdh.lua but since we no longer want to overload functione we use -- more locals now. This module keeps changing as it is also a testbed. @@ -35,20 +38,24 @@ local pdfgraycode = lpdf.graycode local pdfspotcode = lpdf.spotcode local pdftransparencycode = lpdf.transparencycode local pdffinishtransparencycode = lpdf.finishtransparencycode ------ pdfpageliteral = nodes.pool.pdfpageliteral metapost.mptopdf = metapost.mptopdf or { } local mptopdf = metapost.mptopdf mptopdf.nofconverted = 0 -local f_translate = formatters["1 0 0 0 1 %F %F cm"] -- no %s due to 1e-035 issues -local f_concat = formatters["%F %F %F %F %F %F cm"] -- no %s due to 1e-035 issues +local f_translate = formatters["1 0 0 0 1 %.6F %.6F cm"] +local f_concat = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"] + +directives.register("pdf.stripzeros",function() + f_translate = formatters["1 0 0 0 1 %.6N %.6N cm"] + f_concat = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] +end) local m_path, m_stack, m_texts, m_version, m_date, m_shortcuts = { }, { }, { }, 0, 0, false local m_stack_close, m_stack_path, m_stack_concat = false, { }, nil -local extra_path_code, ignore_path = nil, false +local extra_path_data, ignore_path = nil, false local specials = { } local function resetpath() @@ -57,28 +64,21 @@ end local function resetall() m_path, m_stack, m_texts, m_version, m_shortcuts = { }, { }, { }, 0, false - extra_path_code, ignore_path = nil, false + extra_path_data, ignore_path = nil, false specials = { } resetpath() end resetall() --- -- this does not work as expected (displacement of text) beware, needs another --- -- comment hack --- --- local function pdfcode(str) --- context(pdfpageliteral(str)) --- end - local pdfcode = context.pdfliteral local function mpscode(str) if ignore_path then pdfcode("h W n") - if extra_path_code then - pdfcode(extra_path_code) - extra_path_code = nil + if extra_path_data then + pdfcode(extra_path_data) + extra_path_data = nil end ignore_path = false else @@ -99,16 +99,28 @@ local function flushpath(cmd) if #m_stack_path > 0 then local path = { } if m_stack_concat then - local sx, sy = m_stack_concat[1], m_stack_concat[4] - local rx, ry = m_stack_concat[2], m_stack_concat[3] - local tx, ty = m_stack_concat[5], m_stack_concat[6] + local sx = m_stack_concat[1] + local sy = m_stack_concat[4] + local rx = m_stack_concat[2] + local ry = m_stack_concat[3] + local tx = m_stack_concat[5] + local ty = m_stack_concat[6] local d = (sx*sy) - (rx*ry) for k=1,#m_stack_path do - local v = m_stack_path[k] - local px, py = v[1], v[2] ; v[1], v[2] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[1],v[2]) + local v = m_stack_path[k] + local px = v[1] + local py = v[2] + v[1] = (sy*(px-tx)-ry*(py-ty))/d + v[2] = (sx*(py-ty)-rx*(px-tx))/d if #v == 7 then - local px, py = v[3], v[4] ; v[3], v[4] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[3],v[4]) - local px, py = v[5], v[6] ; v[5], v[6] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[5],v[6]) + px = v[3] + py = v[4] + v[3] = (sy*(px-tx)-ry*(py-ty))/d + v[4] = (sx*(py-ty)-rx*(px-tx))/d + px = v[5] + py = v[6] + v[5] = (sy*(px-tx)-ry*(py-ty))/d + v[6] = (sx*(py-ty)-rx*(px-tx))/d end path[k] = concat(v," ") end @@ -161,7 +173,8 @@ function mps.lineto(x,y) end function mps.rlineto(x,y) - local dx, dy = 0, 0 + local dx = 0 + local dy = 0 local topofstack = #m_stack_path if topofstack > 0 then local msp = m_stack_path[topofstack] @@ -238,7 +251,8 @@ function mps.clip() end function mps.textext(font, scale, str) -- old parser - local dx, dy = 0, 0 + local dx = 0 + local dy = 0 if #m_stack_path > 0 then dx, dy = m_stack_path[1][1], m_stack_path[1][2] end @@ -279,7 +293,7 @@ local function linearshade(colorspace,domain,ca,cb,coordinates) nofshades = nofshades + 1 local name = formatters["MpsSh%s"](nofshades) lpdf.linearshade(name,domain,ca,cb,1,colorspace,coordinates) - extra_path_code, ignore_path = formatters["/%s sh Q"](name), true + extra_path_data, ignore_path = formatters["/%s sh Q"](name), true pdfcode("q /Pattern cs") end @@ -288,7 +302,7 @@ local function circularshade(colorspace,domain,ca,cb,coordinates) nofshades = nofshades + 1 local name = formatters["MpsSh%s"](nofshades) lpdf.circularshade(name,domain,ca,cb,1,colorspace,coordinates) - extra_path_code, ignore_path = formatters["/%s sh Q"](name), true + extra_path_data, ignore_path = formatters["/%s sh Q"](name), true pdfcode("q /Pattern cs") end @@ -333,9 +347,12 @@ handlers[50] = function() report_mptopdf("skipping special %s",50) end --end of not supported function mps.setrgbcolor(r,g,b) -- extra check - r, g, b = tonumber(r), tonumber(g), tonumber(b) -- needed when we use lpeg + r = tonumber(r) -- needed when we use lpeg + g = tonumber(g) -- needed when we use lpeg + b = tonumber(b) -- needed when we use lpeg if r == 0.0123 and g < 0.1 then - g, b = round(g*10000), round(b*10000) + g = round(g*10000) + b = round(b*10000) local s = specials[b] local h = round(s[#s]) local handler = handlers[h] @@ -345,7 +362,8 @@ function mps.setrgbcolor(r,g,b) -- extra check report_mptopdf("unknown special handler %s (1)",h) end elseif r == 0.123 and g < 0.1 then - g, b = round(g*1000), round(b*1000) + g = round(g*1000) + b = round(b*1000) local s = specials[b] local h = round(s[#s]) local handler = handlers[h] diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv index f9eff73caaa..e4ac92fb404 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-pdh.mkiv @@ -92,15 +92,15 @@ {\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi} \def\resetMPvariables#1#2#3% - {\global\let\MPwidth \!!zeropoint - \global\let\MPheight\!!zeropoint - \global\let\MPllx \!!zerocount - \global\let\MPlly \!!zerocount - \global\let\MPurx \!!zerocount - \global\let\MPury \!!zerocount - \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi - \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi - \xdef\MPfilename {#1}} + {\glet\MPwidth \!!zeropoint + \glet\MPheight \!!zeropoint + \glet\MPllx \!!zerocount + \glet\MPlly \!!zerocount + \glet\MPurx \!!zerocount + \glet\MPury \!!zerocount + \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi + \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi + \xdef\MPfilename {#1}} %D The main macro: @@ -164,7 +164,7 @@ \else \getMPPDFobject \fi - \global\let\currentPDFresources\empty + \glet\currentPDFresources\empty \else \box#1% \fi} @@ -250,12 +250,12 @@ %D Some day we may consider collecting local resources. \appendtoks - \global\let\currentPDFresources\empty % kind of redundant + \glet\currentPDFresources\empty % kind of redundant \to \MPstartresources % \appendtoks % \collectPDFresources -% \global\let\currentPDFresources\collectedPDFresources +% \glet\currentPDFresources\collectedPDFresources % \to \MPstopresources \appendtoksonce diff --git a/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua index fdf11842428..c2f72bcf3c7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/meta-tex.lua @@ -126,11 +126,7 @@ do arguments = "2 strings", } - if LUAVERSION < 5.2 then - utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], "local texexp = metapost.texexp") - else - utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], { texexp = metapost.texexp }) - end + utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], { texexp = metapost.texexp }) local f_textext = formatters[ [[textext("%s")]] ] local f_mthtext = formatters[ [[textext("\mathematics{%s}")]] ] diff --git a/Master/texmf-dist/tex/context/base/mkiv/metatex.tex b/Master/texmf-dist/tex/context/base/mkiv/metatex.tex deleted file mode 100644 index 7c8a7ff0104..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/metatex.tex +++ /dev/null @@ -1,30 +0,0 @@ -%D \module -%D [ file=metatex, -%D version=2008.10.10, -%D title=\METATEX, -%D subtitle=\METATEX\ Format Generation, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D We can experiment here with runtime loading, i.e. no longer -%D use a format. However, we still need a stub then but it could -%D as well be luatools (mtxrun) itself then. - -%D This format is just a minimal layer on top of the \LUATEX\ -%D engine and will not provide high level functionality. It can -%D be used as basis for dedicated (specialized) macro packages. -%D -%D A format is generated with the command; -%D -%D \starttyping -%D mtxrun --script metatex --make -%D \stoptyping -%D -%D For the moment this is a placeholder. Maybe some day ... the old -%D file history/metatex/metatex.tex so I can pick up from there if -%D needed. diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua index c568b92a3f1..89f2fa0eeb1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-ctx.lua @@ -11,46 +11,29 @@ local format, concat = string.format, table.concat local settings_to_hash = utilities.parsers.settings_to_hash local formatters = string.formatters -local report_metapost = logs.reporter("metapost") +local report_metapost = logs.reporter ("metapost") +local status_metapost = logs.messenger("metapost") -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming -local mplib = mplib +local trace_graphic = false -metapost = metapost or { } -local metapost = metapost -local context = context +trackers.register("metapost.graphics", + function(v) trace_graphic = v end +); -local setters = tokens.setters -local setmacro = setters.macro -local implement = interfaces.implement +local mplib = mplib -local v_no = interfaces.variables.no +metapost = metapost or { } +local metapost = metapost +local context = context -metapost.defaultformat = "metafun" -metapost.defaultinstance = "metafun" -metapost.defaultmethod = "default" +local setters = tokens.setters +local setmacro = setters.macro +local implement = interfaces.implement -local function setmpsformat(specification) - local instance = specification.instance - local format = specification.format - local method = specification.method - if not instance or instance == "" then - instance = metapost.defaultinstance - specification.instance = instance - end - if not format or format == "" then - format = metapost.defaultformat - specification.format = format - end - if not method or method == "" then - method = metapost.defaultmethod - specification.method = method - end - specification.mpx = metapost.format(instance,format,method) - return specification -end +local v_no = interfaces.variables.no local extensiondata = metapost.extensiondata or storage.allocate { } metapost.extensiondata = extensiondata @@ -96,9 +79,6 @@ implement { arguments = "string" } -local report_metapost = logs.reporter ("metapost") -local status_metapost = logs.messenger("metapost") - local patterns = { "meta-imp-%s.mkiv", "meta-imp-%s.tex", @@ -192,7 +172,9 @@ implement { -- or just move the scanners to pps function metapost.graphic(specification) - metapost.graphic_base_pass(setmpsformat(specification)) + metapost.pushformat(specification) + metapost.graphic_base_pass(specification) + metapost.popformat() end function metapost.startgraphic(t) @@ -208,9 +190,6 @@ function metapost.startgraphic(t) if not t.method then t.method = metapost.defaultmethod end - if not t.definitions then - t.definitions = "" - end t.data = { } return t end @@ -218,8 +197,10 @@ end function metapost.stopgraphic(t) if t then t.data = concat(t.data or { },"\n") + if trace_graphic then + report_metapost("\n"..t.data.."\n") + end metapost.graphic(t) - t.data = "" end end @@ -265,8 +246,7 @@ implement { } function metapost.getclippath(specification) -- why not a special instance for this - setmpsformat(specification) - local mpx = specification.mpx + local mpx = metapost.pushformat(specification) local data = specification.data or "" if mpx and data ~= "" then starttiming(metapost) @@ -285,7 +265,10 @@ function metapost.getclippath(specification) -- why not a special instance for t result = metapost.filterclippath(result) end stoptiming(metapost) + metapost.pushformat() return result + else + metapost.pushformat() end end @@ -337,23 +320,17 @@ implement { } } -statistics.register("metapost processing time", function() +statistics.register("metapost", function() local n = metapost.n if n and n > 0 then - local nofconverted = metapost.makempy.nofconverted local elapsedtime = statistics.elapsedtime - local elapsed = statistics.elapsed - local instances, memory = metapost.getstatistics(true) - local str = format("%s seconds, loading: %s, execution: %s, n: %s, average: %s, instances: %i, memory: %0.3f M", + local elapsed = statistics.elapsed + local instances, + memory = metapost.getstatistics(true) + return format("%s seconds, loading: %s, execution: %s, n: %s, average: %s, instances: %i, luacalls: %i, memory: %0.3f M", elapsedtime(metapost), elapsedtime(mplib), elapsedtime(metapost.exectime), n, elapsedtime((elapsed(metapost) + elapsed(mplib) + elapsed(metapost.exectime)) / n), - instances, memory/(1024*1024)) - if nofconverted > 0 then - return format("%s, external: %s (%s calls)", - str, elapsedtime(metapost.makempy), nofconverted) - else - return str - end + instances, metapost.nofscriptruns(),memory/(1024*1024)) else return nil end diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua index bd3ba213f86..63e7278dae7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-int.lua @@ -7,11 +7,14 @@ if not modules then modules = { } end modules ['mlib-int'] = { } local factor = number.dimenfactors.bp -local mpprint = mp.print ------ mpboolean = mp.boolean ------ mpquoted = mp.quoted +----- mpprint = mp.print +local mpnumeric = mp.numeric +local mpboolean = mp.boolean +local mpstring = mp.string +local mpquoted = mp.quoted local getdimen = tex.getdimen local getcount = tex.getcount +local getmacro = tokens.getters.macro local get = tex.get local mpcolor = attributes.colors.mpcolor local emwidths = fonts.hashes.emwidths @@ -19,90 +22,90 @@ local exheights = fonts.hashes.exheights local mpgetdimen = mp.getdimen -function mp.PaperHeight () mpprint(getdimen("paperheight") *factor) end -function mp.PaperWidth () mpprint(getdimen("paperwidth") *factor) end -function mp.PrintPaperHeight () mpprint(getdimen("printpaperheight") *factor) end -function mp.PrintPaperWidth () mpprint(getdimen("printpaperwidth") *factor) end -function mp.TopSpace () mpprint(getdimen("topspace") *factor) end -function mp.BottomSpace () mpprint(getdimen("bottomspace") *factor) end -function mp.BackSpace () mpprint(getdimen("backspace") *factor) end -function mp.CutSpace () mpprint(getdimen("cutspace") *factor) end -function mp.MakeupHeight () mpprint(getdimen("makeupheight") *factor) end -function mp.MakeupWidth () mpprint(getdimen("makeupwidth") *factor) end -function mp.TopHeight () mpprint(getdimen("topheight") *factor) end -function mp.TopDistance () mpprint(getdimen("topdistance") *factor) end -function mp.HeaderHeight () mpprint(getdimen("headerheight") *factor) end -function mp.HeaderDistance () mpprint(getdimen("headerdistance") *factor) end -function mp.TextHeight () mpprint(getdimen("textheight") *factor) end -function mp.FooterDistance () mpprint(getdimen("footerdistance") *factor) end -function mp.FooterHeight () mpprint(getdimen("footerheight") *factor) end -function mp.BottomDistance () mpprint(getdimen("bottomdistance") *factor) end -function mp.BottomHeight () mpprint(getdimen("bottomheight") *factor) end -function mp.LeftEdgeWidth () mpprint(getdimen("leftedgewidth") *factor) end -function mp.LeftEdgeDistance () mpprint(getdimen("leftedgedistance") *factor) end -function mp.LeftMarginWidth () mpprint(getdimen("leftmarginwidth") *factor) end -function mp.LeftMarginDistance () mpprint(getdimen("leftmargindistance") *factor) end -function mp.TextWidth () mpprint(getdimen("textwidth") *factor) end -function mp.RightMarginDistance () mpprint(getdimen("rightmargindistance") *factor) end -function mp.RightMarginWidth () mpprint(getdimen("rightmarginwidth") *factor) end -function mp.RightEdgeDistance () mpprint(getdimen("rightedgedistance") *factor) end -function mp.RightEdgeWidth () mpprint(getdimen("rightedgewidth") *factor) end -function mp.InnerMarginDistance () mpprint(getdimen("innermargindistance") *factor) end -function mp.InnerMarginWidth () mpprint(getdimen("innermarginwidth") *factor) end -function mp.OuterMarginDistance () mpprint(getdimen("outermargindistance") *factor) end -function mp.OuterMarginWidth () mpprint(getdimen("outermarginwidth") *factor) end -function mp.InnerEdgeDistance () mpprint(getdimen("inneredgedistance") *factor) end -function mp.InnerEdgeWidth () mpprint(getdimen("inneredgewidth") *factor) end -function mp.OuterEdgeDistance () mpprint(getdimen("outeredgedistance") *factor) end -function mp.OuterEdgeWidth () mpprint(getdimen("outeredgewidth") *factor) end -function mp.PageOffset () mpprint(getdimen("pagebackgroundoffset")*factor) end -function mp.PageDepth () mpprint(getdimen("pagebackgrounddepth") *factor) end -function mp.LayoutColumns () mpprint(getcount("layoutcolumns")) end -function mp.LayoutColumnDistance() mpprint(getdimen("layoutcolumndistance")*factor) end -function mp.LayoutColumnWidth () mpprint(getdimen("layoutcolumnwidth") *factor) end -function mp.SpineWidth () mpprint(getdimen("spinewidth") *factor) end -function mp.PaperBleed () mpprint(getdimen("paperbleed") *factor) end - -function mp.RealPageNumber () mpprint(getcount("realpageno")) end -function mp.LastPageNumber () mpprint(getcount("lastpageno")) end - -function mp.PageNumber () mpprint(getcount("pageno")) end -function mp.NOfPages () mpprint(getcount("lastpageno")) end - -function mp.SubPageNumber () mpprint(getcount("subpageno")) end -function mp.NOfSubPages () mpprint(getcount("lastsubpageno")) end - -function mp.CurrentColumn () mpprint(getcount("mofcolumns")) end -function mp.NOfColumns () mpprint(getcount("nofcolumns")) end - -function mp.BaseLineSkip () mpprint(get ("baselineskip",true) *factor) end -function mp.LineHeight () mpprint(getdimen("lineheight") *factor) end -function mp.BodyFontSize () mpprint(getdimen("bodyfontsize") *factor) end - -function mp.TopSkip () mpprint(get ("topskip",true) *factor) end -function mp.StrutHeight () mpprint(getdimen("strutht") *factor) end -function mp.StrutDepth () mpprint(getdimen("strutdp") *factor) end - -function mp.PageNumber () mpprint(getcount("pageno")) end -function mp.RealPageNumber () mpprint(getcount("realpageno")) end -function mp.NOfPages () mpprint(getcount("lastpageno")) end - -function mp.CurrentWidth () mpprint(get ("hsize") *factor) end -function mp.CurrentHeight () mpprint(get ("vsize") *factor) end - -function mp.EmWidth () mpprint(emwidths [false]*factor) end -function mp.ExHeight () mpprint(exheights[false]*factor) end +function mp.PaperHeight () mpnumeric(getdimen("paperheight") *factor) end +function mp.PaperWidth () mpnumeric(getdimen("paperwidth") *factor) end +function mp.PrintPaperHeight () mpnumeric(getdimen("printpaperheight") *factor) end +function mp.PrintPaperWidth () mpnumeric(getdimen("printpaperwidth") *factor) end +function mp.TopSpace () mpnumeric(getdimen("topspace") *factor) end +function mp.BottomSpace () mpnumeric(getdimen("bottomspace") *factor) end +function mp.BackSpace () mpnumeric(getdimen("backspace") *factor) end +function mp.CutSpace () mpnumeric(getdimen("cutspace") *factor) end +function mp.MakeupHeight () mpnumeric(getdimen("makeupheight") *factor) end +function mp.MakeupWidth () mpnumeric(getdimen("makeupwidth") *factor) end +function mp.TopHeight () mpnumeric(getdimen("topheight") *factor) end +function mp.TopDistance () mpnumeric(getdimen("topdistance") *factor) end +function mp.HeaderHeight () mpnumeric(getdimen("headerheight") *factor) end +function mp.HeaderDistance () mpnumeric(getdimen("headerdistance") *factor) end +function mp.TextHeight () mpnumeric(getdimen("textheight") *factor) end +function mp.FooterDistance () mpnumeric(getdimen("footerdistance") *factor) end +function mp.FooterHeight () mpnumeric(getdimen("footerheight") *factor) end +function mp.BottomDistance () mpnumeric(getdimen("bottomdistance") *factor) end +function mp.BottomHeight () mpnumeric(getdimen("bottomheight") *factor) end +function mp.LeftEdgeWidth () mpnumeric(getdimen("leftedgewidth") *factor) end +function mp.LeftEdgeDistance () mpnumeric(getdimen("leftedgedistance") *factor) end +function mp.LeftMarginWidth () mpnumeric(getdimen("leftmarginwidth") *factor) end +function mp.LeftMarginDistance () mpnumeric(getdimen("leftmargindistance") *factor) end +function mp.TextWidth () mpnumeric(getdimen("textwidth") *factor) end +function mp.RightMarginDistance () mpnumeric(getdimen("rightmargindistance") *factor) end +function mp.RightMarginWidth () mpnumeric(getdimen("rightmarginwidth") *factor) end +function mp.RightEdgeDistance () mpnumeric(getdimen("rightedgedistance") *factor) end +function mp.RightEdgeWidth () mpnumeric(getdimen("rightedgewidth") *factor) end +function mp.InnerMarginDistance () mpnumeric(getdimen("innermargindistance") *factor) end +function mp.InnerMarginWidth () mpnumeric(getdimen("innermarginwidth") *factor) end +function mp.OuterMarginDistance () mpnumeric(getdimen("outermargindistance") *factor) end +function mp.OuterMarginWidth () mpnumeric(getdimen("outermarginwidth") *factor) end +function mp.InnerEdgeDistance () mpnumeric(getdimen("inneredgedistance") *factor) end +function mp.InnerEdgeWidth () mpnumeric(getdimen("inneredgewidth") *factor) end +function mp.OuterEdgeDistance () mpnumeric(getdimen("outeredgedistance") *factor) end +function mp.OuterEdgeWidth () mpnumeric(getdimen("outeredgewidth") *factor) end +function mp.PageOffset () mpnumeric(getdimen("pagebackgroundoffset")*factor) end +function mp.PageDepth () mpnumeric(getdimen("pagebackgrounddepth") *factor) end +function mp.LayoutColumns () mpnumeric(getcount("layoutcolumns")) end +function mp.LayoutColumnDistance() mpnumeric(getdimen("layoutcolumndistance")*factor) end +function mp.LayoutColumnWidth () mpnumeric(getdimen("layoutcolumnwidth") *factor) end +function mp.SpineWidth () mpnumeric(getdimen("spinewidth") *factor) end +function mp.PaperBleed () mpnumeric(getdimen("paperbleed") *factor) end + +function mp.RealPageNumber () mpnumeric(getcount("realpageno")) end +function mp.LastPageNumber () mpnumeric(getcount("lastpageno")) end + +function mp.PageNumber () mpnumeric(getcount("pageno")) end +function mp.NOfPages () mpnumeric(getcount("lastpageno")) end + +function mp.SubPageNumber () mpnumeric(getcount("subpageno")) end +function mp.NOfSubPages () mpnumeric(getcount("lastsubpageno")) end + +function mp.CurrentColumn () mpnumeric(getcount("mofcolumns")) end +function mp.NOfColumns () mpnumeric(getcount("nofcolumns")) end + +function mp.BaseLineSkip () mpnumeric(get ("baselineskip",true) *factor) end +function mp.LineHeight () mpnumeric(getdimen("lineheight") *factor) end +function mp.BodyFontSize () mpnumeric(getdimen("bodyfontsize") *factor) end + +function mp.TopSkip () mpnumeric(get ("topskip",true) *factor) end +function mp.StrutHeight () mpnumeric(getdimen("strutht") *factor) end +function mp.StrutDepth () mpnumeric(getdimen("strutdp") *factor) end + +function mp.PageNumber () mpnumeric(getcount("pageno")) end +function mp.RealPageNumber () mpnumeric(getcount("realpageno")) end +function mp.NOfPages () mpnumeric(getcount("lastpageno")) end + +function mp.CurrentWidth () mpnumeric(get ("hsize") *factor) end +function mp.CurrentHeight () mpnumeric(get ("vsize") *factor) end + +function mp.EmWidth () mpnumeric(emwidths [false]*factor) end +function mp.ExHeight () mpnumeric(exheights[false]*factor) end mp.HSize = mp.CurrentWidth mp.VSize = mp.CurrentHeight mp.LastPageNumber = mp.NOfPages -function mp.PageFraction () +function mp.PageFraction() local lastpage = getcount("lastpageno") if lastpage > 1 then - mpprint((getcount("realpageno")-1)/(lastpage-1)) + mpnumeric((getcount("realpageno")-1)/(lastpage-1)) else - mpprint(1) + mpnumeric(1) end end @@ -112,30 +115,22 @@ local on_right = structures.pages.on_right local is_odd = structures.pages.is_odd local in_body = structures.pages.in_body -mp.OnRightPage = function() mpprint(on_right()) end -- needs checking -mp.OnOddPage = function() mpprint(is_odd ()) end -- needs checking -mp.InPageBody = function() mpprint(in_body ()) end -- needs checking +mp.OnRightPage = function() mpboolean(on_right()) end -- needs checking +mp.OnOddPage = function() mpboolean(is_odd ()) end -- needs checking +mp.InPageBody = function() mpboolean(in_body ()) end -- needs checking -- mp.CurrentLayout : \currentlayout -function mp.OverlayWidth () mpprint(getdimen("d_overlay_width") *factor) end -function mp.OverlayHeight () mpprint(getdimen("d_overlay_height") *factor) end -function mp.OverlayDepth () mpprint(getdimen("d_overlay_depth") *factor) end -function mp.OverlayLineWidth () mpprint(getdimen("d_overlay_linewidth")*factor) end -function mp.OverlayOffset () mpprint(getdimen("d_overlay_offset") *factor) end +function mp.OverlayWidth () mpnumeric(getdimen("d_overlay_width") * factor) end +function mp.OverlayHeight () mpnumeric(getdimen("d_overlay_height") * factor) end +function mp.OverlayDepth () mpnumeric(getdimen("d_overlay_depth") * factor) end +function mp.OverlayLineWidth() mpnumeric(getdimen("d_overlay_linewidth") * factor) end +function mp.OverlayOffset () mpnumeric(getdimen("d_overlay_offset") * factor) end +function mp.OverlayRegion () mpstring(getmacro("m_overlay_region")) end -function mp.defaultcolormodel() +function mp.mf_default_color_model() local colormethod = getcount("MPcolormethod") - -- if colormethod == 0 then - -- return 1 - -- elseif colormethod == 1 then - -- return 1 - -- elseif colormethod == 2 then - -- return 3 - -- else - -- return 3 - -- end - return (colormethod == 0 or colormethod == 1) and 1 or 3 + return mpnumeric((colormethod == 0 or colormethod == 1) and 1 or 3) end -- not much difference (10000 calls in a graphic neither as expansion seems to win diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua index 19e731b8569..d7c2a0fc3f2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-lua.lua @@ -10,11 +10,11 @@ if not modules then modules = { } end modules ['mlib-lua'] = { -- maybe we need mplib.model, but how with instances -local type, tostring, select, loadstring = type, tostring, select, loadstring +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 concat, insert, remove = table.concat, table.insert, table.remove local formatters = string.formatters -local concat = table.concat local lpegmatch = lpeg.match local lpegpatterns = lpeg.patterns @@ -26,105 +26,18 @@ local report_message = logs.reporter("metapost") local trace_luarun = false trackers.register("metapost.lua",function(v) trace_luarun = v end) local trace_enabled = true -local be_tolerant = true directives.register("metapost.lua.tolerant",function(v) be_tolerant = v end) +local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end) -mp = mp or { } -- system namespace -MP = MP or { } -- user namespace +local get, set, aux = { }, { }, { } -local buffer, n, max = { }, 0, 10 -- we reuse upto max - -function mp._f_() - if trace_enabled and trace_luarun then - local result = concat(buffer," ",1,n) - if n > max then - buffer = { } - end - n = 0 - report_luarun("data: %s",result) - return result - else - if n == 0 then - return "" - end - local result - if n == 1 then - result = buffer[1] - else - result = concat(buffer," ",1,n) - end - if n > max then - buffer = { } - end - n = 0 - return result - end -end - -local f_code = formatters["%s return mp._f_()"] - -local f_numeric = formatters["%.16f"] -local f_integer = formatters["%i"] -local f_pair = formatters["(%.16f,%.16f)"] -local f_triplet = formatters["(%.16f,%.16f,%.16f)"] -local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"] - -local function mpprint(...) -- we can optimize for n=1 - for i=1,select("#",...) do - local value = select(i,...) - if value ~= nil then - n = n + 1 - local t = type(value) - if t == "number" then - buffer[n] = f_numeric(value) - elseif t == "string" then - buffer[n] = value - elseif t == "table" then - buffer[n] = "(" .. concat(value,",") .. ")" - else -- boolean or whatever - buffer[n] = tostring(value) - end - end - end -end - -local r = P('%') / "percent" - + P('"') / "dquote" - + P('\n') / "crlf" - -- + P(' ') / "space" -local a = Cc("&") -local q = Cc('"') -local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q) - -local function mpvprint(...) -- variable print - for i=1,select("#",...) do - local value = select(i,...) - if value ~= nil then - n = n + 1 - local t = type(value) - if t == "number" then - buffer[n] = f_numeric(value) - elseif t == "string" then - buffer[n] = lpegmatch(p,value) - elseif t == "table" then - local m = #t - if m == 2 then - buffer[n] = f_pair(unpack(t)) - elseif m == 3 then - buffer[n] = f_triplet(unpack(t)) - elseif m == 4 then - buffer[n] = f_quadruple(unpack(t)) - else -- error - buffer[n] = "" - end - else -- boolean or whatever - buffer[n] = tostring(value) - end - end - end -end +mp = mp or { -- system namespace + set = set, + get = get, + aux = aux, +} -mp.print = mpprint -mp.vprint = mpvprint +MP = MP or { -- user namespace +} -- We had this: -- @@ -139,150 +52,540 @@ mp.vprint = mpvprint -- lua.mp("somedefdname","foo") table.setmetatablecall(mp,function(t,k,...) return t[k](...) end) +table.setmetatablecall(MP,function(t,k,...) return t[k](...) end) -function mp.boolean(b) - n = n + 1 - buffer[n] = b and "true" or "false" -end +do -function mp.numeric(f) - n = n + 1 - buffer[n] = f and f_numeric(f) or "0" -end + local currentmpx = nil + local stack = { } -function mp.integer(i) - n = n + 1 - -- buffer[n] = i and f_integer(i) or "0" - buffer[n] = i or "0" -end + local get_numeric = mplib.get_numeric + local get_string = mplib.get_string + local get_boolean = mplib.get_boolean + local get_path = mplib.get_path + local set_path = mplib.set_path + + get.numeric = function(s) return get_numeric(currentmpx,s) end + get.string = function(s) return get_string (currentmpx,s) end + get.boolean = function(s) return get_boolean(currentmpx,s) end + get.path = function(s) return get_path (currentmpx,s) end + get.number = function(s) return get_numeric(currentmpx,s) end -function mp.pair(x,y) - n = n + 1 - if type(x) == "table" then - buffer[n] = f_pair(x[1],x[2]) - else - buffer[n] = f_pair(x,y) + set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet + + function metapost.pushscriptrunner(mpx) + insert(stack,mpx) + currentmpx = mpx end -end -function mp.triplet(x,y,z) - n = n + 1 - if type(x) == "table" then - buffer[n] = f_triplet(x[1],x[2],x[3]) - else - buffer[n] = f_triplet(x,y,z) + function metapost.popscriptrunner() + currentmpx = remove(stack,mpx) end + end -function mp.quadruple(w,x,y,z) - n = n + 1 - if type(w) == "table" then - buffer[n] = f_quadruple(w[1],w[2],w[3],w[4]) - else - buffer[n] = f_quadruple(w,x,y,z) +do + + local buffer = { } + local n = 0 + local max = 20 -- we reuse upto max + local nesting = 0 + local runs = 0 + + local function _f_() + if trace_enabled and trace_luarun then + local result = concat(buffer," ",1,n) + if n > max then + buffer = { } + end + n = 0 + report_luarun("%i: data: %s",nesting,result) + return result + else + if n == 0 then + return "" + end + local result + if n == 1 then + result = buffer[1] + else + result = concat(buffer," ",1,n) + end + if n > max then + buffer = { } + end + n = 0 + return result + end + end + + mp._f_ = _f_ -- convenient to have it in a top module + aux.flush = _f_ + + ----- f_code = formatters["%s return mp._f_()"] + + local f_integer = formatters["%i"] + + local f_numeric = formatters["%n"] -- maybe %N + local f_pair = formatters["(%n,%n)"] + local f_ctrl = formatters["(%n,%n) .. controls (%n,%n) and (%n,%n)"] + local f_triplet = formatters["(%n,%n,%n)"] + local f_quadruple = formatters["(%n,%n,%n,%n)"] + + local f_points = formatters["%p"] + local f_pair_pt = formatters["(%p,%p)"] + local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"] + local f_triplet_pt = formatters["(%p,%p,%p)"] + local f_quadruple_pt = formatters["(%p,%p,%p,%p)"] + + local r = P('%') / "percent" + + P('"') / "dquote" + + P('\n') / "crlf" + -- + P(' ') / "space" + local a = Cc("&") + local q = Cc('"') + local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q) + + mp.cleaned = function(s) return lpegmatch(p,s) or s end + + -- local function mpprint(...) -- we can optimize for n=1 + -- for i=1,select("#",...) do + -- local value = (select(i,...)) + -- if value ~= nil then + -- n = n + 1 + -- local t = type(value) + -- if t == "number" then + -- buffer[n] = f_numeric(value) + -- elseif t == "string" then + -- buffer[n] = value + -- elseif t == "table" then + -- buffer[n] = "(" .. concat(value,",") .. ")" + -- else -- boolean or whatever + -- buffer[n] = tostring(value) + -- end + -- end + -- end + -- end + + local function mpp(value) + n = n + 1 + local t = type(value) + if t == "number" then + buffer[n] = f_numeric(value) + elseif t == "string" then + buffer[n] = value + elseif t == "table" then + buffer[n] = "(" .. concat(value,",") .. ")" + else -- boolean or whatever + buffer[n] = tostring(value) + end + end + + local function mpprint(first,second,...) + if second == nil then + if first ~= nil then + mpp(first) + end + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + mpp(value) + end + end + end end -end -function mp.path(t,connector,cycle) - if type(t) == "table" then - local tn = #t - if tn > 0 then - if connector == true then - connector = "--" - cycle = true - elseif not connector then - connector = "--" + local function mpp(value) + n = n + 1 + local t = type(value) + if t == "number" then + buffer[n] = f_numeric(value) + elseif t == "string" then + buffer[n] = lpegmatch(p,value) + elseif t == "table" then + if #t > 4 then + buffer[n] = "" + else + buffer[n] = "(" .. concat(value,",") .. ")" end - local ti = t[1] - n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2]) - for i=2,tn do - local ti = t[i] - n = n + 1 ; buffer[n] = connector - n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2]) + else -- boolean or whatever + buffer[n] = tostring(value) + end + end + + local function mpvprint(first,second,...) -- variable print + if second == nil then + if first ~= nil then + mpp(first) end - if cycle then - n = n + 1 ; buffer[n] = connector - n = n + 1 ; buffer[n] = "cycle" + else + for i=1,select("#",first,second,...) do + local value = (select(i,first,second,...)) + if value ~= nil then + mpp(value) + end end end end -end -function mp.size(t) - n = n + 1 - buffer[n] = type(t) == "table" and f_numeric(#t) or "0" -end + local function mpstring(value) + n = n + 1 + buffer[n] = lpegmatch(p,value) + end -local mpnamedcolor = attributes.colors.mpnamedcolor + local function mpboolean(b) + n = n + 1 + buffer[n] = b and "true" or "false" + end -mp.NamedColor = function(str) - mpprint(mpnamedcolor(str)) -end + local function mpnumeric(f) + n = n + 1 + if not f or f == 0 then + buffer[n] = "0" + else + buffer[n] = f_numeric(f) + end + end --- experiment: names can change + local function mpinteger(i) + n = n + 1 + -- buffer[n] = i and f_integer(i) or "0" + buffer[n] = i or "0" + end -local datasets = { } -mp.datasets = datasets + local function mppoints(i) + n = n + 1 + if not i or i == 0 then + buffer[n] = "0pt" + else + buffer[n] = f_points(i) + end + end -function datasets.load(tag,filename) - if not filename then - tag, filename = file.basename(tag), tag + local function mppair(x,y) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_pair(x[1],x[2]) + else + buffer[n] = f_pair(x,y) + end end - local data = mp.dataset(io.loaddata(filename) or "") - datasets[tag] = { - Data = data, - Line = function(n) mp.path(data[n or 1]) end, - Size = function() mp.size(data) end, - } -end --- + local function mppairpoints(x,y) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_pair_pt(x[1],x[2]) + else + buffer[n] = f_pair_pt(x,y) + end + end + + local function mptriplet(x,y,z) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_triplet(x[1],x[2],x[3]) + else + buffer[n] = f_triplet(x,y,z) + end + end -local replacer = lpeg.replacer("@","%%") + local function mptripletpoints(x,y,z) + n = n + 1 + if type(x) == "table" then + buffer[n] = f_triplet_pt(x[1],x[2],x[3]) + else + buffer[n] = f_triplet_pt(x,y,z) + end + end -function mp.fprint(fmt,...) - n = n + 1 - if not find(fmt,"%",1,true) then - fmt = lpegmatch(replacer,fmt) + local function mpquadruple(w,x,y,z) + n = n + 1 + if type(w) == "table" then + buffer[n] = f_quadruple(w[1],w[2],w[3],w[4]) + else + buffer[n] = f_quadruple(w,x,y,z) + end end - buffer[n] = formatters[fmt](...) -end -local function mpquoted(fmt,s,...) - n = n + 1 - if s then + local function mpquadruplepoints(w,x,y,z) + n = n + 1 + if type(w) == "table" then + buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4]) + else + buffer[n] = f_quadruple_pt(w,x,y,z) + end + end + + -- we have three kind of connectors: + -- + -- .. ... -- (true) + + local function mp_path(f2,f6,t,connector,cycle) + if type(t) == "table" then + local tn = #t + if tn == 1 then + local t1 = t[1] + n = n + 1 ; buffer[n] = f2(t1[1],t1[2]) + elseif tn > 0 then + if connector == true or connector == nil then + connector = ".." + elseif connector == false then + connector = "--" + end + if cycle == nil then + cycle = t.cycle + if cycle == nil then + cycle = true + end + end + local six = connector == ".." -- otherwise we use whatever gets asked for + local controls = connector -- whatever + local a = t[1] + local b = t[2] + n = n + 1 + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + for i=2,tn-1 do + a = b + b = t[i+1] + n = n + 1 + buffer[n] = connector + n = n + 1 + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + end + n = n + 1 + buffer[n] = connector + a = b + b = t[1] + n = n + 1 + if cycle then + if six and #a == 6 and #b == 6 then + buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4]) + controls = ".." + else + buffer[n] = f2(a[1],a[2]) + controls = connector + end + n = n + 1 + buffer[n] = connector + n = n + 1 + buffer[n] = "cycle" + else + buffer[n] = f2(a[1],a[2]) + end + end + end + end + + local function mppath(...) + mp_path(f_pair,f_ctrl,...) + end + + local function mppathpoints(...) + mp_path(f_pair_pt,f_ctrl_pt,...) + end + + local function mpsize(t) + n = n + 1 + buffer[n] = type(t) == "table" and f_numeric(#t) or "0" + end + + local replacer = lpeg.replacer("@","%%") + + local function mpfprint(fmt,...) + n = n + 1 if not find(fmt,"%",1,true) then fmt = lpegmatch(replacer,fmt) end - -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"' - buffer[n] = lpegmatch(p,formatters[fmt](s,...)) - elseif fmt then - -- buffer[n] = '"' .. fmt .. '"' - buffer[n] = lpegmatch(p,fmt) - else - -- something is wrong + buffer[n] = formatters[fmt](...) end + + local function mpquoted(fmt,s,...) + if s then + n = n + 1 + if not find(fmt,"%",1,true) then + fmt = lpegmatch(replacer,fmt) + end + -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"' + buffer[n] = lpegmatch(p,formatters[fmt](s,...)) + elseif fmt then + n = n + 1 + -- buffer[n] = '"' .. fmt .. '"' + buffer[n] = lpegmatch(p,fmt) + else + -- something is wrong + end + end + + aux.print = mpprint + aux.vprint = mpvprint + aux.boolean = mpboolean + aux.string = mpstring + aux.numeric = mpnumeric + aux.number = mpnumeric + aux.integer = mpinteger + aux.points = mppoints + aux.pair = mppair + aux.pairpoints = mppairpoints + aux.triplet = mptriplet + aux.tripletpoints = mptripletpoints + aux.quadruple = mpquadruple + aux.quadruplepoints = mpquadruplepoints + aux.path = mppath + aux.pathpoints = mppathpoints + aux.size = mpsize + aux.fprint = mpfprint + aux.quoted = mpquoted + + -- we need access to the variables + + function metapost.nofscriptruns() + return runs + end + + -- sometimes we gain (e.g. .5 sec on the sync test) + + local cache = table.makeweak() + + function metapost.runscript(code) + nesting = nesting + 1 + local trace = trace_enabled and trace_luarun + if trace then + report_luarun("%i: code: %s",nesting,code) + end + runs = runs + 1 + local f = cache[code] + if not f then + f = loadstring(code .. " return mp._f_()") + if f then + cache[code] = f + elseif be_tolerant then + f = loadstring(code) + if f then + cache[code] = f + end + end + end + if f then + local _buffer_ = buffer + local _n_ = n + buffer = { } + n = 0 + local result = f() + if result then + local t = type(result) + if t == "number" then + result = f_numeric(result) + elseif t ~= "string" then + result = tostring(result) + end + if trace then + if #result == 0 then + report_luarun("%i: no result",nesting) + else + report_luarun("%i: result: %s",nesting,result) + end + end + buffer = _buffer_ + n = _n_ + nesting = nesting - 1 + return result + elseif trace then + report_luarun("%i: no result",nesting) + end + buffer, n = _buffer_, _n_ + else + report_luarun("%i: no result, invalid code: %s",nesting,code) + end + nesting = nesting - 1 + return "" + end + + -- for the moment + + for k, v in next, aux do mp[k] = v end + end -mp.quoted = mpquoted +do + + local mpnamedcolor = attributes.colors.mpnamedcolor + local mpprint = aux.print -function mp.n(t) + mp.mf_named_color = function(str) + mpprint(mpnamedcolor(str)) + end + +end + +function mp.n(t) -- used ? return type(t) == "table" and #t or 0 end -local whitespace = lpegpatterns.whitespace -local newline = lpegpatterns.newline -local setsep = newline^2 -local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0 -local value = (1-whitespace)^1 / tonumber -local entry = Ct( value * whitespace * value) -local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1) -local series = Ct((set * whitespace^0)^1) +do + + -- experiment: names can change + + local mppath = aux.path + local mpsize = aux.size + + local whitespace = lpegpatterns.whitespace + local newline = lpegpatterns.newline + local setsep = newline^2 + local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0 + local value = (1-whitespace)^1 / tonumber + local entry = Ct( value * whitespace * value) + local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1) + local series = Ct((set * whitespace^0)^1) + + local pattern = whitespace^0 * series -local pattern = whitespace^0 * series + local datasets = { } + mp.datasets = datasets + + function mp.dataset(str) + return lpegmatch(pattern,str) + end + + function datasets.load(tag,filename) + if not filename then + tag, filename = file.basename(tag), tag + end + local data = lpegmatch(pattern,io.loaddata(filename) or "") + datasets[tag] = { + data = data, + line = function(n) mppath(data[n or 1]) end, + size = function() mpsize(data) end, + } + end + + table.setmetatablecall(datasets,function(t,k,f,...) + local d = datasets[k] + local t = type(d) + if t == "table" then + d = d[f] + if type(d) == "function" then + d(...) + else + mpvprint(...) + end + elseif t == "function" then + d(f,...) + end + end) -function mp.dataset(str) - return lpegmatch(pattern,str) end -- \startluacode @@ -314,255 +617,157 @@ end -- endfor ; -- \stopMPpage -local cache, n = { }, 0 -- todo: when > n then reset cache or make weak - -function metapost.runscript(code) - local trace = trace_enabled and trace_luarun - if trace then - report_luarun("code: %s",code) - end - local f - if n > 100 then - cache = nil -- forget about caching - f = loadstring(f_code(code)) - if not f and be_tolerant then - f = loadstring(code) - end - else - f = cache[code] - if not f then - f = loadstring(f_code(code)) - if f then - n = n + 1 - cache[code] = f - elseif be_tolerant then - f = loadstring(code) - if f then - n = n + 1 - cache[code] = f - end - end - end - end - if f then - local result = f() - if result then - local t = type(result) - if t == "number" then - result = f_numeric(result) - elseif t ~= "string" then - result = tostring(result) - end - if trace then - report_luarun("result: %s",result) - end - return result - elseif trace then - report_luarun("no result") - end - else - report_luarun("no result, invalid code: %s",code) - end - return "" -end - --- function metapost.initializescriptrunner(mpx) --- mp.numeric = function(s) return mpx:get_numeric(s) end --- mp.string = function(s) return mpx:get_string (s) end --- mp.boolean = function(s) return mpx:get_boolean(s) end --- mp.number = mp.numeric --- end - -local get_numeric = mplib.get_numeric -local get_string = mplib.get_string -local get_boolean = mplib.get_boolean -local get_number = get_numeric - --- function metapost.initializescriptrunner(mpx) --- mp.numeric = function(s) return get_numeric(mpx,s) end --- mp.string = function(s) return get_string (mpx,s) end --- mp.boolean = function(s) return get_boolean(mpx,s) end --- mp.number = mp.numeric --- end - -local currentmpx = nil - -local get = { } -mp.get = get - -get.numeric = function(s) return get_numeric(currentmpx,s) end -get.string = function(s) return get_string (currentmpx,s) end -get.boolean = function(s) return get_boolean(currentmpx,s) end -get.number = mp.numeric - -function metapost.initializescriptrunner(mpx,trialrun) - currentmpx = mpx - if trace_luarun then - report_luarun("type of run: %s", trialrun and "trial" or "final") - end - -- trace_enabled = not trialrun blocks too much -end - -- texts: -local factor = 65536*(7227/7200) -local textexts = nil -local mptriplet = mp.triplet -local nbdimensions = nodes.boxes.dimensions - -function mp.tt_initialize(tt) - textexts = tt -end +do --- function mp.tt_wd(n) --- local box = textexts and textexts[n] --- mpprint(box and box.width/factor or 0) --- end --- function mp.tt_ht(n) --- local box = textexts and textexts[n] --- mpprint(box and box.height/factor or 0) --- end --- function mp.tt_dp(n) --- local box = textexts and textexts[n] --- mpprint(box and box.depth/factor or 0) --- end - -function mp.tt_dimensions(n) - local box = textexts and textexts[n] - if box then - -- could be made faster with nuts but not critical - mptriplet(box.width/factor,box.height/factor,box.depth/factor) - else - mptriplet(0,0,0) - end -end + local mptriplet = mp.triplet -function mp.tb_dimensions(category,name) - local w, h, d = nbdimensions(category,name) - mptriplet(w/factor,h/factor,d/factor) -end + local bpfactor = number.dimenfactors.bp + local textexts = nil + local mptriplet = mp.triplet + local nbdimensions = nodes.boxes.dimensions -function mp.report(a,b) - if b then - report_message("%s : %s",a,b) - elseif a then - report_message("%s : %s","message",a) + function mp.mf_tt_initialize(tt) + textexts = tt end -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 -local hashes = { } + function mp.mf_tb_dimensions(category,name) + local w, h, d = nbdimensions(category,name) + mptriplet(w*bpfactor,h*bpfactor,d*bpfactor) + end -function mp.newhash() - for i=1,#hashes+1 do - if not hashes[i] then - hashes[i] = { } - mpprint(i) - return + 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("%s : %s","message",a) end end -end -function mp.disposehash(n) - hashes[n] = nil end -function mp.inhash(n,key) - local h = hashes[n] - mpprint(h and h[key] and true or false) -end +do + + local mpprint = aux.print + local modes = tex.modes + local systemmodes = tex.systemmodes -function mp.tohash(n,key) - local h = hashes[n] - if h then - h[key] = true + function mp.mode(s) + mpprint(modes[s] and true or false) end -end -local modes = tex.modes -local systemmodes = tex.systemmodes + function mp.systemmode(s) + mpprint(systemmodes[s] and true or false) + end -function mp.mode(s) - mpprint(modes[s] and true or false) -end + mp.processingmode = mp.mode -function mp.systemmode(s) - mpprint(systemmodes[s] and true or false) end -- for alan's nodes: -function mp.isarray(str) - mpprint(find(str,"%d") and true or false) -end +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 -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 +do -mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint) + local getmacro = tex.getmacro + local getdimen = tex.getdimen + local getcount = tex.getcount + local gettoks = tex.gettoks + local setmacro = tex.setmacro + local setdimen = tex.setdimen + local setcount = tex.setcount + local settoks = tex.settoks --- 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 mpprint = mp.print + local mpquoted = mp.quoted --- 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 + local bpfactor = number.dimenfactors.bp -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 -local mpprint = mp.print -local mpquoted = mp.quoted + local function getmacro(k) mpprint (getmacro(k)) end + local function getdimen(k) mpprint (getdimen(k)*bpfactor) end + local function getcount(k) mpprint (getcount(k)) end + local function gettoks (k) mpquoted(gettoks (k)) end -local factor = number.dimenfactors.bp + local function setmacro(k,v) setmacro(k,v) end + local function setdimen(k,v) setdimen(k,v/bpfactor) end + local function setcount(k,v) setcount(k,v) end + local function settoks (k,v) settoks (k,v) end --- more helpers + -- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix -function mp.getdimen(k) mpprint (getdimen(k)*factor) end -function mp.getcount(k) mpprint (getcount(k)) end -function mp.gettoks (k) mpquoted(gettoks (k)) end -function mp.setdimen(k,v) setdimen(k,v/factor) end -function mp.setcount(k,v) setcount(k,v) end -function mp.settoks (k,v) settoks (k,v) end + mp._get_macro_ = getmacro mp.getmacro = getmacro + mp._get_dimen_ = getdimen mp.getdimen = getdimen + mp._get_count_ = getcount mp.getcount = getcount + mp._get_toks_ = gettoks mp.gettoks = gettoks --- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix + mp._set_macro_ = setmacro mp.setmacro = setmacro + mp._set_dimen_ = setdimen mp.setdimen = setdimen + mp._set_count_ = setcount mp.setcount = setcount + mp._set_toks_ = settoks mp.settoks = settoks -mp._get_dimen_ = mp.getdimen -mp._get_count_ = mp.getcount -mp._get_toks_ = mp.gettoks -mp._set_dimen_ = mp.setdimen -mp._set_count_ = mp.setcount -mp._set_toks_ = mp.settoks +end -- position fun @@ -656,6 +861,21 @@ do 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 + +end + do local mprint = mp.print @@ -674,31 +894,65 @@ end do - local mpvprint = mp.vprint + local mpprint = aux.print + local mpvprint = aux.vprint - local stores = { } + local hashes = { } - function mp.newstore(name) - stores[name] = { } + 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.disposestore(name) - stores[name] = nil + function mp.disposehash(n) + if tonumber(n) then + hashes[n] = false + else + hashes[n] = nil + end end - function mp.tostore(name,key,value) - stores[name][key] = value + function mp.inhash(n,key) + local h = hashes[n] + mpvprint(h and h[key] and true or false) end - function mp.fromstore(name,key) - mpvprint(stores[name][key]) -- type specific + 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 = "getMPstored", + name = "MPfromhash", arguments = "2 strings", actions = function(name,key) - context(stores[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 } @@ -706,11 +960,70 @@ end do - local mpprint = mp.print - local texmodes = tex.modes + -- a bit overkill: just a find(str,"mf_object=") can be enough - function mp.processingmode(s) - mpprint(tostring(texmodes[s])) + 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 + +do + + local mpnumeric = aux.numeric + local mppair = aux.pair + local mpgetpath = get.path + + local p = nil + local n = 0 + + local function mf_path_length(name) + p = mpgetpath(name) + n = p and #p or 0 + mpnumeric(n) + end + + local function mf_path_point(i) + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[1],pi[2]) + end + end + + local function mf_path_left(i) + if i > 0 and i <= n then + local pi = p[i] + mppair(pi[5],pi[6]) + end + end + + local function mf_path_right(i) + 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 + mppair(pn[3],pn[4]) + end + end + + local function mf_path_reset() + p = nil + n = 0 + end + + mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length + mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point + mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left + mp.mf_path_right = mf_path_right mp.pathright = mf_path_right + mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua index 75f810fb33b..92fde5e1369 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua @@ -6,9 +6,8 @@ if not modules then modules = { } end modules ['mlib-pdf'] = { license = "see context related readme files", } --- maybe %s is better than %f - -local format, concat, gsub = string.format, table.concat, string.gsub +local gsub = string.gsub +local concat, insert, remove = table.concat, table.insert, table.remove local abs, sqrt, round = math.abs, math.sqrt, math.round local setmetatable, rawset, tostring, tonumber, type = setmetatable, rawset, tostring, tonumber, type local P, S, C, Ct, Cc, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Carg @@ -41,23 +40,34 @@ local pdfflusher = { } metapost.flushers.pdf = pdfflusher metapost.n = 0 -metapost.optimize = true -- false local experiment = true -- uses context(node) that already does delayed nodes local savedliterals = nil -- needs checking -local mpsliteral = nodes.pool.register(node.new("whatsit",nodes.whatsitcodes.pdfliteral)) -- pdfliteral.mode = 1 - -local f_f = formatters["%F"] - -local f_m = formatters["%F %F m"] -local f_c = formatters["%F %F %F %F %F %F c"] -local f_l = formatters["%F %F l"] -local f_cm = formatters["%F %F %F %F %F %F cm"] -local f_M = formatters["%F M"] +local mpsliteral = nodes.pool.originliteral + +local f_f = formatters["%.6F"] +local f_m = formatters["%.6F %.6F m"] +local f_c = formatters["%.6F %.6F %.6F %.6F %.6F %.6F c"] +local f_l = formatters["%.6F %.6F l"] +local f_cm = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"] +local f_M = formatters["%.6F M"] local f_j = formatters["%i j"] local f_J = formatters["%i J"] -local f_d = formatters["[%s] %F d"] -local f_w = formatters["%F w"] +local f_d = formatters["[%s] %.6F d"] +local f_w = formatters["%.3F w"] + +directives.register("metapost.stripzeros",function() + f_f = formatters["%.6N"] + f_m = formatters["%.6N %.6N m"] + f_c = formatters["%.6N %.6N %.6N %.6N %.6N %.6N c"] + f_l = formatters["%.6N %.6N l"] + f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] + f_M = formatters["%.6N M"] + f_j = formatters["%i j"] + f_J = formatters["%i J"] + f_d = formatters["[%s] %.6N d"] + f_w = formatters["%.3N w"] +end) directives.register("metapost.savetable",function(v) if type(v) == "string" then @@ -73,60 +83,28 @@ trackers.register("metapost.forcestroke",function(v) force_stroke = v end) -local pdfliteral = function(pdfcode) - local literal = copy_node(mpsliteral) - literal.data = pdfcode - return literal -end - -- Because in MKiV we always have two passes, we save the objects. When an extra -- mp run is done (due to for instance texts identifier in the parse pass), we -- get a new result table and the stored objects are forgotten. Otherwise they -- are reused. local function getobjects(result,figure,index) - if metapost.optimize then - local robjects = result.objects - if not robjects then - robjects = { } - result.objects = robjects - end - local fobjects = robjects[index or 1] - if not fobjects then - fobjects = figure:objects() - robjects[index] = fobjects - end - return fobjects - else - return figure:objects() - end + return figure:objects() end -function metapost.convert(result, trialrun, flusher, multipass, askedfig) - if trialrun then - local multipassindeed = metapost.parse(result,askedfig) - if multipass and not multipassindeed and metapost.optimize then - if save_table then - table.save(save_table,metapost.totable(result,1)) -- direct - end - metapost.flush(result,flusher,askedfig) -- saves a run - else - return false - end - else - if save_table then - table.save(save_table,metapost.totable(result,1)) -- direct - end - metapost.flush(result,flusher,askedfig) +function metapost.convert(specification,result) + local flusher = specification.flusher + local askedfig = specification.askedfig + if save_table then + table.save(save_table,metapost.totable(result,1)) -- direct end + metapost.flush(specification,result) return true -- done end function metapost.flushliteral(d) if savedliterals then - local literal = copy_node(mpsliteral) - literal.data = savedliterals[d] - write_node(literal) + write_node(mpsliteral(savedliterals[d])) else report_metapost("problem flushing literal %a",d) end @@ -140,7 +118,7 @@ function pdfflusher.comment(message) if message then message = formatters["%% mps graphic %s: %s"](metapost.n,message) if experiment then - context(pdfliteral(message)) + context(mpsliteral(message)) elseif savedliterals then local last = #savedliterals + 1 savedliterals[last] = message @@ -169,7 +147,7 @@ function pdfflusher.flushfigure(pdfliterals) -- table if #pdfliterals > 0 then pdfliterals = concat(pdfliterals,"\n") if experiment then - context(pdfliteral(pdfliterals)) + context(mpsliteral(pdfliterals)) else if savedliterals then local last = #savedliterals + 1 @@ -320,15 +298,6 @@ local p_boolean = P("false") * Cc(false) + P("true") * Cc(true) local p_set = Ct(number^1) local p_path = Ct(Ct(number * number^-5)^1) --- local variable = --- P("1:") * key * p_number --- + P("2:") * key * p_string --- + P("3:") * key * p_boolean --- + S("4568") * P(":") * key * p_set --- + P("7:") * key * p_path --- --- local pattern_key = Cf ( Carg(1) * (Cg(variable * newline^0)^0), rawset) - local variable = P("1:") * p_number + P("2:") * p_string @@ -374,7 +343,9 @@ function metapost.processspecial(str) end end -local function setproperties(figure) +local stack = { } + +local function pushproperties(figure) local boundingbox = figure:boundingbox() local properties = { llx = boundingbox[1], @@ -388,313 +359,321 @@ local function setproperties(figure) italic = figure:italcorr(), number = figure:charcode() or 0, } + insert(stack,properties) metapost.properties = properties return properties end +local function popproperties() + metapost.properties = remove(stack) +end + local function nocomment() end metapost.comment = nocomment -function metapost.flush(result,flusher,askedfig) +function metapost.flush(specification,result) if result then - local figures = result.fig + local flusher = specification.flusher + local askedfig = specification.askedfig + local incontext = specification.incontext + local figures = result.fig if figures then flusher = flusher or pdfflusher - local resetplugins = metapost.resetplugins or ignore -- before figure - local processplugins = metapost.processplugins or ignore -- each object + local resetplugins = metapost.resetplugins or ignore -- before figure + local processplugins = metapost.processplugins or ignore -- each object local synchronizeplugins = metapost.synchronizeplugins or ignore - local pluginactions = metapost.pluginactions or ignore -- before / after - local startfigure = flusher.startfigure - local stopfigure = flusher.stopfigure - local flushfigure = flusher.flushfigure - local textfigure = flusher.textfigure - local processspecial = flusher.processspecial or metapost.processspecial - metapost.comment = flusher.comment or nocomment + local pluginactions = metapost.pluginactions or ignore -- before / after + local startfigure = flusher.startfigure + local stopfigure = flusher.stopfigure + local flushfigure = flusher.flushfigure + local textfigure = flusher.textfigure + local processspecial = flusher.processspecial or metapost.processspecial + metapost.comment = flusher.comment or nocomment for index=1,#figures do - local figure = figures[index] - local properties = setproperties(figure) + local figure = figures[index] + local properties = pushproperties(figure) if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then - local objects = getobjects(result,figure,index) - local result = { } - local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false - local llx = properties.llx - local lly = properties.lly - local urx = properties.urx - local ury = properties.ury + local objects = getobjects(result,figure,index) + local result = { } + local miterlimit = -1 + local linecap = -1 + local linejoin = -1 + local dashed = false + local llx = properties.llx + local lly = properties.lly + local urx = properties.urx + local ury = properties.ury if urx < llx then -- invalid startfigure(properties.number,0,0,0,0,"invalid",figure) stopfigure() else - startfigure(properties.number,llx,lly,urx,ury,"begin",figure) - result[#result+1] = "q" - if objects then - resetplugins(result) -- we should move the colorinitializer here - local savedpath = nil - local savedhtap = nil - for o=1,#objects do - local object = objects[o] - local objecttype = object.type - if objecttype == "text" then - result[#result+1] = "q" - local ot = object.transform -- 3,4,5,6,1,2 - result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: formatters["%F %F m %F %F %F %F 0 0 cm"](unpack(ot)) - flushfigure(result) -- flush accumulated literals - result = { } - textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) - result[#result+1] = "Q" - elseif objecttype == "special" then - if processspecial then - processspecial(object.prescript) - end - elseif objecttype == "start_clip" then - local evenodd = not object.istext and object.postscript == "evenodd" - result[#result+1] = "q" - flushnormalpath(object.path,result,false) - result[#result+1] = evenodd and "W* n" or "W n" - elseif objecttype == "stop_clip" then - result[#result+1] = "Q" - miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false - elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then - -- skip - else - -- we use an indirect table as we want to overload - -- entries but this is not possible in userdata - -- - -- can be optimized if no path - -- - local original = object - local object = { } - setmetatable(object, { - __index = original - }) - -- first we analyze - local before, after = processplugins(object) - local evenodd, collect, both = false, false, false - local postscript = object.postscript - if not object.istext then - if postscript == "evenodd" then - evenodd = true - elseif postscript == "collect" then - collect = true - elseif postscript == "both" then - both = true - elseif postscript == "eoboth" then - evenodd = true - both = true - end - end - -- - if collect then - if not savedpath then - savedpath = { object.path or false } - savedhtap = { object.htap or false } - else - savedpath[#savedpath+1] = object.path or false - savedhtap[#savedhtap+1] = object.htap or false + + -- we need to be indirect if we want the one-pass solution + + local function processfigure() + result[#result+1] = "q" + if objects then + -- resetplugins(result) -- we should move the colorinitializer here + local savedpath = nil + local savedhtap = nil + for o=1,#objects do + local object = objects[o] + local objecttype = object.type + if objecttype == "text" then + result[#result+1] = "q" + local ot = object.transform -- 3,4,5,6,1,2 + result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) + flushfigure(result) -- flush accumulated literals + result = { } + textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) + result[#result+1] = "Q" + elseif objecttype == "special" then + if processspecial then + processspecial(object.prescript) end + elseif objecttype == "start_clip" then + local evenodd = not object.istext and object.postscript == "evenodd" + result[#result+1] = "q" + flushnormalpath(object.path,result,false) + result[#result+1] = evenodd and "W* n" or "W n" + elseif objecttype == "stop_clip" then + result[#result+1] = "Q" + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false + elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then + -- skip else - local objecttype = object.type -- can have changed - if before then - result = pluginactions(before,result,flushfigure) - end - local ml = object.miterlimit - if ml and ml ~= miterlimit then - miterlimit = ml - result[#result+1] = f_M(ml) - end - local lj = object.linejoin - if lj and lj ~= linejoin then - linejoin = lj - result[#result+1] = f_j(lj) - end - local lc = object.linecap - if lc and lc ~= linecap then - linecap = lc - result[#result+1] = f_J(lc) + -- we use an indirect table as we want to overload + -- entries but this is not possible in userdata + -- + -- can be optimized if no path + -- + local original = object + local object = { } + setmetatable(object, { + __index = original + }) + local before, + after = processplugins(object) + local evenodd = false + local collect = false + local both = false + local postscript = object.postscript + if not object.istext then + if postscript == "evenodd" then + evenodd = true + elseif postscript == "collect" then + collect = true + elseif postscript == "both" then + both = true + elseif postscript == "eoboth" then + evenodd = true + both = true + end end - if both then - if dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false + -- + if collect then + if not savedpath then + savedpath = { object.path or false } + savedhtap = { object.htap or false } + else + savedpath[#savedpath+1] = object.path or false + savedhtap[#savedhtap+1] = object.htap or false end else - local dl = object.dash - if dl then - local d = f_d(concat(dl.dashes or {}," "),dl.offset) - if d ~= dashed then - dashed = d - result[#result+1] = d - end - elseif dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false + local objecttype = object.type -- can have changed + if before then + result = pluginactions(before,result,flushfigure) end - end - local path = object.path -- newpath - local transformed, penwidth = false, 1 - local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point" - local pen = object.pen - if pen then - if pen.type == 'elliptical' then - transformed, penwidth = pen_characteristics(original) -- boolean, value - result[#result+1] = f_w(penwidth) -- todo: only if changed - if objecttype == 'fill' then - objecttype = 'both' + local ml = object.miterlimit + if ml and ml ~= miterlimit then + miterlimit = ml + result[#result+1] = f_M(ml) + end + local lj = object.linejoin + if lj and lj ~= linejoin then + linejoin = lj + result[#result+1] = f_j(lj) + end + local lc = object.linecap + if lc and lc ~= linecap then + linecap = lc + result[#result+1] = f_J(lc) + end + if both then + if dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" + dashed = false end - else -- calculated by mplib itself - objecttype = 'fill' - end - end - if transformed then - result[#result+1] = "q" - end - if path then - if savedpath then - for i=1,#savedpath do - local path = savedpath[i] - if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) + else + local dl = object.dash + if dl then + local d = f_d(concat(dl.dashes or {}," "),dl.offset) + if d ~= dashed then + dashed = d + result[#result+1] = d end + elseif dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" + dashed = false end - savedpath = nil end - if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) - end - if force_stroke then - result[#result+1] = open and "S" or "h S" - elseif objecttype == "fill" then - result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo - elseif objecttype == "outline" then - if both then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo - else - result[#result+1] = open and "S" or "h S" - end - elseif objecttype == "both" then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath + local path = object.path -- newpath + local transformed = false + local penwidth = 1 + local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point" + local pen = object.pen + if pen then + if pen.type == "elliptical" then + transformed, penwidth = pen_characteristics(original) -- boolean, value + result[#result+1] = f_w(penwidth) -- todo: only if changed + if objecttype == "fill" then + objecttype = "both" + end + else -- calculated by mplib itself + objecttype = "fill" + end end - end - if transformed then - result[#result+1] = "Q" - end - local path = object.htap - if path then if transformed then result[#result+1] = "q" end - if savedhtap then - for i=1,#savedhtap do - local path = savedhtap[i] - if transformed then - flushconcatpath(path,result,open) + if path then + if savedpath then + for i=1,#savedpath do + local path = savedpath[i] + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) + end + end + savedpath = nil + end + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) + end + if force_stroke then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "fill" then + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo + elseif objecttype == "outline" then + if both then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo else - flushnormalpath(path,result,open) + result[#result+1] = open and "S" or "h S" end + elseif objecttype == "both" then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath end - savedhtap = nil - evenodd = true end if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) + result[#result+1] = "Q" end - if force_stroke then - result[#result+1] = open and "S" or "h S" - elseif objecttype == "fill" then - result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo - elseif objecttype == "outline" then - result[#result+1] = open and "S" or "h S" - elseif objecttype == "both" then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath + local path = object.htap + if path then + if transformed then + result[#result+1] = "q" + end + if savedhtap then + for i=1,#savedhtap do + local path = savedhtap[i] + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) + end + end + savedhtap = nil + evenodd = true + end + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) + end + if force_stroke then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "fill" then + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo + elseif objecttype == "outline" then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "both" then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath + end + if transformed then + result[#result+1] = "Q" + end end - if transformed then - result[#result+1] = "Q" + if after then + result = pluginactions(after,result,flushfigure) end end - if after then - result = pluginactions(after,result,flushfigure) + if object.grouped then + -- can be qQ'd so changes can end up in groups + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false end end - if object.grouped then - -- can be qQ'd so changes can end up in groups - miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false - end end end + result[#result+1] = "Q" + flushfigure(result) + end + startfigure(properties.number,llx,lly,urx,ury,"begin",figure) + if incontext then + context(function() processfigure() end) + else + processfigure() end - result[#result+1] = "Q" - flushfigure(result) stopfigure("end") + end if askedfig ~= "all" then break end end + popproperties() end metapost.comment = nocomment + resetplugins(result) -- we should move the colorinitializer here end end end -function metapost.parse(result,askedfig) - if result then - local figures = result.fig - if figures then - local multipass = false - local analyzeplugins = metapost.analyzeplugins -- each object - for index=1,#figures do - local figure = figures[index] - local properties = setproperties(figure) - if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then - local objects = getobjects(result,figure,index) - if objects then - for o=1,#objects do - if analyzeplugins(objects[o]) then - multipass = true - end - end - end - if askedfig ~= "all" then - break - end - end +-- tracing: + +do + + local result = { } + + local flusher = { + startfigure = function() + result = { } + context.startnointerference() + end, + flushfigure = function(literals) + local n = #result + for i=1,#literals do + result[n+i] = literals[i] end - return multipass + end, + stopfigure = function() + context.stopnointerference() end - end -end + } --- tracing: + local specification = { + flusher = flusher, + -- incontext = true, + } -local result = { } - -local flusher = { - startfigure = function() - result = { } - context.startnointerference() - end, - flushfigure = function(literals) - local n = #result - for i=1,#literals do - result[n+i] = literals[i] - end - end, - stopfigure = function() - context.stopnointerference() + function metapost.pdfliterals(result) + metapost.flush(specification,result) + return result end -} -function metapost.pdfliterals(result) - metapost.flush(result,flusher) - return result end function metapost.totable(result,askedfig) @@ -702,7 +681,6 @@ function metapost.totable(result,askedfig) local figure = result and result.fig and result.fig[1] if figure then local results = { } - -- local objects = figure:objects() local objects = getobjects(result,figure,askedfig) for o=1,#objects do local object = objects[o] diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv index 147b67f743c..6dc73a15352 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.mkiv @@ -47,6 +47,18 @@ \global\MPurx \zeropoint \global\MPury \zeropoint} +\let\popMPboundingbox\relax + +\unexpanded\def\pushMPboundingbox + {\edef\popMPboundingbox + {\global\MPwidth \the\MPwidth + \global\MPheight\the\MPheight + \global\MPllx \the\MPllx + \global\MPlly \the\MPlly + \global\MPurx \the\MPurx + \global\MPury \the\MPury + \relax}} + \unexpanded\def\repositionMPboxindeed {\setbox\MPbox\hpack\bgroup \kern-\MPllx @@ -76,15 +88,15 @@ \wd\MPbox\MPwidth \ht\MPbox\MPheight} -\unexpanded\def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps) - {\begingroup - \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}% text - \MPllx-#4\onebasepoint - \MPlly-#5\onebasepoint - \repositionMPbox - \smashbox\MPbox - \box\MPbox - \endgroup} +% \unexpanded\def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps) +% {\begingroup +% \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}% text +% \MPllx-#4\onebasepoint +% \MPlly-#5\onebasepoint +% \repositionMPbox +% \smashbox\MPbox +% \box\MPbox +% \endgroup} % MPLIB specific: diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua index bb5ce31e5e5..5708577fea6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.lua @@ -6,8 +6,8 @@ if not modules then modules = { } end modules ['mlib-pps'] = { license = "see context related readme files", } -local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split -local tonumber, type, unpack, next = tonumber, type, unpack, next +local format, gmatch, match, split, gsub = string.format, string.gmatch, string.match, string.split, string.gsub +local tonumber, type, unpack, next, select = tonumber, type, unpack, next, select local round, sqrt, min, max = math.round, math.sqrt, math.min, math.max local insert, remove, concat = table.insert, table.remove, table.concat local Cs, Cf, C, Cg, Ct, P, S, V, Carg = lpeg.Cs, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V, lpeg.Carg @@ -23,7 +23,6 @@ local context = context local implement = interfaces.implement local setmacro = interfaces.setmacro ------ texgetbox = tex.getbox local texsetbox = tex.setbox local textakebox = tex.takebox -- or: nodes.takebox local copy_list = node.copy_list @@ -37,6 +36,7 @@ local stoptiming = statistics.stoptiming local trace_runs = false trackers.register("metapost.runs", function(v) trace_runs = v end) local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end) local trace_scripts = false trackers.register("metapost.scripts", function(v) trace_scripts = v end) +local trace_btexetex = false trackers.register("metapost.btexetex", function(v) trace_btexetex = v end) local report_metapost = logs.reporter("metapost") local report_textexts = logs.reporter("metapost","textexts") @@ -57,9 +57,6 @@ local cmyktorgb = colors.cmyktorgb -- or function() return 0,0,0 e local rgbtogray = colors.rgbtogray -- or function() return 0 end local cmyktogray = colors.cmyktogray -- or function() return 0 end -metapost.makempy = metapost.makempy or { nofconverted = 0 } -local makempy = metapost.makempy - local nooutercolor = "0 g 0 G" local nooutertransparency = "/Tr0 gs" -- only when set local outercolormode = 0 @@ -97,14 +94,25 @@ end local f_f = formatters["%F"] local f_f3 = formatters["%.3F"] - local f_gray = formatters["%.3F g %.3F G"] local f_rgb = formatters["%.3F %.3F %.3F rg %.3F %.3F %.3F RG"] local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"] -local f_cm = formatters["q %F %F %F %F %F %F cm"] -local f_shade = formatters["MpSh%s"] +local f_cm_b = formatters["q %.6F %.6F %.6F %.6F %.6F %.6F cm"] +local f_scn = formatters["%.3F"] +local f_shade = formatters["MpSh%s"] local f_spot = formatters["/%s cs /%s CS %s SCN %s scn"] +local s_cm_e = "Q" + +directives.register("metapost.stripzeros",function() + f_f = formatters["%N"] + f_f3 = formatters["%.3N"] + f_gray = formatters["%.3N g %.3N G"] + f_rgb = formatters["%.3N %.3N %.3N rg %.3N %.3N %.3N RG"] + f_cmyk = formatters["%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K"] + f_cm_b = formatters["q %.6N %.6N %.6N %.6N %.6N %.6N cm"] + f_scn = formatters["%.3N"] +end) local function checked_color_pair(color,...) if not color then @@ -194,7 +202,8 @@ local function checkandconvert(ca,cb,model) ca = { cmyktorgb(ca[1],ca[2],ca[3],ca[4]) } cb = { cmyktorgb(cb[1],cb[2],cb[3],cb[4]) } elseif #ca == 1 then - local a, b = 1-ca[1], 1-cb[1] + local a = 1 - ca[1] + local b = 1 - cb[1] ca = { a, a, a } cb = { b, b, b } end @@ -244,16 +253,18 @@ local function preset(t,k) return v end -local function startjob(plugmode) +local function startjob(plugmode,kind) + insert(stack,top) top = { - textexts = { }, -- all boxes, optionally with a different color - texlast = 0, - texdata = setmetatableindex({},preset), -- references to textexts in order or usage - plugmode = plugmode, -- some day we can then skip all pre/postscripts + textexts = { }, -- all boxes, optionally with a different color + texstrings = { }, + texlast = 0, + texdata = setmetatableindex({},preset), -- references to textexts in order or usage + plugmode = plugmode, -- some day we can then skip all pre/postscripts } - insert(stack,top) if trace_runs then - report_metapost("starting run at level %i",#stack) + report_metapost("starting %s run at level %i in %s mode", + kind,#stack+1,plugmode and "plug" or "normal") end return top end @@ -261,16 +272,17 @@ end local function stopjob() if top then for slot, content in next, top.textexts do - flush_list(content) - if trace_textexts then - report_textexts("freeing text %s",slot) + if content then + flush_list(content) + if trace_textexts then + report_textexts("freeing text %s",slot) + end end end if trace_runs then - report_metapost("stopping run at level %i",#stack) + report_metapost("stopping run at level %i",#stack+1) end - remove(stack) - top = stack[#stack] + top = remove(stack) return top end end @@ -281,7 +293,7 @@ end -- end of new -local function settext(box,slot) +local settext = function(box,slot,str) if top then -- if trace_textexts then -- report_textexts("getting text %s from box %s",slot,box) @@ -290,10 +302,10 @@ local function settext(box,slot) end end -local function gettext(box,slot) +local gettext = function(box,slot) if top then - -- maybe check how often referenced - texsetbox(box,copy_list(top.textexts[slot])) + texsetbox(box,top.textexts[slot]) + top.textexts[slot] = false -- if trace_textexts then -- report_textexts("putting text %s in box %s",slot,box) -- end @@ -323,14 +335,19 @@ function models.all(cr) local s = cr[1] return checked_color_pair(f_gray,s,s) elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] + local r = cr[1] + local g = cr[2] + local b = cr[3] if r == g and g == b then return checked_color_pair(f_gray,r,r) else return checked_color_pair(f_rgb,r,g,b,r,g,b) end else - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + local c = cr[1] + local m = cr[2] + local y = cr[3] + local k = cr[4] if c == m and m == y and y == 0 then k = 1 - k return checked_color_pair(f_gray,k,k) @@ -342,10 +359,15 @@ function models.all(cr) local s = cr[1] return checked_color_pair(f_gray,s,s) elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] + local r = cr[1] + local g = cr[2] + local b = cr[3] return checked_color_pair(f_rgb,r,g,b,r,g,b) else - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + local c = cr[1] + local m = cr[2] + local y = cr[3] + local k = cr[4] return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k) end end @@ -359,14 +381,19 @@ function models.rgb(cr) local s = cr[1] checked_color_pair(f_gray,s,s) elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] + local r = cr[1] + local g = cr[2] + local b = cr[3] if r == g and g == b then return checked_color_pair(f_gray,r,r) else return checked_color_pair(f_rgb,r,g,b,r,g,b) end else - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + local c = cr[1] + local m = cr[2] + local y = cr[3] + local k = cr[4] if c == m and m == y and y == 0 then k = 1 - k return checked_color_pair(f_gray,k,k) @@ -379,11 +406,12 @@ function models.rgb(cr) local s = cr[1] return checked_color_pair(f_gray,s,s) else + local r = cr[1] + local g = cr[2] + local b = cr[3] local r, g, b if n == 3 then - r, g, b = cmyktorgb(cr[1],cr[2],cr[3],cr[4]) - else - r, g, b = cr[1], cr[2], cr[3] + r, g, b = cmyktorgb(r,g,b,cr[4]) end return checked_color_pair(f_rgb,r,g,b,r,g,b) end @@ -398,7 +426,9 @@ function models.cmyk(cr) local s = cr[1] return checked_color_pair(f_gray,s,s) elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] + local r = cr[1] + local g = cr[2] + local b = cr[3] if r == g and g == b then return checked_color_pair(f_gray,r,r) else @@ -406,7 +436,10 @@ function models.cmyk(cr) return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k) end else - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + local c = cr[1] + local m = cr[2] + local y = cr[3] + local k = cr[4] if c == m and m == y and y == 0 then k = k - 1 return checked_color_pair(f_gray,k,k) @@ -418,18 +451,20 @@ function models.cmyk(cr) local s = cr[1] return checked_color_pair(f_gray,s,s) else - local c, m, y, k + local c = cr[1] + local m = cr[2] + local y = cr[3] + local k = cr[4] if n == 3 then - c, m, y, k = rgbtocmyk(cr[1],cr[2],cr[3]) - else - c, m, y, k = cr[1], cr[2], cr[3], cr[4] + c, m, y, k = rgbtocmyk(c,m,y) end return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k) end end function models.gray(cr) - local n, s = #cr, 0 + local n = #cr + local s = 0 if n == 0 then return checked_color_pair() elseif n == 4 then @@ -454,76 +489,9 @@ setmetatableindex(models, function(t,k) end) local function colorconverter(cs) - -- return models[colors.currentmodel()](cs) return models[outercolormodel](cs) end -local btex = P("btex") -local etex = P(" etex") -local vtex = P("verbatimtex") -local ttex = P("textext") -local gtex = P("graphictext") -local multipass = P("forcemultipass") -local spacing = S(" \n\r\t\v")^0 -local dquote = P('"') - -local found, forced = false, false - -local function convert(str) - found = true - return "rawtextext(\"" .. str .. "\")" -- centered -end -local function ditto(str) - return "\" & ditto & \"" -end -local function register() - found = true -end -local function force() - forced = true -end - -local texmess = (dquote/ditto + (1 - etex))^0 - -local function ignore(s) - report_metapost("ignoring verbatim tex: %s",s) - return "" -end - --- local parser = P { --- [1] = Cs((V(2)/register + V(4)/ignore + V(3)/convert + V(5)/force + 1)^0), --- [2] = ttex + gtex, --- [3] = btex * spacing * Cs(texmess) * etex, --- [4] = vtex * spacing * Cs(texmess) * etex, --- [5] = multipass, -- experimental, only for testing --- } - --- currently a a one-liner produces less code - --- textext.*(".*") can have "'s but tricky parsing as we can have concatenated strings --- so this is something for a boring plane or train trip and we might assume proper mp --- input anyway - -local parser = Cs(( - (ttex + gtex)/register - + (btex * spacing * Cs(texmess) * etex)/convert - + (vtex * spacing * Cs(texmess) * etex)/ignore - + 1 -)^0) - -local checking_enabled = false directives.register("metapost.checktexts",function(v) checking_enabled = v end) - -local function checktexts(str) - if checking_enabled then - found, forced = false, false - return lpegmatch(parser,str), found, forced - else - return str - end -end - -metapost.checktexts = checktexts - local factor = 65536*(7227/7200) implement { @@ -541,42 +509,15 @@ local function sxsy(wd,ht,dp) -- helper for text return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0 end +metapost.sxsy = sxsy + -- for stock mp we need to declare the booleans first -local no_first_run = "boolean mfun_first_run ; mfun_first_run := false ;" -local do_first_run = "boolean mfun_first_run ; mfun_first_run := true ;" -local no_trial_run = "boolean mfun_trial_run ; mfun_trial_run := false ;" -local do_trial_run = "boolean mfun_trial_run ; mfun_trial_run := true ;" local do_begin_fig = "; beginfig(1) ; " local do_end_fig = "; endfig ;" local do_safeguard = ";" --- local f_text_data = formatters["mfun_tt_w[%i] := %f ; mfun_tt_h[%i] := %f ; mfun_tt_d[%i] := %f ;"] --- --- function metapost.textextsdata() --- local textexts = top.textexts --- local collected = { } --- local nofcollected = 0 --- for k, data in sortedhash(top.texdata) do -- sort is nicer in trace --- local texorder = data.texorder --- for n=1,#texorder do --- local box = textexts[texorder[n]] --- if box then --- local wd, ht, dp = box.width/factor, box.height/factor, box.depth/factor --- if trace_textexts then --- report_textexts("passed data item %s:%s > (%p,%p,%p)",k,n,wd,ht,dp) --- end --- nofcollected = nofcollected + 1 --- collected[nofcollected] = f_text_data(n,wd,n,ht,n,dp) --- else --- break --- end --- end --- end --- return collected --- end - -function metapost.textextsdata() +function metapost.preparetextextsdata() local textexts = top.textexts local collected = { } for k, data in sortedhash(top.texdata) do -- sort is nicer in trace @@ -590,18 +531,10 @@ function metapost.textextsdata() end end end - mp.tt_initialize(collected) + mp.mf_tt_initialize(collected) end - -metapost.intermediate = metapost.intermediate or { } -metapost.intermediate.actions = metapost.intermediate.actions or { } - -metapost.method = 1 -- 1:dumb 2:clever - --- maybe we can latelua the texts some day - -local processmetapost = metapost.process +local runmetapost = metapost.run local function checkaskedfig(askedfig) -- return askedfig, wrappit if not askedfig then @@ -624,231 +557,98 @@ local function extrapass() if trace_runs then report_metapost("second run of job %s, asked figure %a",top.nofruns,top.askedfig) end - local textexts = metapost.textextsdata() - processmetapost(top.mpx, { - top.wrappit and do_begin_fig or "", - no_trial_run, - textexts and concat(textexts," ;\n") or "", - top.initializations, - do_safeguard, - top.data, - top.wrappit and do_end_fig or "", - }, false, nil, false, true, top.askedfig) + metapost.preparetextextsdata() + runmetapost { + mpx = top.mpx, + askedfig = top.askedfig, + incontext = true, + data = { + top.wrappit and do_begin_fig or "", + no_trial_run, + top.initializations, + do_safeguard, + top.data, + top.wrappit and do_end_fig or "", + }, + } end -function metapost.graphic_base_pass(specification) -- name will change (see mlib-ctx.lua) - local top = startjob(true) - -- +-- This one is called from the \TEX\ end so the specification is different +-- from the specification to metapost,run cum suis! The definitions and +-- extension used to be handled here but are now delegated to the format +-- initializers because we need to accumulate them for nested instances (a +-- side effect of going single pass). + +function metapost.graphic_base_pass(specification) + local top = startjob(true,"base") local mpx = specification.mpx -- mandate local data = specification.data or "" - local definitions = specification.definitions or "" - -- local extensions = metapost.getextensions(specification.instance,specification.useextensions) - local extensions = specification.extensions or "" local inclusions = specification.inclusions or "" local initializations = specification.initializations or "" - local askedfig = specification.figure -- no default else no wrapper + local askedfig, + wrappit = checkaskedfig(specification.figure) + nofruns = nofruns + 1 + top.askedfig = askedfig + top.wrappit = wrappit + top.nofruns = nofruns metapost.namespace = specification.namespace or "" - -- - local askedfig, wrappit = checkaskedfig(askedfig) - -- - nofruns = nofruns + 1 - -- - top.askedfig = askedfig - top.wrappit = wrappit - top.nofruns = nofruns - -- - local done_1, done_2, done_3, forced_1, forced_2, forced_3 - if checking_enabled then - data, done_1, forced_1 = checktexts(data) - if extensions == "" then - extensions, done_2, forced_2 = "", false, false - else - extensions, done_2, forced_2 = checktexts(extensions) - end - if inclusions == "" then - inclusions, done_3, forced_3 = "", false, false - else - inclusions, done_3, forced_3 = checktexts(inclusions) - end - end - top.intermediate = false - top.multipass = false -- no needed here - top.mpx = mpx - top.data = data - top.initializations = initializations - local method = metapost.method + top.mpx = mpx + top.data = data + top.initializations = initializations if trace_runs then - if method == 1 then - report_metapost("forcing two runs due to library configuration") - elseif method ~= 2 then - report_metapost("ignoring run due to library configuration") - elseif not (done_1 or done_2 or done_3) then - report_metapost("forcing one run only due to analysis") - elseif done_1 then - report_metapost("forcing at max two runs due to main code") - elseif done_2 then - report_metapost("forcing at max two runs due to extensions") - else - report_metapost("forcing at max two runs due to inclusions") - end + report_metapost("running job %s, asked figure %a",nofruns,askedfig) end - if method == 1 or (method == 2 and (done_1 or done_2 or done_3)) then - if trace_runs then - report_metapost("first run of job %s, asked figure %a",nofruns,askedfig) - end - -- first true means: trialrun, second true means: avoid extra run if no multipass - local flushed = processmetapost(mpx, { - definitions, - extensions, - inclusions, - wrappit and do_begin_fig or "", - do_first_run, - do_trial_run, - initializations, - do_safeguard, - data, - wrappit and do_end_fig or "", - }, true, nil, not (forced_1 or forced_2 or forced_3), false, askedfig) - if top.intermediate then - for _, action in next, metapost.intermediate.actions do - action() - end - end - if not flushed or not metapost.optimize then - -- tricky, we can only ask once for objects and therefore - -- we really need a second run when not optimized - -- context.MPLIBextrapass(askedfig) - context(extrapass) - end - else - if trace_runs then - report_metapost("running job %s, asked figure %a",nofruns,askedfig) - end - processmetapost(mpx, { - definitions, - extensions, + runmetapost { + mpx = mpx, + askedfig = askedfig, + incontext = true, + data = { inclusions, wrappit and do_begin_fig or "", - do_first_run, - no_trial_run, initializations, do_safeguard, data, wrappit and do_end_fig or "", - }, false, nil, false, false, askedfig) - end + }, + } context(stopjob) end --- we overload metapost.process here - -function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig, plugmode) -- overloads - startjob(plugmode) - processmetapost(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig) - stopjob() -end - -local start = [[\starttext]] -local preamble = [[\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]] -local stop = [[\stoptext]] - -local mpyfilename = nil - -function makempy.registerfile(filename) - mpyfilename = filename +local function oldschool(mpx, data, trial_run, flusher, was_multi_pass, is_extra_pass, askedfig, incontext) + metapost.process { + mpx = mpx, + flusher = flusher, + askedfig = askedfig, + useplugins = incontext, + incontext = incontext, + data = data, + } end -implement { - name = "registermpyfile", - actions = makempy.registerfile, - arguments = "string" -} - -local pdftompy = sandbox.registerrunner { - name = "mpy:pstoedit", - program = "pstoedit", - template = "-ssp -dt -f mpost %pdffile% %mpyfile%", - checkers = { - pdffile = "writable", - mpyfile = "readable", - }, - reporter = report_metapost, -} - -local textopdf = sandbox.registerrunner { - name = "mpy:context", - program = "context", - template = "--once %runmode% %texfile%", - checkers = { - runmode = "string", - texfile = "readable", - }, - reporter = report_metapost, -} - -function makempy.processgraphics(graphics) - if #graphics == 0 then - return - end - if mpyfilename and exists(mpyfilename) then - report_metapost("using file: %s",mpyfilename) - return - end - makempy.nofconverted = makempy.nofconverted + 1 - starttiming(makempy) - local mpofile = tex.jobname .. "-mpgraph" - local mpyfile = file.replacesuffix(mpofile,"mpy") - local pdffile = file.replacesuffix(mpofile,"pdf") - local texfile = file.replacesuffix(mpofile,"tex") - savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n") - textopdf { - runmode = tex.interactionmode == 0 and "--batchmode" or "", - texfile = texfile, - } - if exists(pdffile) then - pdftompy { - pdffile = pdffile, - mpyfile = mpyfile, - } - if exists(mpyfile) then - local result, r = { }, 0 - local data = io.loaddata(mpyfile) - if data and #data > 0 then - for figure in gmatch(data,"beginfig(.-)endfig") do - r = r + 1 - result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure) - end - savedata(mpyfile,concat(result,"")) - end - end +function metapost.process(specification,...) + if type(specification) ~= "table" then + oldschool(specification,...) + else + startjob(specification.incontext or specification.useplugins,"process") + runmetapost(specification) + stopjob() end - stoptiming(makempy) end -- -- the new plugin handler -- -- -local sequencers = utilities.sequencers -local appendgroup = sequencers.appendgroup -local appendaction = sequencers.appendaction +local sequencers = utilities.sequencers +local appendgroup = sequencers.appendgroup +local appendaction = sequencers.appendaction -local resetter = nil -local analyzer = nil -local processor = nil - -local resetteractions = sequencers.new { arguments = "t" } -local analyzeractions = sequencers.new { arguments = "object,prescript" } -local processoractions = sequencers.new { arguments = "object,prescript,before,after" } +local resetteractions = sequencers.new { arguments = "t" } +local processoractions = sequencers.new { arguments = "object,prescript,before,after" } appendgroup(resetteractions, "system") -appendgroup(analyzeractions, "system") appendgroup(processoractions,"system") -- later entries come first ---~ local scriptsplitter = Cf(Ct("") * ( ---~ Cg(C((1-S("= "))^1) * S("= ")^1 * C((1-S("\n\r"))^0) * S("\n\r")^0) ---~ )^0, rawset) - local scriptsplitter = Ct ( Ct ( C((1-S("= "))^1) * S("= ")^1 * C((1-S("\n\r"))^0) * S("\n\r")^0 )^0 ) @@ -857,22 +657,24 @@ local function splitprescript(script) local hash = lpegmatch(scriptsplitter,script) for i=#hash,1,-1 do local h = hash[i] -if h == "reset" then - for k, v in next, hash do - if type(k) ~= "number" then - hash[k] = nil + if h == "reset" then + for k, v in next, hash do + if type(k) ~= "number" then + hash[k] = nil + end + end + else + hash[h[1]] = h[2] end end -else - hash[h[1]] = h[2] -end - end if trace_scripts then report_scripts(table.serialize(hash,"prescript")) end return hash end +metapost.splitprescript = splitprescript + -- -- not used: -- -- local function splitpostscript(script) @@ -906,27 +708,9 @@ end function metapost.resetplugins(t) -- intialize plugins, before figure if top.plugmode then - outercolormodel = colors.currentmodel() -- currently overloads the one set at the tex end - - -- plugins can have been added - resetter = resetteractions.runner - analyzer = analyzeractions.runner - processor = processoractions.runner - -- let's apply one runner - resetter(t) - end -end - -function metapost.analyzeplugins(object) -- each object (first pass) - if top.plugmode then - local prescript = object.prescript -- specifications - if prescript and #prescript > 0 then - analyzer(object,splitprescript(prescript) or {}) - return top.multipass - end + resetteractions.runner(t) end - return false end function metapost.processplugins(object) -- each object (second pass) @@ -935,7 +719,7 @@ function metapost.processplugins(object) -- each object (second pass) if prescript and #prescript > 0 then local before = { } local after = { } - processor(object,splitprescript(prescript) or {},before,after) + processoractions.runner(object,splitprescript(prescript) or {},before,after) return #before > 0 and before, #after > 0 and after else local c = object.color @@ -954,11 +738,16 @@ local basepoints = number.dimenfactors["bp"] local function cm(object) local op = object.path if op then - local first, second, fourth = op[1], op[2], op[4] + local first = op[1] + local second = op[2] + local fourth = op[4] if fourth then - local tx, ty = first.x_coord , first.y_coord - local sx, sy = second.x_coord - tx, fourth.y_coord - ty - local rx, ry = second.y_coord - ty, fourth.x_coord - tx + local tx = first.x_coord + local ty = first.y_coord + local sx = second.x_coord - tx + local sy = fourth.y_coord - ty + local rx = second.y_coord - ty + local ry = fourth.x_coord - tx if sx == 0 then sx = 0.00001 end if sy == 0 then sy = 0.00001 end return sx, rx, ry, sy, tx, ty @@ -967,6 +756,8 @@ local function cm(object) return 1, 0, 0, 1, 0, 0 -- weird case end +metapost.cm = cm + -- color local function cl_reset(t) @@ -975,157 +766,195 @@ end -- text -local function tx_reset() - if top then - -- why ? - top.texhash = { } - top.texlast = 0 +local tx_reset, tx_process do + + local eol = S("\n\r")^1 + local cleaner = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0) + local splitter = Ct( + ( ( + P("s:") * C((1-eol)^1) + + P("n:") * ((1-eol)^1/tonumber) + + P("b:") * ((1-eol)^1/toboolean) + ) * eol^0 )^0) + + local function applyformat(s) + local t = lpegmatch(splitter,s) + if #t == 1 then + return s + else + local f = lpegmatch(cleaner,t[1]) + return formatters[f](unpack(t,2)) + end end -end -local fmt = formatters["%s %s %s % t"] ------ pat = tsplitat(":") -local pat = lpeg.tsplitter(":",tonumber) -- so that %F can do its work - -local f_gray_yes = formatters["s=%F,a=%F,t=%F"] -local f_gray_nop = formatters["s=%F"] -local f_rgb_yes = formatters["r=%F,g=%F,b=%F,a=%F,t=%F"] -local f_rgb_nop = formatters["r=%F,g=%F,b=%F"] -local f_cmyk_yes = formatters["c=%F,m=%F,y=%F,k=%F,a=%F,t=%F"] -local f_cmyk_nop = formatters["c=%F,m=%F,y=%F,k=%F"] - -local ctx_MPLIBsetNtext = context.MPLIBsetNtext -local ctx_MPLIBsetCtext = context.MPLIBsetCtext -local ctx_MPLIBsettext = context.MPLIBsettext - --- we reuse content when possible --- we always create at least one instance (for dimensions) --- we make sure we don't do that when we use one (else counter issues with e.g. \definelabel) - -local eol = S("\n\r")^1 -local cleaner = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0) -local splitter = Ct( - ( ( - P("s:") * C((1-eol)^1) - + P("n:") * ((1-eol)^1/tonumber) - + P("b:") * ((1-eol)^1/toboolean) - ) * eol^0 )^0) - -local function applyformat(s) - local t = lpegmatch(splitter,s) - if #t == 1 then - return s - else - local f = lpegmatch(cleaner,t[1]) - return formatters[f](unpack(t,2)) - end -end - -local function tx_analyze(object,prescript) - local data = top.texdata[metapost.properties.number] - local tx_stage = prescript.tx_stage - if tx_stage == "trial" then - local tx_trial = data.textrial + 1 - data.textrial = tx_trial - local tx_number = tonumber(prescript.tx_number) - local s = object.postscript or "" - local c = object.color -- only simple ones, no transparency - if #c == 0 then - local txc = prescript.tx_color - if txc then - c = lpegmatch(pat,txc) + local fmt = formatters["%s %s %s % t"] + ----- pat = tsplitat(":") + local pat = lpeg.tsplitter(":",tonumber) -- so that %F can do its work + + local f_gray_yes = formatters["s=%.3F,a=%i,t=%.3F"] + local f_gray_nop = formatters["s=%.3F"] + local f_rgb_yes = formatters["r=%.3F,g=%.3F,b=%.3F,a=%.3F,t=%.3F"] + local f_rgb_nop = formatters["r=%.3F,g=%.3F,b=%.3F"] + local f_cmyk_yes = formatters["c=%.3F,m=%.3F,y=%.3F,k=%.3F,a=%.3F,t=%.3F"] + local f_cmyk_nop = formatters["c=%.3F,m=%.3F,y=%.3F,k=%.3F"] + + directives.register("metapost.stripzeros",function() + f_gray_yes = formatters["s=%.3N,a=%i,t=%.3N"] + f_gray_nop = formatters["s=%.3N"] + f_rgb_yes = formatters["r=%.3N,g=%.3N,b=%.3N,a=%.3N,t=%.3N"] + f_rgb_nop = formatters["r=%.3N,g=%.3N,b=%.3N"] + f_cmyk_yes = formatters["c=%.3N,m=%.3N,y=%.3N,k=%.3N,a=%.3N,t=%.3N"] + f_cmyk_nop = formatters["c=%.3N,m=%.3N,y=%.3N,k=%.3N"] + end) + + local ctx_MPLIBsetNtext = context.MPLIBsetNtextX + local ctx_MPLIBsetCtext = context.MPLIBsetCtextX + local ctx_MPLIBsettext = context.MPLIBsettextX + + local bp = number.dimenfactors.bp + + local mp_index = 0 + local mp_target = 0 + local mp_c = nil + local mp_a = nil + local mp_t = nil + + local function processtext() + local mp_text = top.texstrings[mp_index] + if not mp_text then + report_textexts("missing text for index %a",mp_index) + elseif not mp_c then + ctx_MPLIBsetNtext(mp_target,mp_text) + elseif #mp_c == 1 then + if mp_a and mp_t then + ctx_MPLIBsetCtext(mp_target,f_gray_yes(mp_c[1],mp_a,mp_t),mp_text) + else + ctx_MPLIBsetCtext(mp_target,f_gray_nop(mp_c[1]),mp_text) end - end - if prescript.tx_type == "format" then - s = applyformat(s) - end - local a = tonumber(prescript.tr_alternative) - local t = tonumber(prescript.tr_transparency) - local h = fmt(tx_number,a or "-",t or "-",c or "-") - local n = data.texhash[h] -- todo: hashed variant with s (nicer for similar labels) - if n then - data.texslots[tx_trial] = n - if trace_textexts then - report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"old",n,h,s) + elseif #mp_c == 3 then + if mp_a and mp_t then + ctx_MPLIBsetCtext(mp_target,f_rgb_nop(mp_c[1],mp_c[2],mp_c[3],mp_a,mp_t),mp_text) + else + ctx_MPLIBsetCtext(mp_target,f_rgb_nop(mp_c[1],mp_c[2],mp_c[3]),mp_text) end - elseif prescript.tx_global == "yes" and data.texorder[tx_number] then - -- we already have one flush and don't want it redone .. this needs checking - if trace_textexts then - report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"ignored",tx_last,h,s) + elseif #mp_c == 4 then + if mp_a and mp_t then + ctx_MPLIBsetCtext(mp_target,f_cmyk_yes(mp_c[1],mp_c[2],mp_c[3],mp_c[4],mp_a,mp_t),mp_text) + else + ctx_MPLIBsetCtext(mp_target,f_cmyk_nop(mp_c[1],mp_c[2],mp_c[3],mp_c[4]),mp_text) end else - local tx_last = top.texlast + 1 - top.texlast = tx_last - -- report_textexts("tex string: %s",s) - if not c then - ctx_MPLIBsetNtext(tx_last,s) - elseif #c == 1 then - if a and t then - ctx_MPLIBsetCtext(tx_last,f_gray_yes(c[1],a,t),s) - else - ctx_MPLIBsetCtext(tx_last,f_gray_nop(c[1]),s) - end - elseif #c == 3 then - if a and t then - ctx_MPLIBsetCtext(tx_last,f_rgb_nop(c[1],c[2],c[3],a,t),s) - else - ctx_MPLIBsetCtext(tx_last,f_rgb_nop(c[1],c[2],c[3]),s) - end - elseif #c == 4 then - if a and t then - ctx_MPLIBsetCtext(tx_last,f_cmyk_yes(c[1],c[2],c[3],c[4],a,t),s) - else - ctx_MPLIBsetCtext(tx_last,f_cmyk_nop(c[1],c[2],c[3],c[4]),s) - end - else - ctx_MPLIBsetNtext(tx_last,s) + -- can't happen + ctx_MPLIBsetNtext(mp_target,mp_text) + end + end + + function mp.mf_some_text(index,str) + mp_target = index + mp_index = index + mp_c = nil + mp_a = nil + mp_t = nil + top.texstrings[mp_index] = str + tex.runtoks("mptexttoks") + local box = textakebox("mptextbox") + top.textexts[mp_target] = box + mp.triplet(bp*box.width,bp*box.height,bp*box.depth) + madetext = nil + end + + local madetext = nil + + function mp.mf_made_text(index) + mp.mf_some_text(index,madetext) + end + + function metapost.maketext(s,mode) + if mode and mode == 1 then + if trace_btexetex then + report_metapost("ignoring verbatimtex: [[%s]]",s) end - top.multipass = true - data.texhash [h] = tx_last - -- data.texhash [tx_number] = tx_last - data.texslots[tx_trial] = tx_last - data.texorder[tx_number] = tx_last - if trace_textexts then - report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"new",tx_last,h,s) + else + if trace_btexetex then + report_metapost("handling btex ... etex: [[%s]]",s) end + -- madetext = utilities.strings.collapse(s) + madetext = s + return "rawmadetext" end - elseif tx_stage == "extra" then - local tx_trial = data.textrial + 1 - data.textrial = tx_trial - local tx_number = tonumber(prescript.tx_number) - if not data.texorder[tx_number] then - local s = object.postscript or "" - local tx_last = top.texlast + 1 - top.texlast = tx_last - ctx_MPLIBsettext(tx_last,s) - top.multipass = true - data.texslots[tx_trial] = tx_last - data.texorder[tx_number] = tx_last - if trace_textexts then - report_textexts("stage %a, usage %a, number %a, extra %a, text %a",tx_stage,tx_trial,tx_number,tx_last,s) + end + + function mp.mf_formatted_text(index,fmt,...) + local t = { } + for i=1,select("#",...) do + local ti = select(i,...) + if type(ti) ~= "table" then + t[#t+1] = ti end end + local f = lpegmatch(cleaner,fmt) + local s = formatters[f](unpack(t)) or "" + mp.mf_some_text(index,s) end -end -local function tx_process(object,prescript,before,after) - local data = top.texdata[metapost.properties.number] - local tx_number = tonumber(prescript.tx_number) - if tx_number then - local tx_stage = prescript.tx_stage - if tx_stage == "final" then - local tx_final = data.texfinal + 1 - data.texfinal = tx_final - local n = data.texslots[tx_final] + interfaces.implement { + name = "mptexttoks", + actions = processtext, + } + + tx_reset = function() + if top then + top.texhash = { } + top.texlast = 0 + end + end + + tx_process = function(object,prescript,before,after) + local data = top.texdata[metapost.properties.number] + local index = tonumber(prescript.tx_index) + if index then if trace_textexts then - report_textexts("stage %a, usage %a, number %a, use %a",tx_stage,tx_final,tx_number,n) + report_textexts("using index %a",index) + end + -- + mp_c = object.color + if #mp_c == 0 then + local txc = prescript.tx_color + if txc then + mp_c = lpegmatch(pat,txc) + end + end + mp_a = tonumber(prescript.tr_alternative) + mp_t = tonumber(prescript.tr_transparency) + -- + mp_index = index + mp_target = top.texlast - 1 + top.texlast = mp_target + -- + local mp_text = top.texstrings[mp_index] + local box + if prescript.tx_cache == "no" then + tex.runtoks("mptexttoks") + box = textakebox("mptextbox") + else + local hash = fmt(mp_text,mp_a or "-",mp_t or "-",mp_c or "-") + box = data.texhash[hash] + if box then + box = copy_list(box) + else + tex.runtoks("mptexttoks") + box = textakebox("mptextbox") + data.texhash[hash] = box + end end - local sx, rx, ry, sy, tx, ty = cm(object) -- needs to be frozen outside the function - local box = top.textexts[n] + top.textexts[mp_target] = box + -- if box then + -- we need to freeze the variables outside the function + local sx, rx, ry, sy, tx, ty = cm(object) + local target = mp_target before[#before+1] = function() - -- flush always happens, we can have a special flush function injected before - context.MPLIBgettextscaledcm(n, + context.MPLIBgettextscaledcm(target, f_f(sx), -- bah ... %s no longer checks f_f(rx), -- bah ... %s no longer checks f_f(ry), -- bah ... %s no longer checks @@ -1136,7 +965,7 @@ local function tx_process(object,prescript,before,after) end else before[#before+1] = function() - report_textexts("unknown %s",tx_number) + report_textexts("unknown %s",index) end end if not trace_textexts then @@ -1147,6 +976,7 @@ local function tx_process(object,prescript,before,after) object.istext = true end end + end -- we could probably redo normal textexts in the next way but as it's rather optimized @@ -1182,30 +1012,31 @@ end -- graphics (we use the given index because pictures can be reused) -local graphics = { } -function metapost.intermediate.actions.makempy() - if #graphics > 0 then - makempy.processgraphics(graphics) - graphics = { } -- ? could be gt_reset - end -end +local gt_reset, gt_process do + + local graphics = { } -local function gt_analyze(object,prescript) - local gt_stage = prescript.gt_stage - local gt_index = tonumber(prescript.gt_index) - if gt_stage == "trial" and not graphics[gt_index] then - graphics[gt_index] = formatters["\\MPLIBgraphictext{%s}"](object.postscript or "") - top.intermediate = true - top.multipass = true + + local mp_index = 0 + local mp_str = "" + + function mp.mf_graphic_text(index,str) + if not graphics[index] then + mp_index = index + mp_str = str + tex.runtoks("mpgraphictexttoks") + end end -end --- local function gt_process(object,prescript,before,after) --- local gt_stage = prescript.gt_stage --- if gt_stage == "final" then --- end --- end + interfaces.implement { + name = "mpgraphictexttoks", + actions = function() + context.MPLIBgraphictext(mp_index,mp_str) + end, + } + +end -- shades @@ -1342,7 +1173,7 @@ end local function bm_process(object,prescript,before,after) local bm_xresolution = prescript.bm_xresolution if bm_xresolution then - before[#before+1] = f_cm(cm(object)) + before[#before+1] = f_cm_b(cm(object)) before[#before+1] = function() figures.bitmapimage { xresolution = tonumber(bm_xresolution), @@ -1352,7 +1183,7 @@ local function bm_process(object,prescript,before,after) data = object.postscript } end - before[#before+1] = "Q" + before[#before+1] = s_cm_e object.path = false object.color = false object.grouped = true @@ -1364,10 +1195,13 @@ end local function ps_process(object,prescript,before,after) local ps_label = prescript.ps_label if ps_label then - local op = object.path - local first, third = op[1], op[3] - local x, y = first.x_coord, first.y_coord - local w, h = third.x_coord - x, third.y_coord - y + local op = object.path + local first = op[1] + local third = op[3] + local x = first.x_coord + local y = first.y_coord + local w = third.x_coord - x + local h = third.y_coord - y local properties = metapost.properties x = x - properties.llx y = properties.ury - y @@ -1380,14 +1214,33 @@ end -- figures +-- local sx, rx, ry, sy, tx, ty = cm(object) +-- sxsy(box.width,box.height,box.depth)) + +function mp.mf_external_figure(filename) + local f = figures.getinfo(filename) + local w = 0 + local h = 0 + if f then + local u = f.used + if u and u.fullname then + w = u.width or 0 + h = u.height or 0 + end + else + report_metapost("external figure %a not found",filename) + end + mp.triplet(w/65536,h/65536,0) +end + local function fg_process(object,prescript,before,after) local fg_name = prescript.fg_name if fg_name then - before[#before+1] = f_cm(cm(object)) -- beware: does not use the cm stack + before[#before+1] = f_cm_b(cm(object)) -- beware: does not use the cm stack before[#before+1] = function() context.MPLIBfigure(fg_name,prescript.fg_mask or "") end - before[#before+1] = "Q" + before[#before+1] = s_cm_e object.path = false object.grouped = true end @@ -1411,14 +1264,27 @@ local remappers = { [4] = formatters["c=%s,m=%s,y=%s,k=%s"], } +local processlast = 0 +local processhash = setmetatableindex(function(t,k) + processlast = processlast + 1 + local v = formatters["mp_%s"](processlast) + defineprocesscolor(v,k,true,true) + t[k] = v + return v +end) + +local function checked_transparency(alternative,transparency,before,after) + alternative = tonumber(alternative) or 1 + transparency = tonumber(transparency) or 0 + before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,alternative,transparency,true)) + after [#after +1] = "/Tr0 gs" -- outertransparency +end + local function tr_process(object,prescript,before,after) -- before can be shortcut to t local tr_alternative = prescript.tr_alternative if tr_alternative then - tr_alternative = tonumber(tr_alternative) - local tr_transparency = tonumber(prescript.tr_transparency) - before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,tr_alternative,tr_transparency,true)) - after[#after+1] = "/Tr0 gs" -- outertransparency + checked_transparency(tr_alternative,prescript.tr_transparency,before,after) end local cs = object.color if cs and #cs > 0 then @@ -1429,29 +1295,35 @@ local function tr_process(object,prescript,before,after) else local sp_name = prescript.sp_name or "black" if sp_type == "spot" then - local sp_value = prescript.sp_value or "s:1" - local sp_temp = formatters["mp:%s"](sp_value) - local s = split(sp_value,":") - local r = remappers[#s] - defineprocesscolor(sp_temp,r and r(unpack(s)) or "s=0",true,true) - definespotcolor(sp_name,sp_temp,"p=1",true) + local sp_value = prescript.sp_value or "1" + local components = split(sp_value,":") + local specification = remappers[#components] + if specification then + specification = specification(unpack(components)) + else + specification = "s=0" + end + local sp_spec = processhash[specification] + definespotcolor(sp_name,sp_spec,"p=1",true) sp_type = "named" elseif sp_type == "multitone" then -- (fractions of a multitone) don't work well in mupdf - local sp_value = prescript.sp_value or "s:1" - local sp_spec = { } + local sp_value = prescript.sp_value or "1" + local sp_specs = { } local sp_list = split(sp_value," ") for i=1,#sp_list do - local v = sp_list[i] - local t = formatters["mp:%s"](v) - local s = split(v,":") - local r = remappers[#s] - defineprocesscolor(t,r and r(unpack(s)) or "s=0",true,true) - local tt = formatters["ms:%s"](v) - definespotcolor(tt,t,"p=1",true) - sp_spec[#sp_spec+1] = formatters["%s=1"](t) + local sp_value = sp_list[i] + local components = split(sp_value,":") + local specification = remappers[#components] + if specification then + specification = specification(unpack(components)) + else + specification = "s=0" + end + local sp_spec = processhash[specification] + sp_specs[i] = formatters["%s=1"](sp_spec) end - sp_spec = concat(sp_spec,",") - definemultitonecolor(sp_name,sp_spec,"","",true) + sp_specs = concat(sp_specs,",") + definemultitonecolor(sp_name,sp_specs,"","") sp_type = "named" end if sp_type == "named" then @@ -1463,8 +1335,7 @@ local function tr_process(object,prescript,before,after) local t = t_list[sp_name] -- string or attribute local v = t and transparencyvalue(t) if v then - before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,v[1],v[2],true)) - after[#after+1] = "/Tr0 gs" -- outertransparency + checked_transparency(v[1],v[2],before,after) end end local c = c_list[sp_name] -- string or attribute @@ -1472,29 +1343,34 @@ local function tr_process(object,prescript,before,after) if v then -- all=1 gray=2 rgb=3 cmyk=4 local colorspace = v[1] - local f = cs[1] + local factor = cs[1] if colorspace == 2 then - local s = f*v[2] + local s = factor * v[2] c_b, c_a = checked_color_pair(f_gray,s,s) elseif colorspace == 3 then - local r, g, b = f*v[3], f*v[4], f*v[5] + local r = factor * v[3] + local g = factor * v[4] + local b = factor * v[5] c_b, c_a = checked_color_pair(f_rgb,r,g,b,r,g,b) elseif colorspace == 4 or colorspace == 1 then - local c, m, y, k = f*v[6], f*v[7], f*v[8], f*v[9] + local c = factor * v[6] + local m = factor * v[7] + local y = factor * v[8] + local k = factor * v[9] c_b, c_a = checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k) elseif colorspace == 5 then -- not all viewers show the fractions ok local name = v[10] local value = split(v[13],",") - if f ~= 1 then + if factor ~= 1 then for i=1,#value do - value[i] = f * (tonumber(value[i]) or 1) + value[i] = f_scn(factor * (tonumber(value[i]) or 1)) end end value = concat(value," ") c_b, c_a = checked_color_pair(f_spot,name,name,value,value) else - local s = f*v[2] + local s = factor *v[2] c_b, c_a = checked_color_pair(f_gray,s,s) end end @@ -1519,10 +1395,6 @@ end -- groups -local types = { - isolated -} - local function gr_process(object,prescript,before,after) local gr_state = prescript.gr_state if not gr_state then @@ -1530,7 +1402,10 @@ local function gr_process(object,prescript,before,after) elseif gr_state == "start" then local gr_type = utilities.parsers.settings_to_set(prescript.gr_type) local path = object.path - local p1, p2, p3, p4 = path[1], path[2], path[3], path[4] + local p1 = path[1] + local p2 = path[2] + local p3 = path[3] + local p4 = path[4] local llx = min(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord) local lly = min(p1.y_coord,p2.y_coord,p3.y_coord,p4.y_coord) local urx = max(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord) @@ -1554,82 +1429,88 @@ end -- outlines -local outlinetexts = { } +local ot_reset, ot_process do -local function ot_reset() - outlinetexts = { } -end + local outlinetexts = { } -- also in top data -local function ot_analyze(object,prescript) - local ot_stage = prescript.ot_stage - local ot_index = tonumber(prescript.ot_index) - if ot_index and ot_stage == "trial" and not outlinetexts[ot_index] then - local ot_kind = prescript.ot_kind or "" - top.intermediate = true - top.multipass = true - context.MPLIBoutlinetext(ot_index,ot_kind,object.postscript) + ot_reset = function () + outlinetexts = { } end -end -local function ot_process(object,prescript,before,after) -end + local mp_index = 0 + local mp_kind = "" + local mp_str = "" -implement { - name = "MPLIBconvertoutlinetext", - arguments = { "integer", "string", "integer" }, - actions = function(index,kind,box) - local boxtomp = fonts.metapost.boxtomp - if boxtomp then - outlinetexts[index] = boxtomp(box,kind) - else - outlinetexts[index] = "" + function mp.mf_outline_text(index,str,kind) + if not outlinetexts[index] then + mp_index = index + mp_kind = kind + mp_str = str + tex.runtoks("mpoutlinetoks") end end -} -function mp.get_outline_text(index) -- maybe we need a more private namespace - mp.print(outlinetexts[index] or "draw origin;") -end + interfaces.implement { + name = "mpoutlinetoks", + actions = function() + context.MPLIBoutlinetext(mp_index,mp_kind,mp_str) + end, + } + implement { + name = "MPLIBconvertoutlinetext", + arguments = { "integer", "string", "integer" }, + actions = function(index,kind,box) + local boxtomp = fonts.metapost.boxtomp + if boxtomp then + outlinetexts[index] = boxtomp(box,kind) + else + outlinetexts[index] = "" + end + end + } --- definitions + function mp.mf_get_outline_text(index) -- maybe we need a more private namespace + mp.print(outlinetexts[index] or "draw origin;") + end -appendaction(resetteractions, "system",ot_reset) -appendaction(resetteractions, "system",cl_reset) -appendaction(resetteractions, "system",tx_reset) +end -appendaction(processoractions,"system",ot_process) -appendaction(processoractions,"system",gr_process) +-- mf_object= -appendaction(analyzeractions, "system",ot_analyze) -appendaction(analyzeractions, "system",tx_analyze) -appendaction(analyzeractions, "system",gt_analyze) +local p1 = P("mf_object=") +local p2 = lpeg.patterns.eol * p1 +local pattern = (1-p2)^0 * p2 + p1 -appendaction(processoractions,"system",sh_process) --- (processoractions,"system",gt_process) -appendaction(processoractions,"system",bm_process) -appendaction(processoractions,"system",tx_process) -appendaction(processoractions,"system",bx_process) -appendaction(processoractions,"system",ps_process) -appendaction(processoractions,"system",fg_process) -appendaction(processoractions,"system",tr_process) -- last, as color can be reset +function metapost.isobject(str) + return pattern and str ~= "" and lpegmatch(p,str) and true or false +end -appendaction(processoractions,"system",la_process) +local function installplugin(specification) + local reset = specification.reset + local process = specification.process + local object = specification.object + if reset then + appendaction(resetteractions,"system",reset) + end + if process then + appendaction(processoractions,"system",process) + end +end --- function metapost.installplugin(reset,analyze,process) --- if reset then --- appendaction(resetteractions,"system",reset) --- end --- if analyze then --- appendaction(analyzeractions,"system",analyze) --- end --- if process then --- appendaction(processoractions,"system",process) --- end --- end +metapost.installplugin = installplugin --- we're nice and set them already +-- definitions -resetter = resetteractions .runner -analyzer = analyzeractions .runner -processor = processoractions.runner +installplugin { name = "outline", reset = ot_reset, process = ot_process } +installplugin { name = "color", reset = cl_reset, process = cl_process } +installplugin { name = "text", reset = tx_reset, process = tx_process } +installplugin { name = "group", reset = gr_reset, process = gr_process } +installplugin { name = "graphictext", reset = gt_reset, process = gt_process } +installplugin { name = "shade", reset = sh_reset, process = sh_process } +installplugin { name = "bitmap", reset = bm_reset, process = bm_process } +installplugin { name = "box", reset = bx_reset, process = bx_process } +installplugin { name = "position", reset = ps_reset, process = ps_process } +installplugin { name = "figure", reset = fg_reset, process = fg_process } +installplugin { name = "layer", reset = la_reset, process = la_process } +installplugin { name = "transparency", reset = tr_reset, process = tr_process } diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv index c9d181bf976..05113058511 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pps.mkiv @@ -57,14 +57,36 @@ \let\MPLIBsettext\MPLIBsetNtext +\unexpanded\def\MPLIBsetNtextX#1% #2% box text + {\MPLIBflushenvironment + \hbox\bgroup % text + \meta_set_current_color + \let\MPLIBflushenvironment\doMPLIBflushenvironment + \let\next} + +\unexpanded\def\MPLIBsetCtextX#1#2% #3% box colorspec text + {\MPLIBflushenvironment + \hbox\bgroup % text + \directcolored[#2]% + \meta_set_current_color % so, textcolor wins ! + \let\MPLIBflushenvironment\doMPLIBflushenvironment + \let\next} + +\let\MPLIBsettextX\MPLIBsetNtextX + \unexpanded\def\MPLIBgettextscaled#1#2#3% why a copy .. can be used more often {\clf_mpgettext\MPtextbox #1% \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}} +% \unexpanded\def\MPLIBfigure#1#2% +% {\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}% +% \clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint +% \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}} + \unexpanded\def\MPLIBfigure#1#2% {\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}% \clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint - \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}} + \vpack to \zeropoint{\vss\hpack to \zeropoint{\fastsxsy{\sx}{\sy}{\box\scratchbox}\hss}}} % horrible (we could inline scale and matrix code): @@ -185,4 +207,15 @@ \setbox\scratchbox\hpack\bgroup \unexpanded\def\MPLIBstopgroup{\doMPLIBstopgroup{#1}{#2}{#3}{#4}{#5}{#6}}} +% For now here ... will be cleaned up: + +\newtoks\mptexttoks +\newbox \mptextbox +\newtoks\mpoutlinetoks +\newtoks\mpgraphictexttoks + +\mptexttoks {\global\setbox\mptextbox\hbox{\clf_mptexttoks}} +\mpoutlinetoks {\global\setbox\mptextbox\vbox{\clf_mpoutlinetoks}} +\mpgraphictexttoks{\global\setbox\mptextbox\vbox{\clf_mpgraphictexttoks}} + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua index 18bc7e4da11..670c0e16b35 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-run.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['mlib-run'] = { license = "see context related readme files", } +-- todo mpx :execute -> mlib.execute(mpx,) + -- cmyk -> done, native -- spot -> done, but needs reworking (simpler) -- multitone -> @@ -30,7 +32,6 @@ nears zero.

--ldx]]-- local type, tostring, tonumber, next = type, tostring, tonumber, next -local gsub, match, find = string.gsub, string.match, string.find local striplines = utilities.strings.striplines local concat, insert, remove = table.concat, table.insert, table.remove @@ -70,20 +71,6 @@ end ----- mpbasepath = lpeg.instringchecker(lpeg.append { "/metapost/context/", "/metapost/base/" }) local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("base")) * P("/")) --- local function i_finder(askedname,mode,ftype) -- fake message for mpost.map and metafun.mpvi --- local foundname = file.is_qualified_path(askedname) and askedname or resolvers.findfile(askedname,ftype) --- if not mpbasepath(foundname) then --- -- we could use the via file but we don't have a complete io interface yet --- local data, found, forced = metapost.checktexts(io.loaddata(foundname) or "") --- if found then --- local tempname = luatex.registertempfile(foundname,true) --- io.savedata(tempname,data) --- foundname = tempname --- end --- end --- return foundname --- end - -- mplib has no real io interface so we have a different mechanism than -- tex (as soon as we have more control, we will use the normal code) -- @@ -97,21 +84,6 @@ do local new_instance = mplib.new - local function preprocessed(name) - if not mpbasepath(name) then - -- we could use the via file but we don't have a complete io interface yet - local data, found, forced = metapost.checktexts(io.loaddata(name) or "") - if found then - local temp = luatex.registertempfile(name,true) - io.savedata(temp,data) - return temp - end - end - return name - end - - mplib.preprocessed = preprocessed -- helper - local function validftype(ftype) if ftype == "" then -- whatever @@ -123,14 +95,13 @@ do end finders.file = function(specification,name,mode,ftype) - return preprocessed(resolvers.findfile(name,validftype(ftype))) + return resolvers.findfile(name,validftype(ftype)) end local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi local specification = url.hashed(name) local finder = finders[specification.scheme] or finders.file local found = finder(specification,name,mode,validftype(ftype)) - -- print(found) return found end @@ -160,7 +131,9 @@ function metapost.reporterror(result) if not result then report_metapost("error: no result object returned") elseif result.status > 0 then - local t, e, l = result.term, result.error, result.log + local t = result.term + local e = result.error + local l = result.log local report = metapost.texerrors and texerrormessage or report_metapost if t and t ~= "" then report("mp error: %s",striplines(t)) @@ -193,7 +166,8 @@ local f_preamble = formatters [ [[ local methods = { double = "double", scaled = "scaled", - binary = "binary", + -- binary = "binary", + binary = "double", decimal = "decimal", default = "scaled", } @@ -208,18 +182,6 @@ end -- todo: random_seed -local f_textext = formatters[ [[rawtextext("%s")]] ] - -function metapost.maketext(s,mode) - if mode and mode == 1 then - -- report_metapost("ignoring verbatimtex: %s",s) - else - -- report_metapost("handling btex ... etex: %s",s) - s = gsub(s,'"','"&ditto&"') - return f_textext(s) - end -end - local seed = nil function metapost.load(name,method) @@ -291,24 +253,103 @@ function metapost.unload(mpx) stoptiming(mplib) end -local mpxformats = { } +-- The flatten hack is needed because the library currently barks on \n\n and the +-- collapse because mp cannot handle snippets due to grouping issues. + +local function flatten(source,target) + for i=1,#source do + local d = source[i] + if type(d) == "table" then + flatten(d,target) + elseif d and d ~= "" then + target[#target+1] = d + end + end + return target +end + +local function prepareddata(data,collapse) + if data and data ~= "" then + if type(data) == "table" then + data = flatten(data,{ }) + if collapse then + data = #data > 1 and concat(data,"\n") or data[1] + end + end + return data + end +end + +metapost.defaultformat = "metafun" +metapost.defaultinstance = "metafun" +metapost.defaultmethod = "default" -function metapost.format(instance,name,method) +local mpxformats = { } +local nofformats = 0 +local mpxpreambles = { } + +function metapost.pushformat(specification,f,m) -- was: instance, name, method + if type(specification) ~= "table" then + specification = { + instance = specification, + format = f, + method = m, + } + end + local instance = specification.instance + local format = specification.format + local method = specification.method + local definitions = specification.definitions + local extensions = specification.extensions + local preamble = nil if not instance or instance == "" then - instance = "metafun" -- brrr + instance = metapost.defaultinstance + specification.instance = instance + end + if not format or format == "" then + format = metapost.defaultformat + specification.format = format + end + if not method or method == "" then + method = metapost.defaultmethod + specification.method = method + end + if definitions and definitions ~= "" then + preamble = definitions + end + if extensions and extensions ~= "" then + if preamble then + preamble = preamble .. "\n" .. extensions + else + preamble = extensions + end + end + nofformats = nofformats + 1 + local usedinstance = instance .. ":" .. nofformats + local mpx = mpxformats[usedinstance] + local mpp = mpxpreambles[instance] or "" + if preamble then + preamble = prepareddata(preamble,true) + mpp = mpp .. "\n" .. preamble + mpxpreambles[instance] = mpp end - name = name or instance - local mpx = mpxformats[instance] if not mpx then - report_metapost("initializing instance %a using format %a",instance,name) - mpx = metapost.checkformat(name,method) - mpxformats[instance] = mpx + report_metapost("initializing instance %a using format %a and method %a",usedinstance,format,method) + mpx = metapost.checkformat(format,method) + mpxformats[usedinstance] = mpx + if mpp ~= "" then + preamble = mpp + end + end + if preamble then + mpx:execute(preamble) end + specification.mpx = mpx return mpx end -function metapost.instance(instance) - return mpxformats[instance] +function metapost.popformat() + nofformats = nofformats - 1 end function metapost.reset(mpx) @@ -335,10 +376,6 @@ local mp_tag = 0 -- key/values -if not metapost.initializescriptrunner then - function metapost.initializescriptrunner() end -end - do local stack, top = { }, nil @@ -379,16 +416,47 @@ do end -function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig) - local converted, result = false, { } - if type(mpx) == "string" then - mpx = metapost.format(mpx) -- goody + +if not metapost.process then + + function metapost.process(specification) + metapost.run(specification) + end + +end + +-- run, process, convert and flush all work with a specification with the +-- following (often optional) fields +-- +-- mpx string or mp object +-- data string or table of strings +-- flusher table with flush methods +-- askedfig string ("all" etc) or number +-- incontext boolean +-- plugmode boolean + +local function makebeginbanner(specification) + return formatters["%% begin graphic: n=%s\n\n"](metapost.n) +end + +local function makeendbanner(specification) + return "\n% end graphic\n\n" +end + +function metapost.run(specification) + local mpx = specification.mpx + local data = specification.data + local converted = false + local result = { } + local mpxdone = type(mpx) == "string" + if mpxdone then + mpx = metapost.pushformat { instance = mpx, format = mpx } end if mpx and data then local tra = nil starttiming(metapost) - metapost.variables = { } - metapost.initializescriptrunner(mpx,trialrun) + metapost.variables = { } -- todo also push / pop + metapost.pushscriptrunner(mpx) if trace_graphics then tra = mp_tra[mpx] if not tra then @@ -400,39 +468,12 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, } mp_tra[mpx] = tra end - local banner = formatters["%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n"]( - metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass)) + local banner = makebeginbanner(specification) tra.inp:write(banner) tra.log:write(banner) end - if type(data) == "table" then - -- this hack is needed because the library currently barks on \n\n - -- eventually we can text for "" in the next loop - local n = 0 - local nofsnippets = #data - for i=1,nofsnippets do - local d = data[i] - if d ~= "" then - n = n + 1 - data[n] = d - end - end - for i=nofsnippets,n+1,-1 do - data[i] = nil - end - -- and this one because mp cannot handle snippets due to grouping issues - if metapost.collapse then - if #data > 1 then - data = concat(data,"\n") - else - data = data[1] - end - end - -- end of hacks - end - + local data = prepareddata(data,metapost.collapse) local function process(d,i) - -- d = string.gsub(d,"\r","") if d then if trace_graphics then if i then @@ -444,7 +485,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end end starttiming(metapost.exectime) - result = mpx:execute(d) -- some day we wil use a coroutine with textexts + result = mpx:execute(d) stoptiming(metapost.exectime) if trace_graphics and result then local str = result.log or result.error @@ -461,7 +502,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end end if result.fig then - converted = metapost.convert(result, trialrun, flusher, multipass, askedfig) + converted = metapost.convert(specification,result) end end elseif i then @@ -475,7 +516,6 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, if trace_tracingall then mpx:execute("tracingall;") end - -- table.insert(data,2,"") for i=1,#data do process(data[i],i) end @@ -486,17 +526,25 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, process(data) end if trace_graphics then - local banner = "\n% end graphic\n\n" + local banner = makeendbanner(specification) tra.inp:write(banner) tra.log:write(banner) end stoptiming(metapost) + metapost.popscriptrunner(mpx) + end + if mpxdone then + metapost.popformat() end return converted, result end -function metapost.convert() - report_metapost('warning: no converter set') +if not metapost.convert then + + function metapost.convert() + report_metapost('warning: no converter set') + end + end -- handy @@ -564,7 +612,7 @@ end -- goodie -function metapost.quickanddirty(mpxformat,data,plugmode) +function metapost.quickanddirty(mpxformat,data,incontext) if not data then mpxformat = "metafun" data = mpxformat @@ -584,7 +632,14 @@ function metapost.quickanddirty(mpxformat,data,plugmode) end } local data = formatters["; beginfig(1) ;\n %s\n ; endfig ;"](data) - metapost.process(mpxformat, { data }, false, flusher, false, false, "all", plugmode) + metapost.process { + mpx = mpxformat, + flusher = flusher, + askedfig = "all", + useplugins = incontext, + incontext = incontext, + data = { data }, + } if code then return { bbox = bbox or { 0, 0, 0, 0 }, @@ -619,7 +674,6 @@ do local width = 0 local height = 0 local depth = 0 - local mpx = false local flusher = { startfigure = function(n,llx,lly,urx,ury) @@ -637,13 +691,18 @@ do end } - function metapost.simple(format,code) -- even less than metapost.quickcanddirty - local mpx = metapost.format(format or "metafun","metafun") + function metapost.simple(format,code) -- even less than metapost.quickcanddirty + local mpx = metapost.pushformat { } -- takes defaults -- metapost.setoutercolor(2) - metapost.process(mpx, - { "beginfig(1);", code, "endfig;" }, - false, flusher, false, false, 1, true -- last true is plugmode ! - ) + metapost.process { + mpx = mpx, + flusher = flusher, + askedfig = 1, + useplugins = false, + incontext = false, + data = { "beginfig(1);", code, "endfig;" }, + } + metapost.popformat() if result then local stream = concat(result," ") result = nil -- cleanup diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-domotica.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-domotica.tex index 83562ee30cf..5a162893be3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-domotica.tex +++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-domotica.tex @@ -29,7 +29,9 @@ % % example: context --extra=domotica --openzwave ./config/fibaro/fgms.xml ./open-zwave-master/config/aeotec/zw100.xml % example: context --extra=domotica --openzwave --pattern="./open-zwave-master/config/**.xml" -% example: context --extra=domotica --hue hue-pragma-tasks.lua +% example: context --extra=domotica --hue hue-pragma-tasks.lua +% example: context --extra=domotica --hue pragma-youless-gas.lua --year=2018 --month=8 +% example: context --extra=domotica --hue pragma-youless-electricity.lua % % end help @@ -161,8 +163,11 @@ \stopmode + \startmode[hue] + \usemodule[youless] + \starttext \setupheadertexts @@ -171,10 +176,22 @@ local arguments = document.arguments local files = document.files - local pattern = arguments.pattern local filename = files[1] - - if filename then + local pattern = arguments.pattern + local year = arguments.year + local month = arguments.month + + local action = (arguments.tasks and "task") + or (arguments.graphics and "graphics") + or (string.find(filename,"tasks") and "tasks") + or (string.find(filename,"electricity") and "graphics") + or (string.find(filename,"pulse") and "graphics") + or (string.find(filename,"gas") and "graphics") + + if not filename or filename == "" then + logs.report("youless","provide filename") + context("no files given") + elseif action == "tasks" then context.starttitle { title = "Hue: " .. file.nameonly(filename) } filename = file.addsuffix(filename,"lua") if lfs.isfile(filename) then @@ -183,9 +200,11 @@ context("unknown file %a",filename) end context.stoptitle() + elseif action == "graphics" then + moduledata.youless.graphics { year = year, month = month, filename = filename } else - context("no files given") - context.stoptitle() + logs.report("youless","provide --status or --graphics") + context("no action given") end \stopluacode diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-fonts.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-fonts.tex new file mode 100644 index 00000000000..f1f74c9e9ae --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-fonts.tex @@ -0,0 +1,98 @@ +%D \module +%D [ file=mtx-context-fonts, +%D version=2018.10.10, +%D title=\CONTEXT\ Extra Trickry, +%D subtitle=Show Font Info, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% begin help +% +% usage: context --extra=fonts [options] name +% +% --topspace=dimension : distance above first line +% --backspace=dimension : distance before left margin +% --paperformat=spec : paper*print or paperxprint +% --compact : small margins, 8pt font +% --verycompact : small margins, 7pt font +% +% example: context --extra=fonts --name=dejavu-serif +% end help + +\input mtx-context-common.tex + +\usemodule[fonts-charts] +\usemodule[fonts-tables] + +\input mtx-context-common.tex + +\doifdocumentargument {compact} { + \setdocumentargument{topspace} {5mm} + \setdocumentargument{backspace}{5mm} + \setdocumentargument{bodyfont} {8pt} +} + +\doifdocumentargument {verycompact} { + \setdocumentargument{topspace} {5mm} + \setdocumentargument{backspace}{5mm} + \setdocumentargument{bodyfont} {7pt} +} + +\setupbodyfont + [dejavu,9pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete + +\setuplayout + [header=0cm, + footer=1.5cm, + topspace=\getdocumentargumentdefault{topspace}{1.5cm}, + backspace=\getdocumentargumentdefault{backspace}{1.5cm}, + width=middle, + height=middle] + +\setuppapersize + [\getdocumentargument{paperformat_paper}] + [\getdocumentargument{paperformat_print}] + +\starttexdefinition unexpanded showfontdetails [#1] + \starttitle[title=#1] + \startsubject[title=Properties] + \showfontproperties[#1] + \stopsubject + \startsubject[title=Parameters] + \showfontparameters[#1] + \stopsubject + \startsubject[title=Positionings] + \showfontpositionings[#1] + \stopsubject + \startsubject[title=Substitutions] + \showfontsubstitutions[#1] + \stopsubject + \startsubject[title=Unicodevariants] + \showfontunicodevariants[#1] + \stopsubject + \startsubject[title=Ligatures] + \showfontligatures[#1] + \stopsubject + \showfontchart[#1,page=yes] + \stoptitle +\stoptexdefinition + +\starttext + + \startluacode + local files = document.files + if #files > 0 then + for i=1,#files do + context.showfontdetails { name = files[i] .. "*default" } + end + else + context("No font name(s) given.") + end + \stopluacode + +\stoptext diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex index f7c3d28680c..1053e80b9c3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex +++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-listing.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This is a \TEXEXEC\ features that has been moved to \MKIV. +%D This is a \TEXEXEC\ feature that has been moved to \MKIV. % begin help % @@ -44,7 +44,7 @@ } \setupbodyfont - [dejavu,11pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete + [dejavu,9pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete \setuptyping [lines=yes] diff --git a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex index f8bfeef3a6e..875f02da696 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex +++ b/Master/texmf-dist/tex/context/base/mkiv/mtx-context-xml.tex @@ -76,6 +76,11 @@ if template then moduledata.xml.analyzers.allsetups(files,type(template) == "string" and template or nil) end + context.page() + for i=1,#files do + context.type(files[i]) + context.par() + end else context("no action given") end diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv index a1aecc35464..5e7de227096 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-aux.mkiv @@ -180,6 +180,10 @@ \def\mult_check_for_assignment_indeed#1=#2#3\_end_ {\if#2@\assignmentfalse\else\assignmenttrue\fi} +\def\mult_check_for_assignment_indeed_begin_#1=#2#3\_end_ + {\if#2@} + + \def\mult_check_for_assignment#1% {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_} @@ -223,7 +227,8 @@ {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - \def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? + %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? + \def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ? \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack \def#8##1{\begincsname#1#2:##1\endcsname}} @@ -255,7 +260,8 @@ {\ifx#2\relax\let#2\empty\fi \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}% + %\def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}% + \def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}% \def#6{#1#2:}% \def#7##1{#1##1:}% \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}% @@ -389,6 +395,43 @@ \the#7% \let#4#9}} +% \unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones +% {\ifx#4\relax\let#4\empty\fi % see \defineregister +% \unexpanded\def#2{\dotripleempty#5}% +% \newtoks#6% +% \newtoks#7% +% \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] +% {\let#9#4% +% \edef#4{##1}% +% \ifthirdargument +% \the#6% predefine +% \edef#8{##2}% +% \mult_check_for_parent{#1}{#3}#4#8% +% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% +% \mult_interfaces_get_parameters{#1#4:}[##3]% +% \else\ifsecondargument +% \the#6% predefine +% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=@@\_end_ +% \edef#8{##2}% +% \mult_check_for_parent{#1}{#3}#4#8% +% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% +% \else +% \let#8\empty +% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% +% \mult_interfaces_get_parameters{#1#4:}[##2]% +% \fi +% \else +% \the#6% predefine +% \let#8\empty +% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% +% \fi\fi +% \the#7% +% \let#4#9}} + \unexpanded\def\installdefinehandler#1#2#3% {\normalexpanded {\mult_interfaces_install_define_handler @@ -466,7 +509,7 @@ \let#3#7% \else\iffirstargument % \mult_check_for_assignment{##1}% - \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ + \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ \ifassignment % \setuplayout[key=value] \let#7#3% @@ -496,6 +539,54 @@ #2\zerocount % mode is always zero at the end \the#9}} +% \unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% +% {\newtoks#5% +% \newconstant#2% +% \newtoks#8% +% \newtoks#9% +% \ifx#6\relax\let#6\empty\fi +% \unexpanded\def#4[##1][##2]% maybe helper +% {\ifsecondargument % no commalist here +% % \setuplayout[whatever][key=value] +% \let#7#3% +% \let#6#3% +% \edef#3{##1}% +% #2\doingrootsetupnamed +% \mult_interfaces_get_parameters{#1#3:}[##2]% +% \the#5% +% \ifx#3#6\the#8\fi % only switchsetups if previous == current +% \let#3#7% +% \else\iffirstargument +% % \mult_check_for_assignment{##1}% +% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=@@\_end_ +% % \setuplayout[whatever] +% \let#6#3% % previous becomes current +% \edef#3{##1}% this will catch reset so one needs to test for it +% #2\doingrootsetnamed +% \the#5% % we can check for previous vs current +% \the#8% switchsetups +% \else +% % \setuplayout[key=value] +% \let#7#3% +% \let#6#3% +% \let#3\empty +% #2\doingrootsetuproot +% \mult_interfaces_get_parameters{#1:}[##1]% +% \the#5% +% \the#8% switchsetups +% \let#3#7% +% \fi +% \else +% % \setuplayout +% \let#6#3% % previous becomes current +% \let#3\empty % current becomes empty +% #2\doingrootsetroot +% \the#5% +% \the#8% switchsetups +% \fi\fi +% #2\zerocount % mode is always zero at the end +% \the#9}} + \unexpanded\def\installswitchsetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_switch_setup_handler_a @@ -966,176 +1057,176 @@ \def\s!double{double} \def\s!triple{triple} -\unexpanded\def\syst_helpers_double_empty#1#2#3% - {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_double_empty_one_yes_mult#2#3}% - {\syst_helpers_double_empty_one_nop_mult#1}} - -\def\syst_helpers_double_empty_one_yes_mult#1#2[#3]% - {\firstargumenttrue - \doifelsenextoptional - {\secondargumenttrue#2[{#3}]}% - {\syst_helpers_double_empty_two_nop_mult#1{#3}}} - -\def\syst_helpers_double_empty_one_nop_mult% #1% - {\firstargumentfalse - \secondargumentfalse - }% #1} - -\def\syst_helpers_double_empty_two_nop_mult - {\secondargumentfalse - \if_next_blank_space_token - \expandafter\syst_helpers_double_empty_one_spaced_mult - \else - \expandafter\syst_helpers_double_empty_one_normal_mult - \fi} - -\def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] } -\def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]} - -\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% - {\ifx#3\relax\let#3\empty\fi - \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it - \newtoks#4% - \newtoks#7% - \edef\m_mult_interface_setup{\csstring#2_}% - \unexpanded\edef#2{\syst_helpers_double_empty - \csname\m_mult_interface_setup\s!simple\endcsname - \csname\m_mult_interface_setup\s!single\endcsname - \csname\m_mult_interface_setup\s!double\endcsname}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% - {\let#6#3% - \def#8####1% we will have a simple one as well - {\edef#3{####1}% - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#4}% - \processcommalist[##1]#8% - \let#3#6% - \the#7}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% - {\let#6#3% - \let#3\empty - \mult_interfaces_get_parameters{#1:}[##1]% - \the#4% - \let#3#6% - \the#7}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% - {\let#6#3% - \let#3\empty - \the#4% - \let#3#6% - \the#7}} - -\unexpanded\def\installsetuphandler#1#2% - {\normalexpanded - {\mult_interfaces_install_setup_handler - {\noexpand#1}% \??aa - \expandafter\noexpand\csname setup#2\endcsname - \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname everysetup#2\endcsname - \expandafter\noexpand\csname setupcurrent#2\endcsname - \expandafter\noexpand\csname saved_setup_current#2\endcsname - \expandafter\noexpand\csname everysetup#2root\endcsname - \expandafter\noexpand\csname nested_setup_current#2\endcsname}} - -\unexpanded\def\syst_helpers_triple_empty#1#2#3#4% - {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_triple_empty_one_yes_mult#2#3#4}% - {\syst_helpers_triple_empty_one_nop_mult#1}} - -\def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]% - {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}% - {\syst_helpers_triple_empty_two_nop_mult#1{#4}}} - -\def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]% - {\secondargumenttrue - \doifelsenextoptional - {\thirdargumenttrue#2[{#3}][{#4}]}% - {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}} - -\def\syst_helpers_triple_empty_one_nop_mult % #1% - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - } % #1 - -\def\syst_helpers_triple_empty_two_nop_mult - {\secondargumentfalse - \thirdargumentfalse - \if_next_blank_space_token - \expandafter\syst_helpers_triple_empty_two_spaced_mult - \else - \expandafter\syst_helpers_triple_empty_two_normal_mult - \fi} - -\def\syst_helpers_triple_empty_three_nop_mult - {\thirdargumentfalse - \if_next_blank_space_token - \expandafter\syst_helpers_triple_empty_three_spaced_mult - \else - \expandafter\syst_helpers_triple_empty_three_normal_mult - \fi} - -\def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] } -\def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]} -\def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] } -\def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]} - -\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% - {\ifx#3\relax\let#3\empty\fi - \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% - \newtoks#4% - \edef\m_mult_interface_setup{\csstring#2_}% - \unexpanded\edef#2{\syst_helpers_triple_empty - \csname\m_mult_interface_setup\s!simple\endcsname - \csname\m_mult_interface_setup\s!single\endcsname - \csname\m_mult_interface_setup\s!double\endcsname - \csname\m_mult_interface_setup\s!triple\endcsname}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]% - {\let#7#3% - \def#8####1% - {\edef#3{####1}% - \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% - \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent - \the#4}% - \processcommalist[##1]#8% - \let#3#7}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% - {\let#7#3% - \def#8####1% - {\edef#3{####1}% - #6% checks parent and sets if needed - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#4}% - \processcommalist[##1]#8% - \let#3#7}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% - {\let#7#3% - \let#3\empty - \mult_interfaces_get_parameters{#1:}[##1]% - \the#4% - \let#3#7}% - \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% - {\let#7#3% - \let#3\empty - \the#4% - \let#3#7}} - -\unexpanded\def\installautosetuphandler#1#2% - {\normalexpanded - {\mult_interfaces_install_auto_setup_handler - {\noexpand#1}% \??aa - \expandafter\noexpand\csname setup#2\endcsname - \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname everysetup#2\endcsname - \expandafter\noexpand\csname setupcurrent#2\endcsname - \expandafter\noexpand\csname check#2parent\endcsname - \expandafter\noexpand\csname saved_setup_current#2\endcsname - \expandafter\noexpand\csname nested_setup_current#2\endcsname}} +% \unexpanded\def\syst_helpers_double_empty#1#2#3% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_double_empty_one_yes_mult#2#3}% +% {\syst_helpers_double_empty_one_nop_mult#1}} +% +% \def\syst_helpers_double_empty_one_yes_mult#1#2[#3]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\secondargumenttrue#2[{#3}]}% +% {\syst_helpers_double_empty_two_nop_mult#1{#3}}} +% +% \def\syst_helpers_double_empty_one_nop_mult% #1% +% {\firstargumentfalse +% \secondargumentfalse +% }% #1} +% +% \def\syst_helpers_double_empty_two_nop_mult +% {\secondargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_double_empty_one_spaced_mult +% \else +% \expandafter\syst_helpers_double_empty_one_normal_mult +% \fi} +% +% \def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] } +% \def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]} +% +% \unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% +% {\ifx#3\relax\let#3\empty\fi +% \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it +% \newtoks#4% +% \newtoks#7% +% \edef\m_mult_interface_setup{\csstring#2_}% +% \unexpanded\edef#2{\syst_helpers_double_empty +% \csname\m_mult_interface_setup\s!simple\endcsname +% \csname\m_mult_interface_setup\s!single\endcsname +% \csname\m_mult_interface_setup\s!double\endcsname}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% +% {\let#6#3% +% \def#8####1% we will have a simple one as well +% {\edef#3{####1}% +% \mult_interfaces_get_parameters{#1#3:}[##2]% +% \the#4}% +% \processcommalist[##1]#8% +% \let#3#6% +% \the#7}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% +% {\let#6#3% +% \let#3\empty +% \mult_interfaces_get_parameters{#1:}[##1]% +% \the#4% +% \let#3#6% +% \the#7}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% +% {\let#6#3% +% \let#3\empty +% \the#4% +% \let#3#6% +% \the#7}} + +% \unexpanded\def\installsetuphandler#1#2% +% {\normalexpanded +% {\mult_interfaces_install_setup_handler +% {\noexpand#1}% \??aa +% \expandafter\noexpand\csname setup#2\endcsname +% \expandafter\noexpand\csname current#2\endcsname +% \expandafter\noexpand\csname everysetup#2\endcsname +% \expandafter\noexpand\csname setupcurrent#2\endcsname +% \expandafter\noexpand\csname saved_setup_current#2\endcsname +% \expandafter\noexpand\csname everysetup#2root\endcsname +% \expandafter\noexpand\csname nested_setup_current#2\endcsname}} +% +% \unexpanded\def\syst_helpers_triple_empty#1#2#3#4% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_triple_empty_one_yes_mult#2#3#4}% +% {\syst_helpers_triple_empty_one_nop_mult#1}} +% +% \def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}% +% {\syst_helpers_triple_empty_two_nop_mult#1{#4}}} +% +% \def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\thirdargumenttrue#2[{#3}][{#4}]}% +% {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}} +% +% \def\syst_helpers_triple_empty_one_nop_mult % #1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% } % #1 +% +% \def\syst_helpers_triple_empty_two_nop_mult +% {\secondargumentfalse +% \thirdargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_triple_empty_two_spaced_mult +% \else +% \expandafter\syst_helpers_triple_empty_two_normal_mult +% \fi} +% +% \def\syst_helpers_triple_empty_three_nop_mult +% {\thirdargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_triple_empty_three_spaced_mult +% \else +% \expandafter\syst_helpers_triple_empty_three_normal_mult +% \fi} +% +% \def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] } +% \def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]} +% \def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] } +% \def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]} +% +% \unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% +% {\ifx#3\relax\let#3\empty\fi +% \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% +% \newtoks#4% +% \edef\m_mult_interface_setup{\csstring#2_}% +% \unexpanded\edef#2{\syst_helpers_triple_empty +% \csname\m_mult_interface_setup\s!simple\endcsname +% \csname\m_mult_interface_setup\s!single\endcsname +% \csname\m_mult_interface_setup\s!double\endcsname +% \csname\m_mult_interface_setup\s!triple\endcsname}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]% +% {\let#7#3% +% \def#8####1% +% {\edef#3{####1}% +% \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% +% \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent +% \the#4}% +% \processcommalist[##1]#8% +% \let#3#7}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% +% {\let#7#3% +% \def#8####1% +% {\edef#3{####1}% +% #6% checks parent and sets if needed +% \mult_interfaces_get_parameters{#1#3:}[##2]% +% \the#4}% +% \processcommalist[##1]#8% +% \let#3#7}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% +% {\let#7#3% +% \let#3\empty +% \mult_interfaces_get_parameters{#1:}[##1]% +% \the#4% +% \let#3#7}% +% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% +% {\let#7#3% +% \let#3\empty +% \the#4% +% \let#3#7}} +% +% \unexpanded\def\installautosetuphandler#1#2% +% {\normalexpanded +% {\mult_interfaces_install_auto_setup_handler +% {\noexpand#1}% \??aa +% \expandafter\noexpand\csname setup#2\endcsname +% \expandafter\noexpand\csname current#2\endcsname +% \expandafter\noexpand\csname everysetup#2\endcsname +% \expandafter\noexpand\csname setupcurrent#2\endcsname +% \expandafter\noexpand\csname check#2parent\endcsname +% \expandafter\noexpand\csname saved_setup_current#2\endcsname +% \expandafter\noexpand\csname nested_setup_current#2\endcsname}} % okay, we can also get rid of the #9, but this code looks pretty bad, while the previous is % still okay given that we can also use #6 as setup (so in fact we can save some cs again and @@ -1197,9 +1288,11 @@ {\dodoubleempty#7}% \unexpanded\def#7[##1][##2]% {\ifsecondargument - #3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}% + %#3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}% + #3\toksapp\c_mult_set{#9[##1][##2]}% \else\iffirstargument - #3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}% + %#3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}% + #3\toksapp\c_mult_set{#8[##1]}% \fi\fi}} \unexpanded\def\installdefinitionsetmember#1#2#3#4% @@ -1230,9 +1323,30 @@ \expandafter\noexpand\csname current#2parent\endcsname \expandafter\noexpand\csname inject#2parent\endcsname}} +% Faster but not used that much to make a dent in performance. But, because it's +% cleaner anyway and also gives less tracing, we apply it a few times. + +\unexpanded\def\syst_helpers_install_macro_stack#1#2#3% + {\xdef\m_syst_helpers_push_macro{\csstring#1}% + \expandafter\newcount\csname#3\m_syst_helpers_push_macro\endcsname + \expandafter\edef\csname push_macro_\m_syst_helpers_push_macro\endcsname + {\noexpand\expandafter\glet + \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname + \noexpand#1% + \global\advance\csname#3\m_syst_helpers_push_macro\endcsname\plusone}% + \expandafter\edef\csname pop_macro_\m_syst_helpers_push_macro\endcsname + {\global\advance\csname#3\m_syst_helpers_push_macro\endcsname\minusone + \noexpand\expandafter#2% + \noexpand\expandafter\noexpand#1% + \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname}} + +\unexpanded\def\installmacrostack #1{\syst_helpers_install_macro_stack#1\let \??localpushedmacro } +\unexpanded\def\installglobalmacrostack#1{\syst_helpers_install_macro_stack#1\glet\??globalpushedmacro} + \protect -%\unprotect +% \unprotect +% % \installcorenamespace {test} \installcommandhandler \??test {test} \??test % \unexpanded\def\TestMeA[#1]% % {\edef\currenttest{#1} @@ -1247,12 +1361,92 @@ % \unexpanded\def\TestMeD[#1]% % {\edef\currenttest{#1} % \doubleexpandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi} -% \protect % -% \starttext -% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed] -% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502 -% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530 -% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487 -% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493 -% \stoptext +% \protect +% +% \starttext +% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed] +% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502 +% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530 +% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487 +% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493 +% \stoptext + +% There is no real demand for this ... even if this is twice as fast we only gain +% a few milliseconds: +% +% \unexpanded\def\foo#1{[foo:#1]} +% +% \installcommalistprocessor {foo} \foo +% \installcommalistprocessorcommand \processfoolist {foo} \foo +% +% \commalistprocessor{foo}[a,b,c,d] +% \processfoolist [a, b, c, d] +% +% \testfeatureonce{30000}{} \elapsedtime\par % 0.01 -> 0.00 +% \testfeatureonce{30000}{\processfoolist [fixed,middle]} \elapsedtime\par % 0.07 -> 0.06 +% \testfeatureonce{30000}{\commalistprocessor{foo}[fixed,middle]} \elapsedtime\par % 0.09 -> 0.08 +% \testfeatureonce{30000}{\processcommalist [fixed,middle]\foo} \elapsedtime\par % 0.13 -> 0.12 +% +% For instance the luatex manual only has some 3000 calls. But I keep this around as one +% never knows when we might need it. +% +% \installcorenamespace{commalistprocessor} +% \installcorenamespace{commalistprocessorcheck} +% \installcorenamespace{commalistprocessorwrap} +% \installcorenamespace{commalistprocessorfirst} +% \installcorenamespace{commalistprocessorcheckspace} +% \installcorenamespace{commalistprocessorcheckfinish} +% \installcorenamespace{commalistprocessoraction} +% \installcorenamespace{commalistprocessorgobblespace} +% +% \unexpanded\def\installcommalistprocessor#1#2% 7 macro names overhead +% {\let\nexttoken\relax +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[% +% {\futurelet\nexttoken\csname\??commalistprocessorcheck#1\endcsname}% +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessorcheck#1\endcsname +% {\noexpand\ifx\nexttoken]% +% \noexpand\expandafter\noexpand\gobblethreearguments +% \noexpand\else +% \noexpand\expandafter\csname\??commalistprocessorwrap#1\endcsname +% \noexpand\fi +% \relax}% this one preserved the next {} +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]% +% {\csname\??commalistprocessorfirst#1\endcsname##1,]\relax}% +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname##1% picks up \relax +% {\csname\??commalistprocessorcheckspace#1\endcsname}% +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessorcheckspace#1\endcsname +% {\noexpand\ifx\nexttoken\noexpand\blankspace +% \noexpand\expandafter\csname\??commalistprocessorgobblespace#1\endcsname +% \noexpand\else +% \noexpand\expandafter\csname\??commalistprocessorcheckfinish#1\endcsname +% \noexpand\fi}% +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessorcheckfinish#1\endcsname +% {\noexpand\ifx\nexttoken]% +% \noexpand\expandafter\noexpand\gobbleoneargument +% \noexpand\else +% \noexpand\expandafter\csname\??commalistprocessoraction#1\endcsname +% \noexpand\fi}% +% % +% \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,% +% {\noexpand#2{##1}% +% \futurelet\nexttoken\csname\??commalistprocessorcheckspace#1\endcsname}% +% % +% \let\next\:% +% \unexpanded\edef \:{\csname\??commalistprocessorgobblespace#1\endcsname}% +% \unexpanded\expandafter\edef\: {\futurelet\nexttoken\csname\??commalistprocessorcheckspace#1\endcsname}% +% \let\:\next +% % +% } +% +% \unexpanded\def\installcommalistprocessorcommand#1#2#3% +% {\installcommalistprocessor{#2}{#3}% +% \expandafter\let\expandafter#1\csname\??commalistprocessor#2\endcsname} +% +% \unexpanded\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname} diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua index 925c22cd223..e03a82a765f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua @@ -7503,6 +7503,10 @@ return { ["pe"]="تاریخ", ["ro"]="data", }, + ["time"]={ + ["en"]="time", + ["nl"]="tijd", + }, ["deepnumbercommand"]={ ["cs"]="deepnumbercommand", ["de"]="deepnumbercommand", @@ -8278,7 +8282,7 @@ return { ["ro"]="inaltime", }, ["hfactor"]={ - ["cs"]="vfaktor", + ["cs"]="hfaktor", ["de"]="hfaktor", ["en"]="hfactor", ["fr"]="facteurhauteur", @@ -8287,6 +8291,14 @@ return { ["pe"]="عامل‌ارتفاع", ["ro"]="hfactor", }, + ["vfactor"]={ + ["cs"]="vfaktor", + ["de"]="vfaktor", + ["en"]="vfactor", + ["it"]="vfactor", + ["nl"]="vfactor", + ["ro"]="vfactor", + }, ["hfil"]={ ["cs"]="hfil", ["de"]="hfil", @@ -11544,6 +11556,12 @@ return { ["pe"]="گام‌وای", ["ro"]="ystep", }, + ["ownerpassword"]={ + ["en"]="ownerpassword", + }, + ["userpassword"]={ + ["en"]="userpassword", + }, }, ["elements"]={ ["answerlines"]={ @@ -13020,6 +13038,10 @@ return { ["cite"]={ ["en"]="cite", }, + ["closed"]={ + ["en"]="closed", + ["nl"]="gesloten", + }, ["color"]={ ["cs"]="barevne", ["de"]="farbe", @@ -15538,7 +15560,7 @@ return { ["ro"]="postscript", }, ["precedingpage"]={ - ["en"]="followingpage", + ["en"]="precedingpage", ["nl"]="voorafgaandepagina", }, ["preference"]={ @@ -17053,6 +17075,9 @@ return { ["unframed"]={ ["en"]="unframed", }, + ["unicode"]={ + ["en"]="unicode", + }, ["unit"]={ ["cs"]="jednotka", ["de"]="einheit", @@ -17815,8 +17840,8 @@ return { ["cd:brackets-l"] = { en = "[...,...]", lua = "{..., ...}" }, ["cd:parenthesis-s"] = { en = "(...)" }, ["cd:parenthesis-l"] = { en = "(...,...)" }, - ["cd:index-s"] = { en = "[...]" }, - ["cd:index-l"] = { en = "[..+...+..]" }, + ["cd:index-s"] = { en = "{...}" }, + ["cd:index-l"] = { en = "{..+...+..}" }, ["cd:math-s"] = { en = "$...$" }, ["cd:math-l"] = { en = "$...$" }, ["cd:inlinemath-s"] = { en = "$...$" }, diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua index 9b7062605b7..0776f36b4b2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-fun.lua @@ -3,7 +3,7 @@ return { -- "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", - "textextoffset", + "textextoffset", "textextanchor", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", @@ -53,17 +53,19 @@ return { "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", - "withshadestep", "withshadefraction", + "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", - "graphictext", "loadfigure", "externalfigure", "figure", "register", "outlinetext", -- "lua", + "graphictext", "loadfigure", "externalfigure", "figure", "register", + "outlinetext", "filloutlinetext", "drawoutlinetext", "outlinetexttopath", "checkedbounds", "checkbounds", "strut", "rule", "withmask", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "colordecimalslist", "textext", "thetextext", "rawtextext", "textextoffset", "texbox", "thetexbox", "rawtexbox", "istextext", + "notcached", "verbatim", "thelabel", "label", "autoalign", @@ -144,5 +146,31 @@ return { "sortlist", "copylist", "shapedlist", "listtocurves", "listtolines", "listsize", "listlast", "uniquelist", -- "circularpath", "squarepath", "linearpath", + -- + "theoffset", + -- + "texmode", "systemmode", + "texvar", "texstr", + "isarray", "prefix", "dimension", + "getmacro", "getdimen", "getcount", "gettoks", + "setmacro", "setdimen", "setcount", "settoks", + -- + "positionpath", "positioncurve", "positionxy", "positionpxy", + "positionwhd", "positionpage", "positionregion", "positionbox", + "positionanchor", "positioninregion", "positionatanchor", + -- + "wdpart", "htpart", "dppart", + -- + "texvar", "texstr", + -- + "inpath", "pointof", "leftof", "rightof", + -- + "newhash", "disposehash", "inhash", "tohash", + -- + "isarray", "prefix", "isobject", + -- + "comment", "report", "lua", "mp", "MP", "luacall", + -- + "mirrored", "mirroredabout", }, } diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua index 3f320bf7fdf..0c8581281d1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.lua @@ -105,6 +105,22 @@ function interfaces.getnamespace(n) return usednamespaces[n] .. ">" end +if documentdata then + + local prefix, getmacro + + function documentdata.variable(name) + if not prefix then + prefix = usednamespaces.variables .. ">document:" + end + if not getmacro then + getmacro = tokens.getters.macro + end + return getmacro(prefix..name) + end + +end + local function resolve(t,k) local v = logs.reporter(k) t[k] = v diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv index d66749d145e..634e2c1d827 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-ini.mkiv @@ -111,6 +111,8 @@ \def\s!spread{spread} \let\!!spread\s!spread % obsolete \def\s!plus {plus} \let\!!plus \s!plus % obsolete \def\s!minus {minus} \let\!!minus \s!minus % obsolete +\def\s!left {left} +\def\s!right {right} \def\s!fil {fil} \def\s!fill {fill} \let\!!fill \s!fill % obsolete \def\s!filll {filll} @@ -122,11 +124,6 @@ \def\s!top {top} \def\s!both {both} -%D Kind of special: - -\edef\!!TLT{\detokenize{TLT}} -\edef\!!TRT{\detokenize{TRT}} - %D \macros %D {defineinterfaceconstant, %D defineinterfacevariable, @@ -341,17 +338,17 @@ %D These will become obsolete: \unexpanded\def\startmessages #1 library: #2 % - {\bgroup + {\begingroup \ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi - \catcode\endoflineasciicode\activecatcode + \catcode\endoflineasciicode\othercatcode \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} \def\mult_messages_start_yes#1#2\stopmessages {\clf_setinterfacemessages{#1}{#2}% - \egroup} + \endgroup} \def\mult_messages_start_nop#1#2\stopmessages - {\egroup} + {\endgroup} \let\stopmessages\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua index 0acba3b87b1..75c048c92de 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-low.lua @@ -12,7 +12,8 @@ return { ["constants"] = { -- "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", - "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plustwohundred", + "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", + "plusfifty", "plushundred", "plusonehundred", "plustwohundred", "plusfivehundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "maxcardminusone", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxcount", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", @@ -20,7 +21,9 @@ return { "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", - -- -- + -- + "directionlefttoright", "directionrighttoleft", + -- "endoflinetoken", "outputnewlinechar", -- "emptytoks", "empty", "undefined", @@ -31,9 +34,7 @@ return { -- "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "texenginefunctionality", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", - -- "etexversion", - -- "pdftexversion", "pdftexrevision", - -- "xetexversion", "xetexrevision", + "contextformat", "contextversion", "contextkind", "contextlmtxmode", "contextmark", "mksuffix", -- "activecatcode", -- @@ -59,6 +60,7 @@ return { "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", + "leftparentasciicode", "rightparentasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", @@ -101,7 +103,9 @@ return { "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", - "starttext", "stoptext", "startnotext", "stopnotext","startdocument", "stopdocument", "documentvariable", "unexpandeddocumentvariable", "setupdocument", "presetdocument", + "starttext", "stoptext", "startnotext", "stopnotext", + "startdocument", "stopdocument", "documentvariable", "unexpandeddocumentvariable", "setupdocument", "presetdocument", + "doifelsedocumentvariable", "doifdocumentvariableelse", "doifdocumentvariable", "doifnotdocumentvariable", "startmodule", "stopmodule", "usemodule", "usetexmodule", "useluamodule","setupmodule","currentmoduleparameter","moduleparameter", "everystarttext", "everystoptext", -- @@ -153,10 +157,12 @@ return { "texdefinition", -- "doifelsesetups", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "fastsetup", + "copysetups", "resetsetups", "doifelsecommandhandler", "doifcommandhandlerelse", "doifnotcommandhandler", "doifcommandhandler", -- "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", + "globalsetmode", "globalresetmode", "globalsetsystemmode", "globalresetsystemmode", "booleanmodevalue", -- "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", @@ -165,14 +171,19 @@ return { "then", "begcsname", -- + "autorule", + -- "strippedcsname","checkedstrippedcsname", -- "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", - "fifthargumentfalse", "fifthsargumenttrue", - "sixthargumentfalse", "sixtsargumenttrue", + "fifthargumentfalse", "fifthargumenttrue", + "sixthargumentfalse", "sixthargumenttrue", + "seventhargumentfalse", "seventhargumenttrue", + -- + "vkern", "hkern", -- "doglobal", "dodoglobal", "redoglobal", "resetglobal", -- @@ -197,8 +208,8 @@ return { -- "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", -- - "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", - "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", + "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilll", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "normalhfilllneg", + "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilll", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "normalvfilllneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox", "ruledhpack", "ruledvpack", "ruledtpack", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", @@ -214,11 +225,20 @@ return { "scratchtoks", "globalscratchtoks", "privatescratchtoks", "scratchbox", "globalscratchbox", "privatescratchbox", -- + "globalscratchcounterone", "globalscratchcountertwo", "globalscratchcounterthree", + -- + "groupedcommand", "groupedcommandcs", + "triggergroupedcommand", "triggergroupedcommandcs", + "simplegroupedcommand", "pickupgroupedcommand", + -- "normalbaselineskip", "normallineskip", "normallineskiplimit", -- "availablehsize", "localhsize", "setlocalhsize", "distributedhsize", "hsizefraction", -- + "next", "nexttoken", + -- "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "flushnextbox", + "boxisempty", -- "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", @@ -239,6 +259,7 @@ return { "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", -- "doif", "doifnot", "doifelse", + "firstinset", "doifinset", "doifnotinset", "doifelseinset", "doifinsetelse", "doifelsenextchar", "doifnextcharelse", @@ -262,7 +283,7 @@ return { "doifelsenumber", "doifnumberelse", "doifnumber", "doifnotnumber", "doifelsecommon", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifelseinstring", "doifinstringelse", - "doifelseassignment", "doifassignmentelse", "docheckassignment", + "doifelseassignment", "doifassignmentelse", "docheckassignment", "doifelseassignmentcs", "doifassignmentelsecs", "doiftext", "doifelsetext", "doiftextelse", "doifnottext", -- "tracingall", "tracingnone", "loggingall", @@ -278,7 +299,7 @@ return { "singleexpandafter", "doubleexpandafter", "tripleexpandafter", -- "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", - "removepunctuation", "ignoreparskip", "forcestrutdepth", + "removepunctuation", "ignoreparskip", "forcestrutdepth", "onlynonbreakablespace", -- "wait", "writestatus", "define", "defineexpandable", "redefine", -- @@ -329,7 +350,7 @@ return { "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "permitspacesbetweengroups", "dontpermitspacesbetweengroups", -- - "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", + "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "onlypdfobjectcompression", "nopdfobjectcompression", -- "modulonumber", "dividenumber", -- @@ -403,12 +424,8 @@ return { "startluacode", "stopluacode", "startlua", "stoplua", "startctxfunction","stopctxfunction","ctxfunction", "startctxfunctiondefinition","stopctxfunctiondefinition", - "installctxfunction", "installctxfunctioncall", - "installprotectedctxfunction", "installprotectedctxfunctioncall", - "installctxscanner", "installctxscannercall", - "resetctxscanner", - "installprotectedctxscanner", "installprotectedctxscannercall", - "cldprocessfile", "cldloadfile", "cldcontext", "cldcommand", + "installctxfunction", "installprotectedctxfunction", "installprotectedctxscanner", "installctxscanner", "resetctxscanner", + "cldprocessfile", "cldloadfile", "cldloadviafile", "cldcontext", "cldcommand", -- "carryoverpar", "lastlinewidth", @@ -433,7 +450,8 @@ return { -- "nospace", "nospacing", "dospacing", -- - "naturalhbox", "naturalvbox", "naturalvtop", "naturalhpack", "naturalvpack", + "naturalhbox", "naturalvbox", "naturalvtop", "naturalhpack", "naturalvpack", "naturaltpack", + "reversehbox", "reversevbox", "reversevtop", "reversehpack", "reversevpack", "reversetpack", -- "frule", -- diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua index 1cd5f581007..579750bc97d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.lua @@ -231,35 +231,44 @@ return { "breakafterdirmode", "catcodetable", "clearmarks", - "copyfont", "compoundhyphenmode", + "copyfont", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", + "csstring", "draftmode", "dviextension", "dvifeedback", "dvivariable", "efcode", + "endlocalcontrol", "etoksapp", "etokspre", + "exceptionpenalty", "expanded", "expandglyphsinfont", "explicitdiscretionary", "explicithyphenpenalty", + "fixupboxesmode", "fontid", "formatname", "gleaders", + "gtoksapp", + "gtokspre", "hjcode", "hyphenationbounds", "hyphenationmin", "hyphenpenaltymode", "ifabsdim", "ifabsnum", + "ifcondition", "ifincsname", "ifprimitive", "ignoreligaturesinfont", + "immediateassigned", + "immediateassignment", "initcatcodetable", "insertht", "lastnamedcs", @@ -269,6 +278,7 @@ return { "lastxpos", "lastypos", "latelua", + "lateluafunction", "leftghost", "leftmarginkern", "letcharcode", @@ -280,6 +290,10 @@ return { "localleftbox", "localrightbox", "lpcode", + "luabytecode", + "luabytecodecall", + "luacopyinputnodes", + "luadef", "luaescapestring", "luafunction", "luafunctioncall", @@ -291,14 +305,17 @@ return { "mathdirection", "mathdisplayskipmode", "matheqnogapstep", + "mathflattenmode", "mathitalicsmode", "mathnolimitsmode", "mathoption", "mathpenaltiesmode", "mathrulesfam", "mathrulesmode", - "mathscriptsmode", + "mathrulethicknessmode", "mathscriptboxmode", + "mathscriptcharmode", + "mathscriptsmode", "mathstyle", "mathsurroundmode", "mathsurroundskip", @@ -362,6 +379,8 @@ return { "uniformdeviate", "useboxresource", "useimageresource", + "xtoksapp", + "xtokspre", }, ["omega"]={ "Omegaminorversion", @@ -422,15 +441,17 @@ return { "pdflastypos", "pdflinkmargin", "pdfliteral", + "pdfmajorversion", "pdfmapfile", "pdfmapline", - "pdfmajorversion", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", + "pdfomitcharset", + "pdfomitcidset", "pdfoutline", "pdfoutput", "pdfpageattr", @@ -447,6 +468,7 @@ return { "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", + "pdfrecompress", "pdfrefobj", "pdfrefxform", "pdfrefximage", @@ -522,7 +544,6 @@ return { "cr", "crcr", "csname", - "csstring", "day", "deadcycles", "def", @@ -580,6 +601,7 @@ return { "fontname", "futurelet", "gdef", + "glet", "global", "globaldefs", "halign", @@ -823,4 +845,4 @@ return { ["xetex"]={ "XeTeXversion", }, -} +} \ No newline at end of file diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv index 1b9195f4101..5ffb84d389c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-prm.mkiv @@ -55,7 +55,7 @@ "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfmajorversion", "pdfminorversion", "pdfnames", - "pdfnoligatures", "pdfnormaldeviate", "pdfobj", + "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfrecompress", "pdfobjcompresslevel", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode", @@ -68,6 +68,7 @@ "pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage", + "pdfomitcidset", "pdfomitcharset", }, aleph = { -- we don't bother "Alephminorversion", "Alephrevision", "Alephversion", diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv index 7000eed7bb9..fdb2ea73214 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/mult-sys.mkiv @@ -55,6 +55,7 @@ \definesystemconstant {danish} \definesystemconstant {da} \definesystemconstant {dutch} \definesystemconstant {nl} \definesystemconstant {english} \definesystemconstant {en} +\definesystemconstant {estonian} \definesystemconstant {et} \definesystemconstant {farsi} \definesystemconstant {fa} % just persian \definesystemconstant {finnish} \definesystemconstant {fi} \definesystemconstant {french} \definesystemconstant {fr} @@ -240,6 +241,7 @@ \definesystemconstant {next} \definesystemconstant {pickup} +\definesystemconstant {forget} \definesystemconstant {ascii} \definesystemconstant {default} \definesystemconstant {unknown} diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua b/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua index 03f6d747634..e6c6176026e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-acc.lua @@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['node-acc'] = { local nodes, node = nodes, node -local nodecodes = nodes.nodecodes local tasks = nodes.tasks local nuts = nodes.nuts @@ -16,6 +15,7 @@ local tonut = nodes.tonut local tonode = nodes.tonode local getid = nuts.getid +local getsubtype = nuts.getsubtype local getattr = nuts.getattr local getlist = nuts.getlist local getchar = nuts.getchar @@ -28,21 +28,28 @@ local setsubtype = nuts.setsubtype local getwidth = nuts.getwidth local setwidth = nuts.setwidth ------ traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph +local nextnode = nuts.traversers.node + ----- copy_node = nuts.copy local insert_after = nuts.insert_after local copy_no_components = nuts.copy_no_components +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes + local glue_code = nodecodes.glue ----- kern_code = nodecodes.kern local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local userskip_code = gluecodes.user +local spaceskip_code = gluecodes.spaceskip +local xspaceskip_code = gluecodes.xspaceskip + local a_characters = attributes.private("characters") -local threshold = 65536 -- not used local nofreplaced = 0 -- todo: nbsp etc @@ -50,6 +57,9 @@ local nofreplaced = 0 -- todo: maybe cache as we now create many nodes -- todo: check for subtype related to spacing (13/14 but most seems to be user anyway) +local trace = false trackers.register("backend.spaces", function(v) trace = v end) +local slot = nil + local function injectspaces(head) local p, p_id local n = head @@ -57,32 +67,42 @@ local function injectspaces(head) local id = getid(n) if id == glue_code then if p and getid(p) == glyph_code then - -- unless we don't care about the little bit of overhead - -- we can just: local g = copy_node(g) - local g = copy_no_components(p) - local a = getattr(n,a_characters) - setchar(g,32) - setlink(p,g,n) - setwidth(n,getwidth(n) - getwidth(g)) - if a then - setattr(g,a_characters,a) + local s = getsubtype(n) + if s == spaceskip_code or s == xspaceskip_code then + -- unless we don't care about the little bit of overhead + -- we can just: local g = copy_node(g) + local g = copy_no_components(p) + local a = getattr(n,a_characters) + setchar(g,slot) + setlink(p,g,n) + setwidth(n,getwidth(n) - getwidth(g)) + -- setsubtype(n,userskip_code) + if a then + setattr(g,a_characters,a) + end + setattr(n,a_characters,0) + nofreplaced = nofreplaced + 1 end - setattr(n,a_characters,0) - nofreplaced = nofreplaced + 1 end elseif id == hlist_code or id == vlist_code then - injectspaces(getlist(n),attribute) + injectspaces(getlist(n),slot) end p_id = id p = n n = getnext(n) end - return head, true -- always done anyway + return head end nodes.handlers.accessibility = function(head) - local head, done = injectspaces(tonut(head)) - return tonode(head), done + if trace then + if not slot then + slot = fonts.helpers.privateslot("visualspace") + end + else + slot = 32 + end + return injectspaces(head,slot) end statistics.register("inserted spaces in output",function() @@ -99,7 +119,7 @@ end) -- -- local function compact(n) -- local t = { } --- for n in traverse_id(glyph_code,n) do +-- for n in nextglyph, n do -- t[#t+1] = utfchar(getchar(n)) -- check for unicode -- end -- return concat(t,"") @@ -107,8 +127,7 @@ end) -- -- local function injectspans(head) -- local done = false --- for n in traverse_nodes(tonuts(head)) do --- local id = getid(n) +-- for n, id in nextnode, tonuts(head) do -- if id == disc then -- local r = getfield(n,"replace") -- local p = getfield(n,"pre") @@ -134,18 +153,17 @@ end) -- -- tasks.appendaction("processors", "words", "nodes.injectspans") -- --- local pdfpageliteral = nuts.pool.pdfpageliteral +-- local pageliteral = nuts.pool.pageliteral -- -- local function injectspans(head) -- local done = false --- for n in traverse_nodes(tonut(head)) do --- local id = getid(n) +-- for n, id in nextnode, tonut(head) do -- if id == disc then -- local a = getattr(n,a_hyphenated) -- if a then -- local str = codes[a] --- local b = pdfpageliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str))) --- local e = pdfpageliteral("EMC") +-- local b = pageliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str))) +-- local e = pageliteral("EMC") -- insert_before(head,n,b) -- insert_after(head,n,e) -- done = true diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua index 84567068bba..d6a9950fe8c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-aux.lua @@ -32,8 +32,6 @@ local getnext = nuts.getnext local getid = nuts.getid local getsubtype = nuts.getsubtype local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar local getattr = nuts.getattr local getboth = nuts.getboth local getcomponents = nuts.getcomponents @@ -51,8 +49,10 @@ local setprev = nuts.setprev local setcomponents = nuts.setcomponents local setattrlist = nuts.setattrlist -local traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id +----- traverse_nodes = nuts.traverse +----- traverse_id = nuts.traverse_id +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph local flush_node = nuts.flush local flush_list = nuts.flush_list local hpack_nodes = nuts.hpack @@ -154,9 +154,8 @@ function nodes.repackhlist(list,...) end local function set_attributes(head,attr,value) - for n in traverse_nodes(head) do + for n, id in nextnode, head do setattr(n,attr,value) - local id = getid(n) if id == hlist_node or id == vlist_node then set_attributes(getlist(n),attr,value) end @@ -164,11 +163,10 @@ local function set_attributes(head,attr,value) end local function set_unset_attributes(head,attr,value) - for n in traverse_nodes(head) do + for n, id in nextnode, head do if not getattr(n,attr) then setattr(n,attr,value) end - local id = getid(n) if id == hlist_code or id == vlist_code then set_unset_attributes(getlist(n),attr,value) end @@ -176,9 +174,8 @@ local function set_unset_attributes(head,attr,value) end local function unset_attributes(head,attr) - for n in traverse_nodes(head) do + for n, id in nextnode, head do setattr(n,attr,unsetvalue) - local id = getid(n) if id == hlist_code or id == vlist_code then unset_attributes(getlist(n),attr) end @@ -197,98 +194,11 @@ nuts.setattributes = set_attributes nodes.setattributes nuts.setunsetattributes = set_unset_attributes nodes.setunsetattributes = vianuts(set_unset_attributes) nuts.unsetattributes = unset_attributes nodes.unsetattributes = vianuts(unset_attributes) --- history: --- --- local function glyph_width(a) --- local ch = chardata[getfont(a)][getchar(a)] --- return (ch and ch.width) or 0 --- end --- --- local function glyph_total(a) --- local ch = chardata[getfont(a)][getchar(a)] --- return (ch and (ch.height+ch.depth)) or 0 --- end --- --- local function non_discardable(a) -- inline --- return getid(id) < math_node -- brrrr --- end --- --- local function calculate_badness(t,s) --- if t == 0 then --- return 0 --- elseif s <= 0 then --- return INF_BAD --- else --- local r --- if t <= 7230584 then --- r = t * 297 / s --- elseif s >= 1663497 then --- r = t / floor(s / 297) --- else --- r = t --- end --- r = floor(r) --- if r > 1290 then --- return INF_BAD --- else --- return floor((r * r * r + 0x20000) / 0x40000) -- 0400000 / 01000000 --- end --- end --- end --- --- left-overs --- --- local function round_xn_over_d(x, n, d) --- local positive -- was x >= 0 --- if x >= 0 then --- positive = true --- else --- x = -x --- positive = false --- end --- local t = floor(x % 0x8000) * n -- 0100000 --- local f = floor(t / 0x8000) -- 0100000 --- local u = floor(x / 0x8000) * n + f -- 0100000 --- local v = floor(u % d) * 0x8000 + f -- 0100000 --- if floor(u / d) >= 0x8000 then -- 0100000 --- report_parbuilders('arith_error') --- else --- u = 0x8000 * floor(u / d) + floor(v / d) -- 0100000 --- end --- v = floor(v % d) --- if 2*v >= d then --- u = u + 1 --- end --- if positive then --- return u --- else --- return -u --- end --- end --- --- local function firstline(n) --- while n do --- local id = getid(n) --- if id == hlist_code then --- if getsubtype(n) == line_code then --- return n --- else --- return firstline(getlist(n)) --- end --- elseif id == vlist_code then --- return firstline(getlist(n)) --- end --- n = getnext(n) --- end --- end --- --- nodes.firstline = firstline - function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 if untagged then return first_glyph(n) else - for g in traverse_id(glyph_code,n) do + for g in nextglyph ,n do return g end end @@ -297,8 +207,8 @@ end local function firstcharinbox(n) local l = getlist(getbox(n)) if l then - for g in traverse_id(glyph_code,l) do - return getchar(g) + for g, c in nextglyph, l do + return c end end return 0 @@ -431,10 +341,9 @@ nodes.link = function(list,currentfont,currentattr,head,tail) end local function locate(start,wantedid,wantedsubtype) - for n in traverse_nodes(start) do - local id = getid(n) + for n, id, subtype in nextnode, start do if id == wantedid then - if not wantedsubtype or getsubtype(n) == wantedsubtype then + if not wantedsubtype or subtype == wantedsubtype then return n end elseif id == hlist_code or id == vlist_code then @@ -490,87 +399,6 @@ end -- end -- end --- these component helpers might move to another module - --- nodemode helper: here we also flatten components, no check for disc here - -function nuts.set_components(target,start,stop) - local head = getcomponents(target) - if head then - flush_list(head) - head = nil - end - if start then - setprev(start) - else - return nil - end - if stop then - setnext(stop) - end - local tail = nil - while start do - local c = getcomponents(start) - local n = getnext(start) - if c then - if head then - setlink(tail,c) - else - head = c - end - tail = find_tail(c) - setcomponents(start) - flush_node(start) - else - if head then - setlink(tail,start) - else - head = start - end - tail = start - end - start = n - end - setcomponents(target,head) - -- maybe also upgrade the subtype but we don't use it anyway - return head -end - -function nuts.get_components(target) - return getcomponents(target) -end - -nuts.get_components = getcomponents - -function nuts.take_components(target) - local c = getcomponents(target) - setcomponents(target) - -- maybe also upgrade the subtype but we don't use it anyway - return c -end - --- nodemode helper: we assume a glyph and a flat components list (basemode can --- have nested components) - -function nuts.count_components(n,marks) - local components = getcomponents(n) - if components then - if marks then - local i = 0 - for g in traverse_id(glyph_code,components) do - if not marks[getchar(g)] then - i = i + 1 - end - end - return i - else - return count(glyph_code,components) - end - else - return 0 - end -end - -- nodemode helper: the next and prev pointers are untouched function nuts.copy_no_components(g,copyinjection) @@ -596,7 +424,7 @@ end function nuts.copy_only_glyphs(current) local head = nil local previous = nil - for n in traverse_id(glyph_code,current) do + for n in nextglyph, current do n = copy_node(n) if head then setlink(previous,n) diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua b/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua index 4ed5abe5e5e..a19e5e969a7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-bck.lua @@ -9,178 +9,288 @@ if not modules then modules = { } end modules ['node-bck'] = { -- beware, this one takes quite some runtime, so we need a status flag -- maybe some page related state +-- todo: done (or just get rid of done altogether) ... saves no purpose +-- any longer + local attributes, nodes, node = attributes, nodes, node -local enableaction = nodes.tasks.enableaction +local enableaction = nodes.tasks.enableaction -local nodecodes = nodes.nodecodes -local listcodes = nodes.listcodes +local nodecodes = nodes.nodecodes +local listcodes = nodes.listcodes -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local cell_code = listcodes.cell +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist -local nuts = nodes.nuts -local nodepool = nuts.pool +local alignmentlist_code = listcodes.alignment +local celllist_code = listcodes.cell -local tonode = nuts.tonode -local tonut = nuts.tonut +local nuts = nodes.nuts +local nodepool = nuts.pool -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local getsubtype = nuts.getsubtype -local getwhd = nuts.getwhd +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getlist = nuts.getlist +local getattr = nuts.getattr +local getsubtype = nuts.getsubtype +local getwhd = nuts.getwhd +local getwidth = nuts.getwidth +local getprop = nuts.getprop -local setattr = nuts.setattr -local setlink = nuts.setlink -local setlist = nuts.setlist +local setattr = nuts.setattr +local setlink = nuts.setlink +local setlist = nuts.setlist +local setattributelist = nuts.setattributelist +local setprop = nuts.setprop -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id +local takebox = nuts.takebox +local findtail = nuts.tail -local new_rule = nodepool.rule -local new_glue = nodepool.glue +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist +local nextlist = nuts.traversers.list -local a_color = attributes.private('color') -local a_transparency = attributes.private('transparency') -local a_colormodel = attributes.private('colormodel') -local a_background = attributes.private('background') -local a_alignbackground = attributes.private('alignbackground') +local flush_node_list = nuts.flush_list -local function add_backgrounds(head) -- rather old code .. to be redone - local current = head - while current do - local id = getid(current) - if id == hlist_code or id == vlist_code then - local list = getlist(current) - if list then - local head = add_backgrounds(list) - if head then - setlist(current,head) - list = head - end +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_hlist = nodepool.hlist + +local privateattributes = attributes.private +local unsetvalue = attributes.unsetvalue + +local linefillers = nodes.linefillers + +local a_color = privateattributes("color") +local a_transparency = privateattributes("transparency") +local a_colormodel = privateattributes("colormodel") +local a_background = privateattributes("background") +local a_alignbackground = privateattributes("alignbackground") +local a_linefiller = privateattributes("linefiller") +local a_ruled = privateattributes("ruled") + +local trace_alignment = false +local report_alignment = logs.reporter("backgrounds","alignment") + +trackers.register("backgrounds.alignments",function(v) trace_alignment = v end) + +-- We can't use listbuilders with where=alignment because at that stage we have +-- unset boxes. Also, post_linebreak is unsuitable for nested processing as we +-- get the same stuff many times (wrapped again and again). +-- +-- After many experiments with different callbacks the shipout is still the best +-- place but then we need to store some settings longer or save them with the node. +-- For color only we can get away with it with an extra attribute flagging a row +-- but for more complex stuff we can better do as we do here now. + +local overshoot = math.floor(65781/5) -- could be an option per table (just also store it) + +local function colored_a(current,list,template,id) + local width, height, depth = getwhd(current) + local total = height + depth + if width > 0 and total > 0 then + local rule = nil + -- + local a = getattr(template,a_linefiller) + if a then + local d = linefillers.data[a%1000] + if d then + rule = linefillers.filler(template,d,width,height,depth) + end + end + -- + if not rule then + rule = new_rule(width,height,depth) + end + setattributelist(rule,template) + local back = new_kern(-((id == vlist_code and total) or width)) + return setlink(rule,back,list) + end +end + +local function colored_b(current,list,template,id,indent) + local width, height, depth = getwhd(current) + local total = height + depth + if width > 0 and total > 0 then + local fore = (indent ~= 0) and new_kern(indent) + local rule = nil + -- + local a = getattr(template,a_linefiller) + if a then + local d = linefillers.data[a%1000] + if d then + rule = linefillers.filler(template,d,width-indent,height,depth) end - local width, height, depth = getwhd(current) - if width > 0 then - local background = getattr(current,a_background) + end + -- + if not rule then + rule = new_rule(width-indent,height+overshoot,depth+overshoot) + setattributelist(rule,template) + end + if overshoot == 0 then + local back = new_kern(-((id == vlist_code and total) or width)) + return setlink(fore,rule,back,list) + else + rule = new_hlist(rule) + return setlink(fore,rule,list) + end + end +end + +local templates = { } +local currentrow = 0 +local enabled = false +local alignments = false + +local function add_alignbackgrounds(head,list) + for current, id, subtype, list in nextlist, list do + if list and id == hlist_code and subtype == celllist_code then + for template in nexthlist, list do + local background = getattr(template,a_alignbackground) if background then - -- direct to hbox - -- colorspace is already set so we can omit that and stick to color - local mode = getattr(current,a_colormodel) - if mode then - local skip = id == hlist_code and width or (height + depth) - local glue = new_glue(-skip) - local rule = new_rule(width,height,depth) - local color = getattr(current,a_color) - local transparency = getattr(current,a_transparency) - setattr(rule,a_colormodel,mode) - if color then - setattr(rule,a_color,color) - end - if transparency then - setattr(rule,a_transparency,transparency) - end --- setlink(rule,glue) --- if list then --- setlink(glue,list) --- end --- setlist(current,rule) - setlist(current,rule,glue,list) + local list = colored_a(current,list,template) + if list then + setlist(current,list) end + setattr(template,a_alignbackground,unsetvalue) -- or property end + break end end - current = getnext(current) end - return head, true + local template = getprop(head,"alignmentchecked") + if template then + list = colored_b(head,list,template[1],hlist_code,template[2]) + flush_node_list(template) + templates[currentrow] = false + return list + end end -local function add_alignbackgrounds(head) - local current = head - while current do - local id = getid(current) - if id == hlist_code then - local list = getlist(current) - if not list then - -- no need to look - elseif getsubtype(current) == cell_code then - local background = nil - local found = nil - -- for l in traverse(list) do - -- background = getattr(l,a_alignbackground) - -- if background then - -- found = l - -- break - -- end - -- end - -- we know that it's a fake hlist (could be user node) - -- but we cannot store tables in user nodes yet - for l in traverse_id(hpack_code,list) do - background = getattr(l,a_alignbackground) - if background then - found = l +local function add_backgrounds(head,id,list) + if list then + for current, id, subtype, list in nextlist, list do + if list then + if alignments and subtype == alignmentlist_code then + local l = add_alignbackgrounds(current,list) + if l then + list = l + setlist(current,list) end - break end - -- - if background then - -- current has subtype 5 (cell) - local width, height, depth = getwhd(current) - if width > 0 then - local mode = getattr(found,a_colormodel) - if mode then - local glue = new_glue(-width) - local rule = new_rule(width,height,depth) - local color = getattr(found,a_color) - local transparency = getattr(found,a_transparency) - setattr(rule,a_colormodel,mode) - if color then - setattr(rule,a_color,color) - end - if transparency then - setattr(rule,a_transparency,transparency) - end - setlink(rule,glue) - if list then - setlink(glue,list) - end - setlist(current,rule) - end - end + local l = add_backgrounds(current,id,list) + if l then + list = l + setlist(current,l) end - else - add_alignbackgrounds(list) end - elseif id == vlist_code then - local list = getlist(current) - if list then - add_alignbackgrounds(list) + end + end + if id == hlist_code or id == vlist_code then + local background = getattr(head,a_background) + if background then + list = colored_a(head,list,head,id) + -- not needed + setattr(head,a_background,unsetvalue) -- or property + return list + end + end +end + +function nodes.handlers.backgrounds(head) + add_backgrounds(head,getid(head),getlist(head)) + return head +end + +function nodes.handlers.backgroundspage(head,where) + if head and where == "alignment" then + for n in nexthlist, head do + local p = getprop(n,"alignmentchecked") + if not p and getsubtype(n) == alignmentlist_code then + currentrow = currentrow + 1 + local template = templates[currentrow] + if trace_alignment then + report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-") + end + setprop(n,"alignmentchecked",template) end end - current = getnext(current) end - return head, true + return head end --- nodes.handlers.backgrounds = add_backgrounds --- nodes.handlers.alignbackgrounds = add_alignbackgrounds +function nodes.handlers.backgroundsvbox(head,where) + if head and where == "vbox" then + local list = getlist(head) + if list then + for n in nexthlist, list do + local p = getprop(n,"alignmentchecked") + if not p and getsubtype(n) == alignmentlist_code then + currentrow = currentrow + 1 + local template = templates[currentrow] + if trace_alignment then + report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-") + end + setprop(n,"alignmentchecked",template) + end + end + end + end + return head +end -nodes.handlers.backgrounds = function(head) local head, done = add_backgrounds (tonut(head)) return tonode(head), done end -nodes.handlers.alignbackgrounds = function(head) local head, done = add_alignbackgrounds(tonut(head)) return tonode(head), done end +-- interfaces.implement { +-- name = "enablebackgroundboxes", +-- onlyonce = true, +-- actions = enableaction, +-- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" } +-- } +-- +-- doing it in the shipout works as well but this is nicer + +local function enable(alignmentstoo) + if not enabled then + enabled = true + enableaction("shipouts","nodes.handlers.backgrounds") + end + if not alignments and alignmentstoo then + alignments = true + enableaction("vboxbuilders","nodes.handlers.backgroundsvbox") + enableaction("mvlbuilders", "nodes.handlers.backgroundspage") + end +end interfaces.implement { name = "enablebackgroundboxes", onlyonce = true, - actions = enableaction, - arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" } + actions = enable, } interfaces.implement { name = "enablebackgroundalign", onlyonce = true, - actions = enableaction, - arguments = { "'shipouts'", "'nodes.handlers.alignbackgrounds'" } + actions = function() + enable(true) + end, +} + +interfaces.implement { + name = "setbackgroundrowdata", + arguments = { "integer", "integer", "dimension" }, + actions = function(row,box,indent) + row = row -1 -- better here than in tex + if box == 0 then + templates[row] = false + else + templates[row] = { takebox(box), indent } + end + end, +} + +interfaces.implement { + name = "resetbackgroundrowdata", + actions = function() + currentrow = 0 + end, } diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv index 6bfc43d6a41..b093274430c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/node-bck.mkiv @@ -16,12 +16,10 @@ %D This is first attempt to replacing backgrounds in a few tables %D mechanisms. When used more frequently, we can store the color %D spec in the attribute. -%D -%D Maybe move some to the bar handler. \unprotect -\registerctxluafile{node-bck}{} +\registerctxluafile{node-bck}{optimize} % \backgroundvbox[green] {\input tufte } \par % \backgroundvbox[blue] {\input ward } \par @@ -74,6 +72,9 @@ \unexpanded\def\backgroundvbox{\node_backgrounds_boxes_add\vbox} \unexpanded\def\backgroundvtop{\node_backgrounds_boxes_add\vtop} +\unexpanded\def\backgroundline{\dontleavehmode + \node_backgrounds_boxes_add\hbox} + % \def\node_backgrounds_boxes_add#1[#2]% % {\begingroup % \clf_enablebackgroundboxes @@ -90,18 +91,4 @@ {\clf_enablebackgroundboxes #1\backgroundcolorattr{#2}} -% less argument carry over: -% -% \def\node_backgrounds_boxes_add#1[#2]% -% {\clf_enablebackgroundboxes#1% -% \ifcsname\??colorattribute\currentcolorprefix#2\endcsname -% \thebackgroundcolorattr{\currentcolorprefix#2}% -% \else\ifcsname\??colorattribute#2\endcsname -% \thebackgroundcolorattr{#2}% -% \fi\fi} - -% \def\backgroundvbox[#1]{\vbox \backgroundcolorattr{#1}} -% \def\backgroundvtop[#1]{\vtop \backgroundcolorattr{#1}} -% \def\backgroundhbox[#1]{\hbox \backgroundcolorattr{#1}} - \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua index 59564ac93bd..3f0cba67e91 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-dir.lua @@ -6,304 +6,61 @@ if not modules then modules = { } end modules ['node-dir'] = { license = "see context related readme files" } ---[[ -

In the process of cleaning up the lua variant of the parbuilder -we ran into a couple of functions (translated c macros) that were -somewhat inefficient. More convenient is to use hashes although at -the c-end still macros are used. In the process directions.h was -adapted and now has the mappings as comments. This lua file is -based on that file. -]]-- - -local allocate = utilities.storage.allocate - -local nodes = nodes - -nodes.is_mirrored = allocate { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, -} - -nodes.is_rotated = allocate { -- used - -- TLT = false, - -- TRT = false, - -- LTL = false, - RTT = true, ["+RTT"] = true, -} - -nodes.textdir_is_parallel = allocate { -- used - TLT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - TRT= { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, - RTT = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - } -} - -nodes.pardir_is_parallel = allocate { - TLT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - TRT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, - RTT = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, -} - -nodes.pardir_is_opposite = allocate { - TLT = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - TRT = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - RTT = true, ["+RTT"] = true, - }, - RTT = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - -- RTT = false, - }, -} - -nodes.textdir_is_opposite = allocate { -- used - TLT = { - -- TLT = false, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - TRT= { - TLT = true, ["+TLT"] = true, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - RTT = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, -} - -nodes.glyphdir_is_opposite = allocate { - TLT = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - TRT= { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - RTT = { - -- TLT = false, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, -} - -nodes.pardir_is_equal = allocate { -- used - TLT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - TRT= { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - LTL= { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - -- RTT = false, - }, - RTT= { - -- TLT = false, - -- TRT = false, - -- LTL = false, - RTT = true, ["+RTT"] = true, - }, -} - -nodes.textdir_is_equal = allocate { -- used - TLT = { - TLT = true, ["+TLT"] = true, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - TRT= { - -- TLT = false, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, - LTL = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, - RTT = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, -} - -nodes.glyphdir_is_equal = allocate { -- used - TLT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - RTT = true, ["+RTT"] = true, - }, - TRT= { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - RTT = true, ["+RTT"] = true, - }, - LTL = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - -- RTT = false, - }, - RTT = { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - -- LTL = false, - RTT = true, ["+RTT"] = true, - }, -} - -nodes.partextdir_is_equal = allocate { - TLT = { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, - TRT= { - -- TLT = false, - -- TRT = false, - LTL = true, ["+LTL"] = true, - RTT = true, ["+RTT"] = true, - }, - LTL = { - TLT = true, ["+TLT"] = true, - -- TRT = false, - -- LTL = false, - -- RTT = false, - }, - RTT = { - -- TLT = false, - TRT = true, ["+TRT"] = true, - -- LTL = false, - -- RTT = false, - }, -} - -nodes.textdir_is_is = allocate { - TLT = true, ["+TLT"] = true, - -- TRT = false, - -- LTL = false, - -- RTT = false, -} - -nodes.glyphdir_is_orthogonal = allocate { - TLT = true, ["+TLT"] = true, - TRT = true, ["+TRT"] = true, - LTL = true, ["+LTL"] = true, - -- RTT = false -} - -nodes.dir_is_pop = allocate { -- used - ["-TRT"] = true, - ["-TLT"] = true, - ["-LTL"] = true, - ["-RTT"] = true, -} - -nodes.dir_negation = allocate { -- used - ["-TRT"] = "+TRT", - ["-TLT"] = "+TLT", - ["-LTL"] = "+LTL", - ["-RTT"] = "+RTT", - ["+TRT"] = "-TRT", - ["+TLT"] = "-TLT", - ["+LTL"] = "-LTL", - ["+RTT"] = "-RTT", -} +-- This is experimental code, so when I change it I need to check other modules +-- too. +-- +-- Local par nodes are somewhat special. They start a paragraph and then register +-- the par direction. But they can also show op mid paragraph in which case they +-- register boxes and penalties. In that case the direction should not be affected. +-- +-- We can assume that when hpack and prelinebreak filters are called, a local par +-- still sits at the head, but after a linebreak pass this node can be after the +-- leftskip (when present). + +local nodes = nodes +local nuts = nodes.nuts + +local nodecodes = nodes.nodecodes +local localpar_code = nodecodes.localpar + +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getdirection = nuts.getdirection + +local dirvalues = nodes.dirvalues +local lefttoright = dirvalues.lefttoright +local righttoleft = dirvalues.righttoleft + +local localparnewgraf_code = 0 + +local function newstack(head,direction) + local stack = { } + local top = 0 + if head and getid(head) == localpar_code and getsubtype(head) == localparnewgraf_code then + direction = getdirection(head) + end + if not direction then + direction = lefttoright + elseif direction == "TLT" then + direction = lefttoright + elseif direction == "TRT" then + direction = righttoleft + end + local function update(node) + local dir, pop = getdirection(node) + if not pop then + top = top + 1 + stack[top] = dir + return dir + elseif top == 0 then + return direction + elseif top == 1 then + top = 0 + return direction + else + top = top - 1 + return stack[top] + end + end + return direction, update +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua index 975eb0becc0..dc681d16556 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-fin.lua @@ -16,16 +16,15 @@ local next, type, format = next, type, string.format local attributes, nodes, node = attributes, nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext -local getprev = nuts.getprev local getid = nuts.getid local getlist = nuts.getlist local getleader = nuts.getleader local getattr = nuts.getattr local getwidth = nuts.getwidth +local getwhd = nuts.getwhd +local getorientation = nuts.getorientation local setlist = nuts.setlist local setleader = nuts.setleader @@ -34,10 +33,22 @@ local copy_node = nuts.copy local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after +local nextnode = nuts.traversers.node + local nodecodes = nodes.nodecodes -local whatcodes = nodes.whatcodes local rulecodes = nodes.rulecodes +----- normalrule_code = rulecodes.normal +local boxrule_code = rulecodes.box +local imagerule_code = rulecodes.image +local emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +----- outlinerule_code = rulecodes.outline + local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc local glue_code = nodecodes.glue @@ -82,37 +93,34 @@ local finalizer = plugin.finalizer local flusher = plugin.flusher if not processor then return function(head) - return head, false + return head end elseif initializer or finalizer or resolver then return function(head) starttiming(attributes) - local done, used, ok, inheritance = false, nil, false, nil + local used, inheritance if resolver then inheritance = resolver() end if initializer then initializer(namespace,attribute,head) end - head, ok = processor(namespace,attribute,head,inheritance) - if ok then - if finalizer then - head, ok, used = finalizer(namespace,attribute,head) - if used and flusher then - head = flusher(namespace,attribute,head,used) - end + head = processor(namespace,attribute,head,inheritance) + if finalizer then + head, used = finalizer(namespace,attribute,head) + if used and flusher then + head = flusher(namespace,attribute,head,used) end - done = true end stoptiming(attributes) - return head, done + return head end else return function(head) starttiming(attributes) - local head, done = processor(namespace,attribute,head) + head = processor(namespace,attribute,head) stoptiming(attributes) - return head, done + return head end end nodes.plugindata = nil @@ -126,7 +134,7 @@ end -- the injectors local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger -local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! +local current, current_selector = 0, 0 -- nb, stack has a local current ! local nsbegin, nsend, nsreset function states.initialize(namespace,attribute,head) @@ -138,7 +146,6 @@ function states.initialize(namespace,attribute,head) nstrigger = triggering and namespace.triggering and a_trigger current = 0 current_selector = 0 - done = false -- todo: done cleanup nsstep = namespace.resolve_step if nsstep then nsreset = namespace.resolve_reset @@ -151,7 +158,6 @@ end function states.finalize(namespace,attribute,head) -- is this one ok? if current > 0 and nsnone then - head = tonut(head) local id = getid(head) if id == hlist_code or id == vlist_code then local content = getlist(head) @@ -164,20 +170,17 @@ function states.finalize(namespace,attribute,head) -- is this one ok? else head = insert_node_before(head,head,copy_node(nsnone)) end - return tonode(head), true, true + return head, true end - return head, false, false + return head, false end -- we need to deal with literals too (reset as well as oval) local function process(attribute,head,inheritance,default) -- one attribute - local stack = head - local done = false local check = false local leader = nil - while stack do - local id = getid(stack) + for stack, id in nextnode, head do if id == glyph_code or id == disc_code then check = true -- disc no longer needed as we flatten replace elseif id == glue_code then @@ -188,39 +191,52 @@ local function process(attribute,head,inheritance,default) -- one attribute elseif id == hlist_code or id == vlist_code then local content = getlist(stack) if content then + -- tricky checking + local outer + if getorientation(stack) then + outer = getattr(stack,attribute) + if outer then + if default and outer == inheritance then + if current ~= default then + head = insert_node_before(head,stack,copy_node(nsdata[default])) + current = default + end + elseif current ~= outer then + head = insert_node_before(head,stack,copy_node(nsdata[c])) + current = outer + end + elseif default and inheritance then + if current ~= default then + head = insert_node_before(head,stack,copy_node(nsdata[default])) + current = default + end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current = 0 + end + end -- begin nested -- + local list if nstrigger and getattr(stack,nstrigger) then - local outer = getattr(stack,attribute) + if not outer then + outer = getattr(stack,attribute) + end if outer ~= inheritance then - local list, ok = process(attribute,content,inheritance,outer) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,outer) else - local list, ok = process(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,default) end else - local list, ok = process(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,default) + end + if content ~= list then + setlist(stack,list) end -- end nested -- end elseif id == rule_code then - check = getwidth(stack) ~= 0 + local wd, ht, dp = getwhd(stack) + check = wd ~= 0 or (ht+dp) ~= 0 end -- much faster this way than using a check() and nested() function if check then @@ -230,12 +246,10 @@ local function process(attribute,head,inheritance,default) -- one attribute if current ~= default then head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default - done = true end elseif current ~= c then head = insert_node_before(head,stack,copy_node(nsdata[c])) current = c - done = true end if leader then local savedcurrent = current @@ -247,33 +261,19 @@ local function process(attribute,head,inheritance,default) -- one attribute current = 0 end -- begin nested -- + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = process(attribute,leader,inheritance,outer) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,outer) else - local list, ok = process(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,default) end else - local list, ok = process(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,default) + end + if leader ~= list then + setleader(stack,list) end -- end nested -- current = savedcurrent @@ -283,23 +283,19 @@ local function process(attribute,head,inheritance,default) -- one attribute if current ~= default then head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default - done = true end elseif current > 0 then head = insert_node_before(head,stack,copy_node(nsnone)) current = 0 - done = true end check = false end - stack = getnext(stack) end - return head, done + return head end states.process = function(namespace,attribute,head,default) - local head, done = process(attribute,tonut(head),default) - return tonode(head), done + return process(attribute,head,default) end -- we can force a selector, e.g. document wide color spaces, saves a little @@ -309,13 +305,9 @@ end -- each other with the same color but different color spaces e.g. \showcolor) local function selective(attribute,head,inheritance,default) -- two attributes - -- local head = head - local stack = head - local done = false local check = false local leader = nil - while stack do - local id = getid(stack) + for stack, id, subtype in nextnode, head do if id == glyph_code or id == disc_code then check = true -- disc no longer needed as we flatten replace elseif id == glue_code then @@ -326,41 +318,66 @@ local function selective(attribute,head,inheritance,default) -- two attributes elseif id == hlist_code or id == vlist_code then local content = getlist(stack) if content then + -- tricky checking + local outer + if getorientation(stack) then + outer = getattr(stack,attribute) + if outer then + if default and outer == inheritance then + if current ~= default then + local data = nsdata[default] + head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) + current = default + end + else + local s = getattr(stack,nsselector) + -- local s = nsforced or getattr(stack,nsselector) + if current ~= outer or current_selector ~= s then + local data = nsdata[outer] + head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector])) + current = outer + current_selector = s + end + end + elseif default and inheritance then + if current ~= default then + local data = nsdata[default] + head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) + current = default + end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current, current_selector = 0, 0 + end + end -- begin nested + local list if nstrigger and getattr(stack,nstrigger) then - local outer = getattr(stack,attribute) + if not outer then + outer = getattr(stack,attribute) + end if outer ~= inheritance then - local list, ok = selective(attribute,content,inheritance,outer) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,outer) else - local list, ok = selective(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,default) end else - local list, ok = selective(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,default) + end + if content ~= list then + setlist(stack,list) end -- end nested end elseif id == rule_code then - check = getwidth(stack) ~= 0 + if subtype == boxrule_code or subtype == imagerule_code or subtype == emptyrule_code then + -- so no redundant color stuff (only here, layers for instance should obey) + check = false + else + local wd, ht, dp = getwhd(stack) + check = wd ~= 0 or (ht+dp) ~= 0 + end end - if check then local c = getattr(stack,attribute) if c then @@ -369,9 +386,6 @@ local function selective(attribute,head,inheritance,default) -- two attributes local data = nsdata[default] head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) current = default - if ok then - done = true - end end else local s = getattr(stack,nsselector) @@ -379,43 +393,25 @@ local function selective(attribute,head,inheritance,default) -- two attributes if current ~= c or current_selector ~= s then local data = nsdata[c] head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector])) - -- head = insert_node_before(head,stack,copy_node(data[s or nsselector])) current = c current_selector = s - if ok then - done = true - end end end if leader then -- begin nested + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = selective(attribute,leader,inheritance,outer) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,outer) else - local list, ok = selective(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,default) end else - local list, ok = selective(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,default) + end + if leader ~= list then + setleader(stack,list) end -- end nested leader = false @@ -425,22 +421,19 @@ local function selective(attribute,head,inheritance,default) -- two attributes local data = nsdata[default] head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) current = default - done = true end elseif current > 0 then head = insert_node_before(head,stack,copy_node(nsnone)) - current, current_selector, done = 0, 0, true + current, current_selector = 0, 0 end check = false end - stack = getnext(stack) end - return head, done + return head end states.selective = function(namespace,attribute,head,default) - local head = selective(attribute,tonut(head),default) - return tonode(head), true + return selective(attribute,head,default) end -- Ideally the next one should be merged with the previous but keeping it separate is @@ -454,7 +447,6 @@ end local function stacked(attribute,head,default) -- no triggering, no inheritance, but list-wise local stack = head - local done = false local current = default or 0 local depth = 0 local check = false @@ -472,42 +464,30 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, local content = getlist(stack) if content then -- the problem is that broken lines gets the attribute which can be a later one + local list if nslistwise then local a = getattr(stack,attribute) if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current current = a head = insert_node_before(head,stack,copy_node(nsdata[a])) - local list = stacked(attribute,content,current) -- two return values - if content ~= list then - setlist(stack,list) - end + list = stacked(attribute,content,current) -- two return values head, stack = insert_node_after(head,stack,copy_node(nsnone)) current = p - done = true else - local list, ok = stacked(attribute,content,current) - if content ~= list then - setlist(stack,list) -- only if ok - end - if ok then - done = true - end + list = stacked(attribute,content,current) end else - local list, ok = stacked(attribute,content,current) - if content ~= list then - setlist(stack,list) -- only if ok - end - if ok then - done = true - end + list = stacked(attribute,content,current) + end + if content ~= list then + setlist(stack,list) -- only if ok end end elseif id == rule_code then - check = getwidth(stack) ~= 0 + local wd, ht, dp = getwhd(stack) + check = wd ~= 0 or (ht+dp) ~= 0 end - if check then local a = getattr(stack,attribute) if a then @@ -515,15 +495,14 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_before(head,stack,copy_node(nsdata[a])) depth = depth + 1 current = a - done = true end if leader then - local list, ok = stacked(attribute,content,current) - if leader ~= list then - setleader(stack,list) -- only if ok - end - if ok then - done = true + local content = getlist(leader) + if content then + local list = stacked(attribute,content,current) + if leader ~= list then + setleader(stack,list) -- only if ok + end end leader = false end @@ -533,7 +512,6 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_before(head,stack,copy_node(nsnone)) depth = depth - 1 current = 0 - done = true end check = false end @@ -543,24 +521,22 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_after(head,stack,copy_node(nsnone)) depth = depth - 1 end - return head, done + return head end states.stacked = function(namespace,attribute,head,default) - local head, done = stacked(attribute,tonut(head),default) - return tonode(head), done + return stacked(attribute,head,default) end -- experimental local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise --- nsbegin() + -- nsbegin() local stacked = false local current = head local previous = head - local done = false local attrib = default or unsetvalue local check = false local leader = false @@ -576,38 +552,27 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, end elseif id == hlist_code or id == vlist_code then local content = getlist(current) - if not content then - -- skip - elseif nslistwise then - local a = getattr(current,attribute) - if a and attrib ~= a and nslistwise[a] then -- viewerlayer - head = insert_node_before(head,current,copy_node(nsdata[a])) - local list = stacker(attribute,content,a) - if list ~= content then - setlist(current,list) + if content then + local list + if nslistwise then + local a = getattr(current,attribute) + if a and attrib ~= a and nslistwise[a] then -- viewerlayer + head = insert_node_before(head,current,copy_node(nsdata[a])) + list = stacker(attribute,content,a) + head, current = insert_node_after(head,current,copy_node(nsnone)) + else + list = stacker(attribute,content,attrib) end - done = true - head, current = insert_node_after(head,current,copy_node(nsnone)) else - local list, ok = stacker(attribute,content,attrib) - if content ~= list then - setlist(current,list) - end - if ok then - done = true - end + list = stacker(attribute,content,default) end - else - local list, ok = stacker(attribute,content,default) if list ~= content then setlist(current,list) end - if ok then - done = true - end end elseif id == rule_code then - check = getwidth(current) ~= 0 + local wd, ht, dp = getwhd(current) + check = wd ~= 0 or (ht+dp) ~= 0 end if check then @@ -619,16 +584,22 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, end local n = nsstep(a) if n then - head = insert_node_before(head,current,tonut(n)) -- a + head = insert_node_before(head,current,n) -- a end attrib = a - done = true if leader then -- tricky as a leader has to be a list so we cannot inject before - local list, ok = stacker(attribute,leader,attrib) - if ok then - done = true + -- local list = stacker(attribute,leader,attrib) + -- leader = false + + local content = getlist(leader) + if content then + local list = stacker(attribute,leader,attrib) + if leader ~= list then + setleader(current,list) + end end + leader = false end end @@ -642,18 +613,101 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, if stacked then local n = nsend() while n do - head = insert_node_after(head,previous,tonut(n)) + head = insert_node_after(head,previous,n) n = nsend() end end - return head, done + return head end +-- local nextid = nodes.nuts.traversers.id +-- +-- local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise +-- +-- -- nsbegin() +-- local stacked = false +-- +-- local current = head +-- local previous = head +-- local attrib = default or unsetvalue +-- local check = false +-- local leader = false +-- +-- local id = getid(current) +-- while current do +-- if id == glyph_code then +-- check = true +-- elseif id == glue_code then +-- leader = getleader(current) +-- if leader then +-- check = true +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = getlist(current) +-- if content then +-- local list +-- if nslistwise then +-- local a = getattr(current,attribute) +-- if a and attrib ~= a and nslistwise[a] then -- viewerlayer +-- head = insert_node_before(head,current,copy_node(nsdata[a])) +-- list = stacker(attribute,content,a) +-- head, current = insert_node_after(head,current,copy_node(nsnone)) +-- else +-- list = stacker(attribute,content,attrib) +-- end +-- else +-- list = stacker(attribute,content,default) +-- end +-- if list ~= content then +-- setlist(current,list) +-- end +-- end +-- elseif id == rule_code then +-- check = getwidth(current) ~= 0 +-- end +-- +-- if check then +-- local a = getattr(current,attribute) or unsetvalue +-- if a ~= attrib then +-- if not stacked then +-- stacked = true +-- nsbegin() +-- end +-- local n = nsstep(a) +-- if n then +-- head = insert_node_before(head,current,n) -- a +-- end +-- attrib = a +-- if leader then +-- -- tricky as a leader has to be a list so we cannot inject before +-- local list = stacker(attribute,leader,attrib) +-- leader = false +-- end +-- end +-- check = false +-- end +-- +-- previous = current +-- +-- current, id = nextid(current,current) +-- end +-- +-- if stacked then +-- local n = nsend() +-- while n do +-- head = insert_node_after(head,previous,n) +-- n = nsend() +-- end +-- end +-- +-- return head +-- end + states.stacker = function(namespace,attribute,head,default) - local head, done = stacker(attribute,tonut(head),default) + local head = stacker(attribute,head,default) nsreset() - return tonode(head), done + return head end -- -- -- diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv index 4f1ff2aba41..086b19ae5dc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/node-fin.mkiv @@ -18,8 +18,8 @@ \unprotect -\registerctxluafile{node-shp}{} -\registerctxluafile{node-fin}{} % we might generalize this one +\registerctxluafile{node-shp}{optimize} +\registerctxluafile{node-fin}{optimize} % we might generalize this one % we might have two variants at some point (efficiency) diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua index f846f996d52..154853121d0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua @@ -37,22 +37,20 @@ local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming local nodecodes = nodes.nodecodes +local boundarycodes = nodes.boundarycodes + local handlers = nodes.handlers local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getattr = nuts.getattr local getid = nuts.getid -local getfont = nuts.getfont local getsubtype = nuts.getsubtype -local getchar = nuts.getchar local getdisc = nuts.getdisc local getnext = nuts.getnext local getprev = nuts.getprev local getboth = nuts.getboth -local getfield = nuts.getfield +local getdata = nuts.getdata ----- getdisc = nuts.getdisc local setchar = nuts.setchar local setlink = nuts.setlink @@ -62,14 +60,18 @@ local setprev = nuts.setprev local isglyph = nuts.isglyph -- unchecked local ischar = nuts.ischar -- checked -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char -local protect_glyph = nuts.protect_glyph +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextboundary = nuts.traversers.boundary +local nextdisc = nuts.traversers.disc +local nextchar = nuts.traversers.char + local flush_node = nuts.flush local disc_code = nodecodes.disc local boundary_code = nodecodes.boundary -local word_boundary = nodes.boundarycodes.word + +local wordboundary_code = boundarycodes.word local protect_glyphs = nuts.protect_glyphs local unprotect_glyphs = nuts.unprotect_glyphs @@ -144,10 +146,10 @@ local kerning = nuts.kerning -- -- -- this will go away -- --- local disccodes = nodes.disccodes --- local explicit_code = disccodes.explicit --- local automatic_code = disccodes.automatic --- local expanders = nil +-- local disccodes = nodes.disccodes +-- local explicitdisc_code = disccodes.explicit +-- local automaticdisc_code = disccodes.automatic +-- local expanders = nil -- -- function fonts.setdiscexpansion(v) -- if v == nil or v == true then @@ -172,17 +174,17 @@ local function start_trace(head) report_fonts() report_fonts("checking node list, run %s",run) report_fonts() - local n = tonut(head) + local n = head while n do local char, id = isglyph(n) if char then - local font = getfont(n) + local font = id local attr = getattr(n,0) or 0 report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,char) elseif id == disc_code then report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n)) elseif id == boundary_code then - report_fonts("[boundary] %i:%i",getsubtype(n),getfield(n,"value")) + report_fonts("[boundary] %i:%i",getsubtype(n),getdata(n)) else report_fonts("[%s]",nodecodes[id]) end @@ -202,32 +204,23 @@ local function stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expa report_fonts() end -function handlers.characters(head,groupcode,size,packtype,direction) - -- either next or not, but definitely no already processed list - starttiming(nodes) - - local usedfonts = { } - local attrfonts = { } - local basefonts = { } - local basefont = nil - local prevfont = nil - local prevattr = 0 - local done = false - local variants = nil - local redundant = nil - local nuthead = tonut(head) - local lastfont = nil - local lastproc = nil - local lastnone = nil - - local a, u, b, r, e = 0, 0, 0, 0, 0 - - if trace_fontrun then - start_trace(head) - end - -- There is no gain in checking for a single glyph and then having a fast path. On the - -- metafun manual (with some 2500 single char lists) the difference is just noise. +do + + local usedfonts + local attrfonts + local basefonts + local basefont + local prevfont + local prevattr + local variants + local redundant + local firstnone + local lastfont + local lastproc + local lastnone + + local a, u, b, r, e local function protectnone() protect_glyphs(firstnone,lastnone) @@ -296,288 +289,290 @@ function handlers.characters(head,groupcode,size,packtype,direction) end end - for n in traverse_char(nuthead) do - local font = getfont(n) - -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context - local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context - if font ~= prevfont or attr ~= prevattr then - prevfont = font - prevattr = attr - variants = fontvariants[font] - local fontmode = fontmodes[font] - if fontmode == "none" then - setnone(n) - elseif fontmode == "base" then - setbase(n) - else - setnode(n,font,attr) - end - elseif firstnone then - lastnone = n + function handlers.characters(head,groupcode,size,packtype,direction) + -- either next or not, but definitely no already processed list + starttiming(nodes) + + usedfonts = { } + attrfonts = { } + basefonts = { } + basefont = nil + prevfont = nil + prevattr = 0 + variants = nil + redundant = nil + firstnone = nil + lastfont = nil + lastproc = nil + lastnone = nil + + a, u, b, r, e = 0, 0, 0, 0, 0 + + if trace_fontrun then + start_trace(head) end - if variants then - local char = getchar(n) - if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then - local hash = variants[char] - if hash then - local p = getprev(n) - if p then - local char = ischar(p) -- checked - local variant = hash[char] - if variant then - if trace_variants then - report_fonts("replacing %C by %C",char,variant) - end - setchar(p,variant) - if redundant then - r = r + 1 - redundant[r] = n - else - r = 1 - redundant = { n } + + -- There is no gain in checking for a single glyph and then having a fast path. On the + -- metafun manual (with some 2500 single char lists) the difference is just noise. + + for n, char, font in nextchar, head do + -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context + if font ~= prevfont or attr ~= prevattr then + prevfont = font + prevattr = attr + variants = fontvariants[font] + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) + end + elseif firstnone then + lastnone = n + end + if variants then + if (char >= 0xFE00 and char <= 0xFE0F) or (char >= 0xE0100 and char <= 0xE01EF) then + local hash = variants[char] + if hash then + local p = getprev(n) + if p then + local char = ischar(p) -- checked + local variant = hash[char] + if variant then + if trace_variants then + report_fonts("replacing %C by %C",char,variant) + end + setchar(p,variant) + if redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } + end end end + elseif keep_redundant then + -- go on, can be used for tracing + elseif redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } end - elseif keep_redundant then - -- go on, can be used for tracing - elseif redundant then - r = r + 1 - redundant[r] = n - else - r = 1 - redundant = { n } end end end - end - if firstnone then - protectnone() - end + if firstnone then + protectnone() + end - if force_boundaryrun then + if force_boundaryrun then - -- we can inject wordboundaries and then let the hyphenator do its work - -- but we need to get rid of those nodes in order to build ligatures - -- and kern (a rather context thing) + -- we can inject wordboundaries and then let the hyphenator do its work + -- but we need to get rid of those nodes in order to build ligatures + -- and kern (a rather context thing) - for b in traverse_id(boundary_code,nuthead) do - if getsubtype(b) == word_boundary then - if redundant then - r = r + 1 - redundant[r] = b - else - r = 1 - redundant = { b } + for b, subtype in nextboundary, head do + if subtype == wordboundary_code then + if redundant then + r = r + 1 + redundant[r] = b + else + r = 1 + redundant = { b } + end end end - end - end + end - if redundant then - for i=1,r do - local r = redundant[i] - local p, n = getboth(r) - if r == nuthead then - nuthead = n - setprev(n) - else - setlink(p,n) - end - if b > 0 then - for i=1,b do - local bi = basefonts[i] - local b1 = bi[1] - local b2 = bi[2] - if b1 == b2 then - if b1 == r then - bi[1] = false - bi[2] = false + if redundant then + for i=1,r do + local r = redundant[i] + local p, n = getboth(r) + if r == head then + head = n + setprev(n) + else + setlink(p,n) + end + if b > 0 then + for i=1,b do + local bi = basefonts[i] + local b1 = bi[1] + local b2 = bi[2] + if b1 == b2 then + if b1 == r then + bi[1] = false + bi[2] = false + end + elseif b1 == r then + bi[1] = n + elseif b2 == r then + bi[2] = p end - elseif b1 == r then - bi[1] = n - elseif b2 == r then - bi[2] = p end end + flush_node(r) end - flush_node(r) end - end - if force_discrun then - - -- basefont is not supported in disc only runs ... it would mean a lot of - -- ranges .. we could try to run basemode as a separate processor run but - -- not for now (we can consider it when the new node code is tested - for d in traverse_id(disc_code,nuthead) do - -- we could use first_glyph, only doing replace is good enough because - -- pre and post are normally used for hyphens and these come from fonts - -- that part of the hyphenated word - local _, _, r = getdisc(d) - if r then - local prevfont = nil - local prevattr = nil - local none = false - for n in traverse_char(r) do - local font = getfont(n) - local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context - if font ~= prevfont or attr ~= prevattr then - prevfont = font - prevattr = attr - local fontmode = fontmodes[font] - if fontmode == "none" then - setnone(n) - elseif fontmode == "base" then - setbase(n) - else - setnode(n,font,attr) + if force_discrun then + + -- basefont is not supported in disc only runs ... it would mean a lot of + -- ranges .. we could try to run basemode as a separate processor run but + -- not for now (we can consider it when the new node code is tested + for d in nextdisc, head do + -- we could use first_glyph, only doing replace is good enough because + -- pre and post are normally used for hyphens and these come from fonts + -- that part of the hyphenated word + local _, _, r = getdisc(d) + if r then + local prevfont = nil + local prevattr = nil + local none = false + for n, char, font in nextchar, r do + local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context + if font ~= prevfont or attr ~= prevattr then + prevfont = font + prevattr = attr + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) + end + elseif firstnone then + -- lastnone = n + lastnone = nil end - elseif firstnone then - -- lastnone = n - lastnone = nil + -- we assume one font for now (and if there are more and we get into issues then + -- we can always remove the break) + break end - -- we assume one font for now (and if there are more and we get into issues then - -- we can always remove the break) - break - end - if firstnone then - protectnone() + if firstnone then + protectnone() + end + -- elseif expanders then + -- local subtype = getsubtype(d) + -- if subtype == automaticdisc_code or subtype == explicitdisc_code then + -- expanders[subtype](d) + -- e = e + 1 + -- end end - -- elseif expanders then - -- local subtype = getsubtype(d) - -- if subtype == automatic_code or subtype == explicit_code then - -- expanders[subtype](d) - -- e = e + 1 - -- end end - end - - end - if trace_fontrun then - stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders) - end + end - -- in context we always have at least 2 processors - if u == 0 then - -- skip - elseif u == 1 then - local attr = a > 0 and 0 or false -- 0 is the savest way - for i=1,#lastproc do - local h, d = lastproc[i](head,lastfont,attr,direction) - if d then - if h then - head = h - end - done = true - end + if trace_fontrun then + stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders) end - else - -- local attr = a == 0 and false or 0 -- 0 is the savest way - local attr = a > 0 and 0 or false -- 0 is the savest way - for font, processors in next, usedfonts do -- unordered - for i=1,#processors do - local h, d = processors[i](head,font,attr,direction,u) - if d then - if h then - head = h - end - done = true - end + + -- in context we always have at least 2 processors + if u == 0 then + -- skip + elseif u == 1 then + local attr = a > 0 and 0 or false -- 0 is the savest way + for i=1,#lastproc do + head = lastproc[i](head,lastfont,attr,direction) end - end - end - if a == 0 then - -- skip - elseif a == 1 then - local font, dynamics = next(attrfonts) - for attribute, processors in next, dynamics do -- unordered, attr can switch in between - for i=1,#processors do - local h, d = processors[i](head,font,attribute,direction) - if d then - if h then - head = h - end - done = true + else + -- local attr = a == 0 and false or 0 -- 0 is the savest way + local attr = a > 0 and 0 or false -- 0 is the savest way + for font, processors in next, usedfonts do -- unordered + for i=1,#processors do + head = processors[i](head,font,attr,direction,u) end end end - else - for font, dynamics in next, attrfonts do + if a == 0 then + -- skip + elseif a == 1 then + local font, dynamics = next(attrfonts) for attribute, processors in next, dynamics do -- unordered, attr can switch in between for i=1,#processors do - local h, d = processors[i](head,font,attribute,direction,a) - if d then - if h then - head = h - end - done = true - end + head = processors[i](head,font,attribute,direction) end end - end - end - if b == 0 then - -- skip - elseif b == 1 then - -- only one font - local range = basefonts[1] - local start = range[1] - local stop = range[2] - if (start or stop) and (start ~= stop) then - local front = nuthead == start - if stop then - start = ligaturing(start,stop) - start = kerning(start,stop) - elseif start then -- safeguard - start = ligaturing(start) - start = kerning(start) - end - if front and nuthead ~= start then - -- nuthead = start - head = tonode(start) + else + for font, dynamics in next, attrfonts do + for attribute, processors in next, dynamics do -- unordered, attr can switch in between + for i=1,#processors do + head = processors[i](head,font,attribute,direction,a) + end + end end end - else - -- multiple fonts - for i=1,b do - local range = basefonts[i] + if b == 0 then + -- skip + elseif b == 1 then + -- only one font + local range = basefonts[1] local start = range[1] local stop = range[2] - if start then -- and start ~= stop but that seldom happens - local front = nuthead == start - local prev = getprev(start) - local next = getnext(stop) + if (start or stop) and (start ~= stop) then + local front = head == start if stop then - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) - else + start = ligaturing(start,stop) + start = kerning(start,stop) + elseif start then -- safeguard start = ligaturing(start) start = kerning(start) end - -- is done automatically - if prev then - setlink(prev,start) - end - if next then - setlink(stop,next) + if front and head ~= start then + head = start end - -- till here - if front and nuthead ~= start then - nuthead = start - head = tonode(start) + end + else + -- multiple fonts + for i=1,b do + local range = basefonts[i] + local start = range[1] + local stop = range[2] + if start then -- and start ~= stop but that seldom happens + local front = head == start + local prev = getprev(start) + local next = getnext(stop) + if stop then + start, stop = ligaturing(start,stop) + start, stop = kerning(start,stop) + else + start = ligaturing(start) + start = kerning(start) + end + -- is done automatically + if prev then + setlink(prev,start) + end + if next then + setlink(stop,next) + end + -- till here + if front and head ~= start then + head = start + end end end end + + stoptiming(nodes) + + if trace_characters then + nodes.report(head) + end + + return head end - stoptiming(nodes) - if trace_characters then - nodes.report(head,done) - end - return head, true + end -handlers.protectglyphs = function(n) protect_glyphs (tonut(n)) return n, true end -handlers.unprotectglyphs = function(n) unprotect_glyphs(tonut(n)) return n, true end +handlers.protectglyphs = protect_glyphs +handlers.unprotectglyphs = unprotect_glyphs diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua index 50da140ce98..f910c7e012f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ini.lua @@ -70,6 +70,12 @@ local formatcolumns = utilities.formatters.formatcolumns local getsubtypes = node.subtypes local getvalues = node.values +tex.magicconstants = { -- we use tex.constants for something else + running = -1073741824, + maxdimen = 1073741823, -- 0x3FFFFFFF or 2^30-1 + trueinch = 4736286, +} + -- local listcodes = allocate { -- [0] = "unknown", -- [1] = "line", @@ -108,12 +114,11 @@ dircodes = allocate { } -- local glyphcodes = allocate { --- [0] = "character", --- [1] = "glyph", --- [2] = "ligature", --- [3] = "ghost", --- [4] = "left", --- [5] = "right", +-- [ 1] = "character", +-- [ 2] = "ligature", +-- [ 4] = "ghost", +-- [ 8] = "left", +-- [16] = "right", -- } local glyphcodes = mark(getsubtypes("glyph")) @@ -281,11 +286,12 @@ local function simplified(t) end local nodecodes = simplified(node.types()) -local whatcodes = simplified(node.whatsits()) +local whatcodes = simplified(node.whatsits and node.whatsits() or { }) local usercodes = allocate { [ 97] = "attribute", -- a [100] = "number", -- d + [102] = "float", -- f [108] = "lua", -- l [110] = "node", -- n [115] = "string", -- s @@ -306,7 +312,7 @@ local noadoptions = allocate { -- local directionvalues = mark(getvalues("dir")) -- local gluevalues = mark(getvalues("glue")) --- local pdfliteralvalues = mark(getvalues("pdf_literal")) +-- local literalvalues = mark(getvalues("literal")) local dirvalues = allocate { [0] = "TLT", @@ -323,7 +329,7 @@ local gluevalues = allocate { [4] = "filll", } -local pdfliteralvalues = allocate { +local literalvalues = allocate { [0] = "origin", [1] = "page", [2] = "always", @@ -356,41 +362,90 @@ usercodes = allocate(swapped(usercodes,usercodes)) noadoptions = allocate(swapped(noadoptions,noadoptions)) dirvalues = allocate(swapped(dirvalues,dirvalues)) gluevalues = allocate(swapped(gluevalues,gluevalues)) -pdfliteralvalues = allocate(swapped(pdfliteralvalues,pdfliteralvalues)) - -nodes.gluecodes = gluecodes -nodes.dircodes = dircodes -nodes.boundarycodes = boundarycodes -nodes.noadcodes = noadcodes -nodes.nodecodes = nodecodes -nodes.whatcodes = whatcodes -nodes.listcodes = listcodes -nodes.glyphcodes = glyphcodes -nodes.kerncodes = kerncodes -nodes.penaltycodes = penaltycodes -nodes.mathcodes = mathcodes -nodes.fillcodes = fillcodes -nodes.margincodes = margincodes -nodes.disccodes = disccodes -nodes.accentcodes = accentcodes -nodes.radicalcodes = radicalcodes -nodes.fencecodes = fencecodes -nodes.rulecodes = rulecodes -nodes.leadercodes = leadercodes -nodes.usercodes = usercodes -nodes.noadoptions = noadoptions -nodes.dirvalues = dirvalues -nodes.gluevalues = gluevalues -nodes.pdfliteralvalues = pdfliteralvalues - -nodes.skipcodes = gluecodes -- more friendly -nodes.directioncodes = dircodes -- more friendly -nodes.whatsitcodes = whatcodes -- more official -nodes.marginkerncodes = margincodes -nodes.discretionarycodes = disccodes -nodes.directionvalues = dirvalues -- more friendly -nodes.skipvalues = gluevalues -- more friendly -nodes.literalvalues = pdfliteralvalues -- more friendly +literalvalues = allocate(swapped(literalvalues,literalvalues)) + +if CONTEXTLMTXMODE > 1 then + whatcodes.literal = 0x1 whatcodes[0x1] = "literal" + whatcodes.latelua = 0x2 whatcodes[0x2] = "latelua" + whatcodes.userdefined = 0x3 whatcodes[0x3] = "userdefined" + whatcodes.savepos = 0x4 whatcodes[0x4] = "savepos" + whatcodes.save = 0x5 whatcodes[0x5] = "save" + whatcodes.restore = 0x6 whatcodes[0x6] = "restore" + whatcodes.setmatrix = 0x7 whatcodes[0x7] = "setmatrix" + whatcodes.open = 0x8 whatcodes[0x8] = "open" + whatcodes.close = 0x9 whatcodes[0x9] = "close" + whatcodes.write = 0xA whatcodes[0xA] = "write" +elseif not whatcodes.literal then + whatcodes.literal = whatcodes.pdfliteral + whatcodes.save = whatcodes.pdfsave + whatcodes.restore = whatcodes.pdfrestore + whatcodes.setmatrix = whatcodes.pdfsetmatrix +end + +nodes.gluecodes = gluecodes +nodes.dircodes = dircodes +nodes.boundarycodes = boundarycodes +nodes.noadcodes = noadcodes +nodes.nodecodes = nodecodes +nodes.whatcodes = whatcodes +nodes.listcodes = listcodes +nodes.glyphcodes = glyphcodes +nodes.kerncodes = kerncodes +nodes.penaltycodes = penaltycodes +nodes.mathcodes = mathcodes +nodes.fillcodes = fillcodes +nodes.margincodes = margincodes +nodes.disccodes = disccodes +nodes.accentcodes = accentcodes +nodes.radicalcodes = radicalcodes +nodes.fencecodes = fencecodes +nodes.rulecodes = rulecodes +nodes.leadercodes = leadercodes +nodes.usercodes = usercodes +nodes.noadoptions = noadoptions +nodes.dirvalues = dirvalues +nodes.gluevalues = gluevalues +nodes.literalvalues = literalvalues + +dirvalues.lefttoright = 0 +dirvalues.righttoleft = 1 + +nodes.subtypes = allocate { + [nodecodes.accent] = accentcodes, + [nodecodes.boundary] = boundarycodes, + [nodecodes.dir] = dircodes, + [nodecodes.disc] = disccodes, + [nodecodes.fence] = fencecodes, + [nodecodes.glue] = gluecodes, + [nodecodes.glyph] = glyphcodes, + [nodecodes.hlist] = listcodes, + [nodecodes.kern] = kerncodes, + [nodecodes.marginkern] = margincodes, + [nodecodes.math] = mathcodes, + [nodecodes.noad] = noadcodes, + [nodecodes.penalty] = penaltycodes, + [nodecodes.radical] = radicalcodes, + [nodecodes.rule] = rulecodes, + [nodecodes.vlist] = listcodes, + [nodecodes.whatsit] = whatcodes, +} + +table.setmetatableindex(nodes.subtypes,function(t,k) + local v = { } + t[k] = v + return v +end) + +nodes.skipcodes = gluecodes -- more friendly +nodes.directioncodes = dircodes -- more friendly +nodes.whatsitcodes = whatcodes -- more official +nodes.marginkerncodes = margincodes +nodes.discretionarycodes = disccodes +nodes.directionvalues = dirvalues -- more friendly +nodes.skipvalues = gluevalues -- more friendly +nodes.literalvalues = literalvalues -- more friendly + +glyphcodes.glyph = glyphcodes.character listcodes.row = listcodes.alignment listcodes.column = listcodes.alignment @@ -399,7 +454,7 @@ kerncodes.kerning = kerncodes.fontkern kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new -pdfliteralvalues.direct = pdfliteralvalues.always +literalvalues.direct = literalvalues.always nodes.codes = allocate { -- mostly for listing glue = skipcodes, @@ -468,4 +523,3 @@ end if node.fix_node_lists then node.fix_node_lists(false) end - diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv index 8f10791633e..35013c4b801 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ini.mkiv @@ -21,7 +21,7 @@ \registerctxluafile{node-met}{} \registerctxluafile{node-nut}{} \registerctxluafile{node-res}{} -\registerctxluafile{node-ppt}{} % experimental +%registerctxluafile{node-ppt}{} % experimental, not used so probably useless \registerctxluafile{node-dir}{} \registerctxluafile{node-aux}{} \registerctxluafile{node-tst}{} @@ -34,9 +34,9 @@ \registerctxluafile{node-ext}{} \registerctxluafile{node-acc}{} % experimental %registerctxluafile{node-prp}{} % makes no sense (yet) -\registerctxluafile{node-ppt}{} \registerctxluafile{node-scn}{} \registerctxluafile{node-syn}{} +\registerctxluafile{node-par}{} \newcount\c_node_tracers_show_box % box number diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua index 865f69c2c7f..0d501890b92 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ltp.lua @@ -134,6 +134,53 @@ if not modules then modules = { } end modules ['node-par'] = { ]]-- +--[[-- + +#define dir_TLT 0 +#define dir_TRT 1 +#define dir_LTL 2 +#define dir_RTT 3 + +#define dir_TLT_or_TRT(A) (A < 2) +#define dir_LTL_or_RTT(A) (A > 1) + +#define textdir_parallel(A,B) (\ +(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \ +(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\ +) + +#define pardir_parallel(A,B) (\ +(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \ +(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\ +) + +#define pardir_opposite(A,B) (\ +(A == dir_LTL and B == dir_RTT) or \ +(A == dir_RTT and B == dir_LTL)\ +) + +#define textdir_opposite(A,B) (\ +(A == dir_TLT and B == dir_TRT) or \ +(A == dir_TRT and B == dir_TLT)\ +) + +#define glyphdir_opposite(A,B) 0 + +#define pardir_equal(A,B) (\ +(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \ +(A == dir_LTL and B == dir_LTL) or \ +(A == dir_RTT and B == dir_RTT)\ +) + +#define textdir_equal(A,B) (\ +(A == dir_TLT and B == dir_TLT) or \ +(A == dir_TRT and B == dir_TRT) or \ +(A == dir_LTL and dir_LTL_or_RTT(B)) or \ +(A == dir_RTT and dir_LTL_or_RTT(B))\ +) + +--]]-- + local tonumber = tonumber local utfchar = utf.char local write, write_nl = texio.write, texio.write_nl @@ -191,7 +238,6 @@ local parameters = fonthashes.parameters local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getfield = nuts.getfield local getid = nuts.getid @@ -200,21 +246,20 @@ local getnext = nuts.getnext local getprev = nuts.getprev local getboth = nuts.getboth local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar local getdisc = nuts.getdisc local getattr = nuts.getattr local getdisc = nuts.getdisc local getglue = nuts.getglue local getwhd = nuts.getwhd -local getcomponents = nuts.getcomponents local getkern = nuts.getkern local getpenalty = nuts.getpenalty -local getdir = nuts.getdir +local getdirection = nuts.getdirection local getshift = nuts.getshift local getwidth = nuts.getwidth local getheight = nuts.getheight local getdepth = nuts.getdepth +local getdata = nuts.getdata +local getwhd = nuts.getwhd local isglyph = nuts.isglyph @@ -229,11 +274,10 @@ local setsubtype = nuts.setsubtype local setglue = nuts.setglue local setwhd = nuts.setwhd local setkern = nuts.setkern -local setdir = nuts.setdir +local setdirection = nuts.setdirection local setshift = nuts.setshift local setwidth = nuts.setwidth ------ setheight = nuts.setheight ------ setdepth = nuts.setdepth +local setexpansion = nuts.setexpansion local slide_node_list = nuts.slide -- get rid of this, probably ok > 78.2 local find_tail = nuts.tail @@ -246,13 +290,14 @@ local replace_node = nuts.replace local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local is_zero_glue = nuts.is_zero_glue +local is_skipable = nuts.protrusion_skippable local nodepool = nuts.pool local nodecodes = nodes.nodecodes local kerncodes = nodes.kerncodes local glyphcodes = nodes.glyphcodes -local gluecodes = nodes.gluecodes +local leadercodes = nodes.leadercodes local margincodes = nodes.margincodes local disccodes = nodes.disccodes local mathcodes = nodes.mathcodes @@ -276,9 +321,9 @@ local marginkern_code = nodecodes.marginkern local dir_code = nodecodes.dir local boundary_code = nodecodes.boundary -local protrusion_code = boundarycodes.protrusion +local protrusionboundary_code = boundarycodes.protrusion -local leaders_code = gluecodes.leaders +local leaders_code = leadercodes.leaders local localpar_code = nodecodes.localpar @@ -287,17 +332,17 @@ local italickern_code = kerncodes.italiccorrection local fontkern_code = kerncodes.fontkern local accentkern_code = kerncodes.accentkern -local ligature_code = glyphcodes.ligature +local ligatureglyph_code = glyphcodes.ligature -local stretch_orders = nodes.fillcodes +local fillcodes = nodes.fillcodes local leftmargin_code = margincodes.left ----- rightmargin_code = margincodes.right -local automatic_disc_code = disccodes.automatic -local regular_disc_code = disccodes.regular -local first_disc_code = disccodes.first -local second_disc_code = disccodes.second +local automaticdisc_code = disccodes.automatic +local regulardisc_code = disccodes.regular +local firstdisc_code = disccodes.first +local seconddisc_code = disccodes.second local endmath_code = mathcodes.endmath @@ -323,7 +368,7 @@ local fit_decent_class = 2 -- fitness for all other lines local fit_tight_class = 3 -- fitness for lines shrinking 0.5 to 1.0 of their shrinkability local new_penalty = nodepool.penalty -local new_dir = nodepool.textdir +local new_direction = nodepool.direction local new_leftmarginkern = nodepool.leftmarginkern local new_rightmarginkern = nodepool.rightmarginkern local new_leftskip = nodepool.leftskip @@ -334,17 +379,6 @@ local new_temp = nodepool.temp local new_rule = nodepool.rule local new_hlist = nodepool.hlist -local is_rotated = nodes.is_rotated -local is_parallel = nodes.textdir_is_parallel -local is_opposite = nodes.textdir_is_opposite -local textdir_is_equal = nodes.textdir_is_equal -local pardir_is_equal = nodes.pardir_is_equal -local glyphdir_is_equal = nodes.glyphdir_is_equal - -local dir_pops = nodes.dir_is_pop -local dir_negations = nodes.dir_negation -local is_skipable = nuts.protrusion_skippable - -- helpers -- -- It makes more sense to move the somewhat messy dir state tracking @@ -359,22 +393,24 @@ end -- in the parbuilder. local function checked_line_dir(stack,current) - if not dir_pops[current] then + local direction, pop = getdirection(current) + if not pop then local n = stack.n + 1 stack.n = n stack[n] = current - return getdir(current) + return direction elseif n > 0 then local n = stack.n local dirnode = stack[n] dirstack.n = n - 1 - return getdir(dirnode) + direction = getdirection(dirnode) -- we could save it + return direction else report_parbuilders("warning: missing pop node (%a)",1) -- in line ... end end --- The next function checks a dir nodes in a list and appends the negations +-- The next function checks dir nodes in a list and appends the negations -- that are currently needed (some day LuaTeX will be more tolerant). We use -- the negations for the next line. @@ -382,10 +418,12 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop) local e = start local n = stack.n local h = nil + -- todo: traverse while start and start ~= stop do local id = getid(start) if id == dir_code then - if not dir_pops[getdir(start)] then -- weird, what is this # + local direction, pop = getdirection(start) + if not pop then n = n + 1 stack[n] = start elseif n > 0 then @@ -397,7 +435,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop) start = getnext(start) end for i=n,1,-1 do - h, current = insert_node_after(current,current,new_dir(dir_negations[getdir(stack[i])])) + h, current = insert_node_after(current,current,new_direction(getdirection(stack[i]),true)) end stack.n = n return current @@ -406,7 +444,7 @@ end local function inject_dirs_at_begin_of_line(stack,current) local h = nil for i=stack.n,1,-1 do - h, current = insert_node_after(current,current,new_dir(stack[i])) + h, current = insert_node_after(current,current,new_direction(stack[i])) end stack.n = 0 return current @@ -507,9 +545,9 @@ end) local function kern_stretch_shrink(p,d) local left = getprev(p) if left then - local char = isglyph(left) + local char, font = isglyph(left) if char then - local data = expansions[getfont(left)][char] + local data = expansions[font][char] if data then local stretch = data.stretch local shrink = data.shrink @@ -630,8 +668,8 @@ local function find(head) -- do we really want to recurse into an hlist? head = getnext(head) end elseif id == boundary_code then - if getsubtype(head) == protrusion_code then - local v = getfield(head,"value") + if getsubtype(head) == protrusionboundary_code then + local v = getdata(head) if v == 1 or v == 3 then head = getnext(head) if head then @@ -654,19 +692,19 @@ end local function find_protchar_left(l) -- weird function local ln = getnext(l) - if ln and getid(ln) == hlist_code and not getlist(ln) and getfield(ln,"width") == 0 and getfield(ln,"height") == 0 and getfield(ln,"depth") == 0 then - l = getnext(l) - else -- if d then -- was always true - local id = getid(l) - while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph? - l = ln - ln = getnext(l) - id = getid(ln) - end + if ln and getid(ln) == hlist_code and not getlist(ln) then + local w, h, d = getwhd(ln) + if w == 0 and h == 0 and d == 0 then + l = getnext(l) + return find(l) or l + end + end -- if d then -- was always true + local id = getid(l) + while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph? + l = ln + ln = getnext(l) + id = getid(ln) end - -- if getid(l) == glyph_code then - -- return l - -- end return find(l) or l end @@ -684,8 +722,8 @@ local function find(head,tail) tail = getprev(tail) end elseif id == boundary_code then - if getsubtype(head) == protrusion_code then - local v = getfield(tail,"value") + if getsubtype(head) == protrusionboundary_code then + local v = getdata(tail) if v == 2 or v == 3 then tail = getprev(tail) if tail then @@ -711,8 +749,8 @@ local function find_protchar_right(l,r) end local function left_pw(p) - local font = getfont(p) - local prot = chardata[font][getchar(p)].left_protruding + local char, font = isglyph(p) + local prot = chardata[font][char].left_protruding if not prot or prot == 0 then return 0 end @@ -720,8 +758,8 @@ local function left_pw(p) end local function right_pw(p) - local font = getfont(p) - local prot = chardata[font][getchar(p)].right_protruding + local char, font = isglyph(p) + local prot = chardata[font][char].right_protruding if not prot or prot == 0 then return 0 end @@ -748,13 +786,13 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw local char, id = isglyph(s) if char then local wd, ht, dp = getwhd(s) - if is_rotated[line_break_dir] then -- can be shared + if is_rotated(line_break_dir) then size = size + ht + dp else size = size + wd end if checked_expansion then - local data = checked_expansion[getfont(s)] + local data = checked_expansion[id] -- id == font if data then data = data[char] if data then @@ -765,7 +803,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw end elseif id == hlist_code or id == vlist_code then local wd, ht, dp = getwhd(s) - if is_parallel[getdir(s)][line_break_dir] then + if textdir_parallel(getdirection(s),line_break_dir) then size = size + wd else size = size + ht + dp @@ -796,1709 +834,1712 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw return size, adjust_stretch, adjust_shrink end -local function compute_break_width(par,break_type,p) -- split in two - local break_width = par.break_width - if break_type > unhyphenated_code then - local disc_width = par.disc_width - local checked_expansion = par.checked_expansion - local line_break_dir = par.line_break_dir - local break_size = break_width.size + disc_width.size - local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch - local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink - local pre, post, replace = getdisc(p) - if replace then - local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) - break_size = break_size - size - break_adjust_stretch = break_adjust_stretch - adjust_stretch - break_adjust_shrink = break_adjust_shrink - adjust_shrink - end - if post then - local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post) - break_size = break_size + size - break_adjust_stretch = break_adjust_stretch + adjust_stretch - break_adjust_shrink = break_adjust_shrink + adjust_shrink - end - break_width.size = break_size - break_width.adjust_stretch = break_adjust_stretch - break_width.adjust_shrink = break_adjust_shrink - if not post then - p = getnext(p) - else - return - end - end - while p do -- skip spacing etc - local id = getid(p) - if id == glyph_code then - return -- happens often - elseif id == glue_code then - local wd, stretch, shrink, stretch_order = getglue(p) - local order = stretch_orders[stretch_order] - break_width.size = break_width.size - wd - break_width[order] = break_width[order] - stretch - break_width.shrink = break_width.shrink - shrink - elseif id == penalty_code then - -- do nothing - elseif id == kern_code then - local s = getsubtype(p) - if s == userkern_code or s == italickern_code then - break_width.size = break_width.size - getkern(p) +-- We can actually make par local to this module as we never break inside a break call and that way the +-- array is reused. At some point the information will be part of the paragraph spec as passed. + +local hztolerance = 2500 +local hzwarned = false + +do + + local function compute_break_width(par,break_type,p) -- split in two + local break_width = par.break_width + if break_type > unhyphenated_code then + local disc_width = par.disc_width + local checked_expansion = par.checked_expansion + local line_break_dir = par.line_break_dir + local break_size = break_width.size + disc_width.size + local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch + local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink + local pre, post, replace = getdisc(p) + if replace then + local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) + break_size = break_size - size + break_adjust_stretch = break_adjust_stretch - adjust_stretch + break_adjust_shrink = break_adjust_shrink - adjust_shrink + end + if post then + local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post) + break_size = break_size + size + break_adjust_stretch = break_adjust_stretch + adjust_stretch + break_adjust_shrink = break_adjust_shrink + adjust_shrink + end + break_width.size = break_size + break_width.adjust_stretch = break_adjust_stretch + break_width.adjust_shrink = break_adjust_shrink + if not post then + p = getnext(p) else return end - elseif id == math_code then - break_width.size = break_width.size - getkern(p) -- surround - -- new in luatex - local wd, stretch, shrink, stretch_order = getglue(p) - local order = stretch_orders[stretch_order] - break_width.size = break_width.size - wd - break_width[order] = break_width[order] - stretch - break_width.shrink = break_width.shrink - shrink - else - return end - p = getnext(p) - end -end - -local function append_to_vlist(par, b) - local prev_depth = par.prev_depth - local head_field = par.head_field - local tail_field = head_field and slide_node_list(head_field) -- todo: find_tail - local is_hlist = getid(b) == hlist_code - -- if prev_depth > par.ignored_dimen then - if prev_depth > ignore_depth then - if is_hlist then - local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip) - local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines - local skip = nil - if delta < par.line_skip_limit then - width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip) - skip = new_lineskip(width, stretch, shrink, stretch_order, shrink_order) - else - skip = new_baselineskip(delta, stretch, shrink, stretch_order, shrink_order) - end - if head_field then - setlink(tail_field,skip) + while p do -- skip spacing etc + local id = getid(p) + if id == glyph_code then + return -- happens often + elseif id == glue_code then + local wd, stretch, shrink, stretch_order = getglue(p) + local order = fillcodes[stretch_order] + break_width.size = break_width.size - wd + break_width[order] = break_width[order] - stretch + break_width.shrink = break_width.shrink - shrink + elseif id == penalty_code then + -- do nothing + elseif id == kern_code then + local s = getsubtype(p) + if s == userkern_code or s == italickern_code then + break_width.size = break_width.size - getkern(p) + else + return + end + elseif id == math_code then + break_width.size = break_width.size - getkern(p) -- surround + -- new in luatex + local wd, stretch, shrink, stretch_order = getglue(p) + local order = fillcodes[stretch_order] + break_width.size = break_width.size - wd + break_width[order] = break_width[order] - stretch + break_width.shrink = break_width.shrink - shrink else - par.head_field = skip - head_field = skip + return end - tail_field = skip + p = getnext(p) end end - if head_field then - setlink(tail_field,b) - else - par.head_field = b - end - if is_hlist then - local pd = getdepth(b) - par.prev_depth = pd - texnest[texnest.ptr].prevdepth = pd - end -end -local function append_list(par, b) - local head_field = par.head_field - if head_field then - local n = slide_node_list(head_field) -- todo: find_tail - setlink(n,b) - else - par.head_field = b + local function append_to_vlist(par, b) + local prev_depth = par.prev_depth + local head_field = par.head_field + local tail_field = head_field and slide_node_list(head_field) -- todo: find_tail + local is_hlist = getid(b) == hlist_code + -- if prev_depth > par.ignored_dimen then + if prev_depth > ignore_depth then + if is_hlist then + local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip) + local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines + local skip = nil + if delta < par.line_skip_limit then + width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip) + skip = new_lineskip(width, stretch, shrink, stretch_order, shrink_order) + else + skip = new_baselineskip(delta, stretch, shrink, stretch_order, shrink_order) + end + if head_field then + setlink(tail_field,skip) + else + par.head_field = skip + head_field = skip + end + tail_field = skip + end + end + if head_field then + setlink(tail_field,b) + else + par.head_field = b + end + if is_hlist then + local pd = getdepth(b) + par.prev_depth = pd + texnest[texnest.ptr].prevdepth = pd + end end -end - --- We can actually make par local to this module as we never break inside a break call and that way the --- array is reused. At some point the information will be part of the paragraph spec as passed. - -local hztolerance = 2500 -local hzwarned = false - -local function used_skip(s) - return s and not is_zero_glue(s) and s -end -local function initialize_line_break(head,display) - - local hang_indent = tex.hangindent or 0 - local hsize = tex.hsize or 0 - local hang_after = tex.hangafter or 0 - local par_shape_ptr = tex.parshape - local left_skip = tonut(tex.leftskip) -- nodes - local right_skip = tonut(tex.rightskip) -- nodes - local pretolerance = tex.pretolerance - local tolerance = tex.tolerance - local adjust_spacing = tex.adjustspacing - local protrude_chars = tex.protrudechars - local last_line_fit = tex.lastlinefit - - local newhead = new_temp() - setnext(newhead,head) - - local adjust_spacing_status = adjust_spacing > 1 and -1 or 0 - - -- metatables - - local par = { - head = newhead, - head_field = nil, - display = display, - font_in_short_display = 0, - no_shrink_error_yet = true, -- have we complained about infinite shrinkage? - second_pass = false, -- is this our second attempt to break this paragraph? - final_pass = false, -- is this our final attempt to break this paragraph? - threshold = 0, -- maximum badness on feasible lines - - passive = nil, -- most recent node on passive list - printed_node = head, -- most recent node that has been printed - pass_number = 0, -- the number of passive nodes allocated on this pass - auto_breaking = 0, -- make auto_breaking accessible out of line_break - - active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 }, - break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 }, - disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 }, - fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 }, - background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 }, - - hang_indent = hang_indent, - hsize = hsize, - hang_after = hang_after, - par_shape_ptr = par_shape_ptr, - left_skip = left_skip, - right_skip = right_skip, - pretolerance = pretolerance, - tolerance = tolerance, - - protrude_chars = protrude_chars, - adjust_spacing = adjust_spacing, - max_stretch_ratio = adjust_spacing_status, - max_shrink_ratio = adjust_spacing_status, - cur_font_step = adjust_spacing_status, - checked_expansion = false, - tracing_paragraphs = tex.tracingparagraphs > 0, - - emergency_stretch = tex.emergencystretch or 0, - looseness = tex.looseness or 0, - line_penalty = tex.linepenalty or 0, - hyphen_penalty = tex.hyphenpenalty or 0, - broken_penalty = tex.brokenpenalty or 0, - inter_line_penalty = tex.interlinepenalty or 0, - club_penalty = tex.clubpenalty or 0, - widow_penalty = tex.widowpenalty or 0, - display_widow_penalty = tex.displaywidowpenalty or 0, - ex_hyphen_penalty = tex.exhyphenpenalty or 0, - - adj_demerits = tex.adjdemerits or 0, - double_hyphen_demerits = tex.doublehyphendemerits or 0, - final_hyphen_demerits = tex.finalhyphendemerits or 0, - - first_line = 0, -- tex.nest[tex.nest.ptr].modeline, -- 0, -- cur_list.pg_field - - -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away - -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away - -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away - -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away - - -- ignored_dimen = tex.pdfignoreddimen or 0, - - baseline_skip = tonut(tex.baselineskip), - lineskip = tonut(tex.lineskip), - line_skip_limit = tex.lineskiplimit, - - prev_depth = texnest[texnest.ptr].prevdepth, - - final_par_glue = slide_node_list(head), -- todo: we know tail already, slow - - par_break_dir = tex.pardir, - line_break_dir = tex.pardir, - - internal_pen_inter = 0, -- running localinterlinepenalty - internal_pen_broken = 0, -- running localbrokenpenalty - internal_left_box = nil, -- running localleftbox - internal_left_box_width = 0, -- running localleftbox width - init_internal_left_box = nil, -- running localleftbox - init_internal_left_box_width = 0, -- running localleftbox width - internal_right_box = nil, -- running localrightbox - internal_right_box_width = 0, -- running localrightbox width - - best_place = { }, -- how to achieve minimal_demerits - best_pl_line = { }, -- corresponding line number - easy_line = 0, -- line numbers easy_line are equivalent in break nodes - last_special_line = 0, -- line numbers last_special_line all have the same width - first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified - second_width = 0, -- the width of all lines last_special_line - first_indent = 0, -- left margin to go with first_width - second_indent = 0, -- left margin to go with second_width - - best_bet = nil, -- use this passive node and its predecessors - fewest_demerits = 0, -- the demerits associated with best_bet - best_line = 0, -- line number following the last line of the new paragraph - line_diff = 0, -- the difference between the current line number and the optimum best_line - - -- not yet used - - best_pl_short = { }, -- shortfall corresponding to minimal_demerits - best_pl_glue = { }, -- corresponding glue stretch or shrink - do_last_line_fit = false, - last_line_fit = last_line_fit, - - minimum_demerits = awful_badness, - - minimal_demerits = { - - [fit_very_loose_class] = awful_badness, - [fit_loose_class] = awful_badness, - [fit_decent_class] = awful_badness, - [fit_tight_class] = awful_badness, - - }, - - prev_char_p = nil, - - statistics = { - - noflines = 0, - nofprotrudedlines = 0, - nofadjustedlines = 0, - - }, - - -- -- just a thought ... parshape functions ... it would be nice to - -- -- also store the height so far (probably not too hard) although - -- -- in most cases we work on grids in such cases - -- - -- adapt_width = function(par,line) - -- -- carry attribute, so that we can accumulate - -- local left = 655360 * (line - 1) - -- local right = 655360 * (line - 1) - -- return left, right - -- end + local function append_list(par, b) + local head_field = par.head_field + if head_field then + local n = slide_node_list(head_field) -- todo: find_tail + setlink(n,b) + else + par.head_field = b + end + end + + local function used_skip(s) + return s and not is_zero_glue(s) and s + end + + local function initialize_line_break(head,display) + + local hang_indent = tex.hangindent or 0 + local hsize = tex.hsize or 0 + local hang_after = tex.hangafter or 0 + local par_shape_ptr = tex.parshape + local left_skip = tonut(tex.leftskip) -- nodes + local right_skip = tonut(tex.rightskip) -- nodes + local pretolerance = tex.pretolerance + local tolerance = tex.tolerance + local adjust_spacing = tex.adjustspacing + local protrude_chars = tex.protrudechars + local last_line_fit = tex.lastlinefit + local par_dir = tex.pardirection + + local newhead = new_temp() + setnext(newhead,head) + + local adjust_spacing_status = adjust_spacing > 1 and -1 or 0 + + -- metatables + + local par = { + head = newhead, + head_field = nil, + display = display, + font_in_short_display = 0, + no_shrink_error_yet = true, -- have we complained about infinite shrinkage? + second_pass = false, -- is this our second attempt to break this paragraph? + final_pass = false, -- is this our final attempt to break this paragraph? + threshold = 0, -- maximum badness on feasible lines + + passive = nil, -- most recent node on passive list + printed_node = head, -- most recent node that has been printed + pass_number = 0, -- the number of passive nodes allocated on this pass + auto_breaking = 0, -- make auto_breaking accessible out of line_break + + active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 }, + break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 }, + disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 }, + fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 }, + background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 }, + + hang_indent = hang_indent, + hsize = hsize, + hang_after = hang_after, + par_shape_ptr = par_shape_ptr, + left_skip = left_skip, + right_skip = right_skip, + pretolerance = pretolerance, + tolerance = tolerance, + + protrude_chars = protrude_chars, + adjust_spacing = adjust_spacing, + max_stretch_ratio = adjust_spacing_status, + max_shrink_ratio = adjust_spacing_status, + cur_font_step = adjust_spacing_status, + checked_expansion = false, + tracing_paragraphs = tex.tracingparagraphs > 0, + + emergency_stretch = tex.emergencystretch or 0, + looseness = tex.looseness or 0, + line_penalty = tex.linepenalty or 0, + hyphen_penalty = tex.hyphenpenalty or 0, + broken_penalty = tex.brokenpenalty or 0, + inter_line_penalty = tex.interlinepenalty or 0, + club_penalty = tex.clubpenalty or 0, + widow_penalty = tex.widowpenalty or 0, + display_widow_penalty = tex.displaywidowpenalty or 0, + ex_hyphen_penalty = tex.exhyphenpenalty or 0, + + adj_demerits = tex.adjdemerits or 0, + double_hyphen_demerits = tex.doublehyphendemerits or 0, + final_hyphen_demerits = tex.finalhyphendemerits or 0, + + first_line = 0, -- texnest[texnest.ptr].modeline, -- 0, -- cur_list.pg_field + + -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away + -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away + -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away + -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away + + -- ignored_dimen = tex.pdfignoreddimen or 0, + + baseline_skip = tonut(tex.baselineskip), + lineskip = tonut(tex.lineskip), + line_skip_limit = tex.lineskiplimit, + + prev_depth = texnest[texnest.ptr].prevdepth, + + final_par_glue = slide_node_list(head), -- todo: we know tail already, slow + + par_break_dir = par_dir, + line_break_dir = par_dir, + + internal_pen_inter = 0, -- running localinterlinepenalty + internal_pen_broken = 0, -- running localbrokenpenalty + internal_left_box = nil, -- running localleftbox + internal_left_box_width = 0, -- running localleftbox width + init_internal_left_box = nil, -- running localleftbox + init_internal_left_box_width = 0, -- running localleftbox width + internal_right_box = nil, -- running localrightbox + internal_right_box_width = 0, -- running localrightbox width + + best_place = { }, -- how to achieve minimal_demerits + best_pl_line = { }, -- corresponding line number + easy_line = 0, -- line numbers easy_line are equivalent in break nodes + last_special_line = 0, -- line numbers last_special_line all have the same width + first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified + second_width = 0, -- the width of all lines last_special_line + first_indent = 0, -- left margin to go with first_width + second_indent = 0, -- left margin to go with second_width + + best_bet = nil, -- use this passive node and its predecessors + fewest_demerits = 0, -- the demerits associated with best_bet + best_line = 0, -- line number following the last line of the new paragraph + line_diff = 0, -- the difference between the current line number and the optimum best_line + + -- not yet used + + best_pl_short = { }, -- shortfall corresponding to minimal_demerits + best_pl_glue = { }, -- corresponding glue stretch or shrink + do_last_line_fit = false, + last_line_fit = last_line_fit, + + minimum_demerits = awful_badness, + + minimal_demerits = { + + [fit_very_loose_class] = awful_badness, + [fit_loose_class] = awful_badness, + [fit_decent_class] = awful_badness, + [fit_tight_class] = awful_badness, + + }, + + prev_char_p = nil, + + statistics = { + + noflines = 0, + nofprotrudedlines = 0, + nofadjustedlines = 0, + + }, + + -- -- just a thought ... parshape functions ... it would be nice to + -- -- also store the height so far (probably not too hard) although + -- -- in most cases we work on grids in such cases + -- + -- adapt_width = function(par,line) + -- -- carry attribute, so that we can accumulate + -- local left = 655360 * (line - 1) + -- local right = 655360 * (line - 1) + -- return left, right + -- end - } + } - -- optimizers + -- optimizers - par.used_left_skip = used_skip(par.left_skip) - par.used_right_skip = used_skip(par.right_skip) + par.used_left_skip = used_skip(par.left_skip) + par.used_right_skip = used_skip(par.right_skip) - -- so far + -- so far - if adjust_spacing > 1 then - local checked_expansion = { par = par } - setmetatableindex(checked_expansion,check_expand_pars) - par.checked_expansion = checked_expansion + if adjust_spacing > 1 then + local checked_expansion = { par = par } + setmetatableindex(checked_expansion,check_expand_pars) + par.checked_expansion = checked_expansion - if par.tolerance < hztolerance then - if not hzwarned then - report_parbuilders("setting tolerance to %a for hz",hztolerance) - hzwarned = true + if par.tolerance < hztolerance then + if not hzwarned then + report_parbuilders("setting tolerance to %a for hz",hztolerance) + hzwarned = true + end + par.tolerance = hztolerance end - par.tolerance = hztolerance - end - expand_kerns = expand_kerns_mode or (adjust_spacing == 2) + expand_kerns = expand_kerns_mode or (adjust_spacing == 2) - end + end - -- we need par for the error message + -- we need par for the error message - local background = par.background + local background = par.background - local l = check_shrinkage(par,left_skip) - local r = check_shrinkage(par,right_skip) + local l = check_shrinkage(par,left_skip) + local r = check_shrinkage(par,right_skip) - local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l) - local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r) + local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l) + local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r) - local l_order = stretch_orders[lstretch_order] - local r_order = stretch_orders[rstretch_order] + local l_order = fillcodes[lstretch_order] + local r_order = fillcodes[rstretch_order] - background.size = lwidth + rwidth - background.shrink = lshrink + rshrink - background[l_order] = lstretch - background[r_order] = rstretch + background[r_order] + background.size = lwidth + rwidth + background.shrink = lshrink + rshrink + background[l_order] = lstretch + background[r_order] = rstretch + background[r_order] - -- this will move up so that we can assign the whole par table + -- this will move up so that we can assign the whole par table - if not par_shape_ptr then - if hang_indent == 0 then - par.second_width = hsize - par.second_indent = 0 - else - local abs_hang_after = hang_after >0 and hang_after or -hang_after - local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent - par.last_special_line = abs_hang_after - if hang_after < 0 then - par.first_width = hsize - abs_hang_indent - if hang_indent >= 0 then - par.first_indent = hang_indent - else - par.first_indent = 0 - end + if not par_shape_ptr then + if hang_indent == 0 then par.second_width = hsize par.second_indent = 0 else - par.first_width = hsize - par.first_indent = 0 - par.second_width = hsize - abs_hang_indent - if hang_indent >= 0 then - par.second_indent = hang_indent - else + local abs_hang_after = hang_after >0 and hang_after or -hang_after + local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent + par.last_special_line = abs_hang_after + if hang_after < 0 then + par.first_width = hsize - abs_hang_indent + if hang_indent >= 0 then + par.first_indent = hang_indent + else + par.first_indent = 0 + end + par.second_width = hsize par.second_indent = 0 + else + par.first_width = hsize + par.first_indent = 0 + par.second_width = hsize - abs_hang_indent + if hang_indent >= 0 then + par.second_indent = hang_indent + else + par.second_indent = 0 + end end end + else + local last_special_line = #par_shape_ptr + par.last_special_line = last_special_line + local parshape = par_shape_ptr[last_special_line] + par.second_width = parshape[2] + par.second_indent = parshape[1] end - else - local last_special_line = #par_shape_ptr - par.last_special_line = last_special_line - local parshape = par_shape_ptr[last_special_line] - par.second_width = parshape[2] - par.second_indent = parshape[1] - end - if par.looseness == 0 then - par.easy_line = par.last_special_line - else - par.easy_line = max_halfword - end + if par.looseness == 0 then + par.easy_line = par.last_special_line + else + par.easy_line = max_halfword + end - if pretolerance >= 0 then - par.threshold = pretolerance - par.second_pass = false - par.final_pass = false - else - par.threshold = tolerance - par.second_pass = true - par.final_pass = par.emergency_stretch <= 0 - if trace_basic then - if par.final_pass then - report_parbuilders("enabling second and final pass") - else - report_parbuilders("enabling second pass") + if pretolerance >= 0 then + par.threshold = pretolerance + par.second_pass = false + par.final_pass = false + else + par.threshold = tolerance + par.second_pass = true + par.final_pass = par.emergency_stretch <= 0 + if trace_basic then + if par.final_pass then + report_parbuilders("enabling second and final pass") + else + report_parbuilders("enabling second pass") + end end end - end - if last_line_fit > 0 then - local final_par_glue = par.final_par_glue - local stretch = getfield(final_par_glue,"stretch") - local stretch_order = getfield(final_par_glue,"stretch_order") - if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then - par.do_last_line_fit = true - local si = stretch_orders[stretch_order] - if trace_lastlinefit or trace_basic then - report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit) + if last_line_fit > 0 then + local final_par_glue = par.final_par_glue + local stretch = getfield(final_par_glue,"stretch") + local stretch_order = getfield(final_par_glue,"stretch_order") + if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then + par.do_last_line_fit = true + local si = fillcodes[stretch_order] + if trace_lastlinefit or trace_basic then + report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit) + end + par.fill_width[si] = stretch end - par.fill_width[si] = stretch end - end - return par -end + return par + end --- there are still all kind of artefacts in here (a side effect I guess of pdftex, --- etex, omega and other extensions that got obscured by patching) + -- there are still all kind of artefacts in here (a side effect I guess of pdftex, + -- etex, omega and other extensions that got obscured by patching) -local function post_line_break(par) + local function post_line_break(par) - local prevgraf = texnest[texnest.ptr].prevgraf - local current_line = prevgraf + 1 -- the current line number being justified + local prevgraf = texnest[texnest.ptr].prevgraf + local current_line = prevgraf + 1 -- the current line number being justified - local adjust_spacing = par.adjust_spacing - local protrude_chars = par.protrude_chars - local statistics = par.statistics + local adjust_spacing = par.adjust_spacing + local protrude_chars = par.protrude_chars + local statistics = par.statistics - local stack = new_dir_stack() + local stack = new_dir_stack() - local leftskip = par.used_left_skip -- used or normal ? - local rightskip = par.right_skip - local parshape = par.par_shape_ptr - ----- ignored_dimen = par.ignored_dimen + local leftskip = par.used_left_skip -- used or normal ? + local rightskip = par.right_skip + local parshape = par.par_shape_ptr + ----- ignored_dimen = par.ignored_dimen - local adapt_width = par.adapt_width + local adapt_width = par.adapt_width - -- reverse the links of the relevant passive nodes, goto first breakpoint + -- reverse the links of the relevant passive nodes, goto first breakpoint - local current_break = nil + local current_break = nil - local break_node = par.best_bet.break_node - repeat - local first_break = break_node - break_node = break_node.prev_break - first_break.prev_break = current_break - current_break = first_break - until not break_node + local break_node = par.best_bet.break_node + repeat + local first_break = break_node + break_node = break_node.prev_break + first_break.prev_break = current_break + current_break = first_break + until not break_node - local head = par.head + local head = par.head - -- maybe : each_... + -- maybe : each_... - while current_break do + while current_break do - inject_dirs_at_begin_of_line(stack,head) + inject_dirs_at_begin_of_line(stack,head) - local disc_break = false - local post_disc_break = false - local glue_break = false + local disc_break = false + local post_disc_break = false + local glue_break = false - local lineend = nil -- q lineend refers to the last node of the line (and paragraph) - local lastnode = current_break.cur_break -- r lastnode refers to the node after which the dir nodes should be closed + local lineend = nil -- lineend : the last node of the line (and paragraph) + local lastnode = current_break.cur_break -- lastnode: the node after which the dir nodes should be closed - if not lastnode then - -- only at the end - lastnode = slide_node_list(head) -- todo: find_tail - if lastnode == par.final_par_glue then - lineend = lastnode - lastnode = getprev(lastnode) - end - else -- todo: use insert_list_after - local id = getid(lastnode) - if id == glue_code then - -- lastnode is normal skip - lastnode = replace_node(lastnode,new_rightskip(rightskip)) - glue_break = true - lineend = lastnode - lastnode = getprev(lastnode) - elseif id == disc_code then - local prevlast = getprev(lastnode) - local nextlast = getnext(lastnode) - local subtype = getsubtype(lastnode) - local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true) - if subtype == second_disc_code then - if not (getid(prevlast) == disc_code and getsubtype(prevlast) == first_disc_code) then - report_parbuilders('unsupported disc at location %a',3) - end - if pre then - flush_node_list(pre) - pre = nil -- signal + if not lastnode then + -- only at the end + lastnode = slide_node_list(head) -- todo: find_tail + if lastnode == par.final_par_glue then + lineend = lastnode + lastnode = getprev(lastnode) + end + else -- todo: use insert_list_after + local id = getid(lastnode) + if id == glue_code then + -- lastnode is normal skip + lastnode = replace_node(lastnode,new_rightskip(rightskip)) + glue_break = true + lineend = lastnode + lastnode = getprev(lastnode) + elseif id == disc_code then + local prevlast = getprev(lastnode) + local nextlast = getnext(lastnode) + local subtype = getsubtype(lastnode) + local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true) + if subtype == seconddisc_code then + if not (getid(prevlast) == disc_code and getsubtype(prevlast) == firstdisc_code) then + report_parbuilders('unsupported disc at location %a',3) + end + if pre then + flush_node_list(pre) + pre = nil -- signal + end + if replace then + setlink(prevlast,replace) + setlink(replacetail,lastnode) + replace = nil -- signal + end + setdisc(lastnode,pre,post,replace) + local pre, post, replace = getdisc(prevlast) + if pre then + flush_node_list(pre) + end + if replace then + flush_node_list(replace) + end + if post then + flush_node_list(post) + end + setdisc(prevlast) -- nil,nil,nil + elseif subtype == firstdisc_code then + -- what is v ... next probably + if not (getid(v) == disc_code and getsubtype(v) == seconddisc_code) then + report_parbuilders('unsupported disc at location %a',4) + end + setsubtype(nextlast,regulardisc_code) + setfield(nextlast,"replace",post) + setfield(lastnode,"post") -- nil end if replace then - setlink(prevlast,replace) - setlink(replacetail,lastnode) - replace = nil -- signal + flush_node_list(replace) end - setdisc(lastnode,pre,post,replace) - local pre, post, replace = getdisc(prevlast) if pre then - flush_node_list(pre) - end - if replace then - flush_node_list(replace) + setlink(prevlast,pre) + setlink(pretail,lastnode) end if post then - flush_node_list(post) - end - setdisc(prevlast) -- nil,nil,nil - elseif subtype == first_disc_code then - -- what is v ... next probably - if not (getid(v) == disc_code and getsubtype(v) == second_disc_code) then - report_parbuilders('unsupported disc at location %a',4) + setlink(lastnode,post) + setlink(posttail,nextlast) + post_disc_break = true end - setsubtype(nextlast,regular_disc_code) - setfield(nextlast,"replace",post) - setfield(lastnode,"post") -- nil - end - if replace then - flush_node_list(replace) + setdisc(lastnode) -- nil, nil, nil + disc_break = true + elseif id == kern_code then + setkern(lastnode,0) + elseif getid(lastnode) == math_code then + setkern(lastnode,0) -- surround + -- new in luatex + setglue(lastnode) -- zeros end - if pre then - setlink(prevlast,pre) - setlink(pretail,lastnode) + end + lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break) + local rightbox = current_break.passive_right_box + if rightbox then + lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox)) + end + if not lineend then + lineend = lastnode + end + if lineend and lineend ~= head and protrude_chars > 0 then + local id = getid(lineend) + local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend) + local p = find_protchar_right(getnext(head),c) + if p and getid(p) == glyph_code then + local w, last_rightmost_char = right_pw(p) + if last_rightmost_char and w ~= 0 then + -- so we inherit attributes, lineend is new pseudo head + lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w)) + end end - if post then - setlink(lastnode,post) - setlink(posttail,nextlast) - post_disc_break = true + end + -- we finish the line + local r = getnext(lineend) + setnext(lineend) + if not glue_break then + if rightskip then + insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head end - setdisc(lastnode) -- nil, nil, nil - disc_break = true - elseif id == kern_code then - setkern(lastnode,0) - elseif getid(lastnode) == math_code then - setkern(lastnode,0) -- surround - -- new in luatex - setglue(lastnode) -- zeros end - end - lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break) - local rightbox = current_break.passive_right_box - if rightbox then - lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox)) - end - if not lineend then - lineend = lastnode - end - if lineend and lineend ~= head and protrude_chars > 0 then - local id = getid(lineend) - local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend) - local p = find_protchar_right(getnext(head),c) - if p and getid(p) == glyph_code then - local w, last_rightmost_char = right_pw(p) - if last_rightmost_char and w ~= 0 then - -- so we inherit attributes, lineend is new pseudo head - lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w)) + -- each time ? + local q = getnext(head) + setlink(head,r) + -- insert leftbox (if needed after parindent) + local leftbox = current_break.passive_left_box + if leftbox then + local first = getnext(q) + if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then + insert_node_after(q,q,copy_node(leftbox)) + else + q = insert_node_before(q,q,copy_node(leftbox)) end end - end - -- we finish the line - local r = getnext(lineend) - setnext(lineend) - if not glue_break then - if rightskip then - insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head + if protrude_chars > 0 then + local p = find_protchar_left(q) + if p and getid(p) == glyph_code then + local w, last_leftmost_char = left_pw(p) + if last_leftmost_char and w ~= 0 then + -- so we inherit attributes, q is pseudo head and moves back + q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w)) + end + end end - end - -- each time ? - local q = getnext(head) - setlink(head,r) - -- insert leftbox (if needed after parindent) - local leftbox = current_break.passive_left_box - if leftbox then - local first = getnext(q) - if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then - insert_node_after(q,q,copy_node(leftbox)) + if leftskip then + q = insert_node_before(q,q,new_leftskip(leftskip)) + end + local cur_width, cur_indent + if current_line > par.last_special_line then + cur_indent = par.second_indent + cur_width = par.second_width + elseif parshape then + local shape = parshape[current_line] + cur_indent = shape[1] + cur_width = shape[2] else - q = insert_node_before(q,q,copy_node(leftbox)) - end - end - if protrude_chars > 0 then - local p = find_protchar_left(q) - if p and getid(p) == glyph_code then - local w, last_leftmost_char = left_pw(p) - if last_leftmost_char and w ~= 0 then - -- so we inherit attributes, q is pseudo head and moves back - q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w)) - end + cur_indent = par.first_indent + cur_width = par.first_width end - end - if leftskip then - q = insert_node_before(q,q,new_leftskip(leftskip)) - end - local cur_width, cur_indent - if current_line > par.last_special_line then - cur_indent = par.second_indent - cur_width = par.second_width - elseif parshape then - local shape = parshape[current_line] - cur_indent = shape[1] - cur_width = shape[2] - else - cur_indent = par.first_indent - cur_width = par.first_width - end - if adapt_width then -- extension - local l, r = adapt_width(par,current_line) - cur_indent = cur_indent + l - cur_width = cur_width - l - r - end + if adapt_width then -- extension + local l, r = adapt_width(par,current_line) + cur_indent = cur_indent + l + cur_width = cur_width - l - r + end - statistics.noflines = statistics.noflines + 1 - local finished_line = nil - if adjust_spacing > 0 then - statistics.nofadjustedlines = statistics.nofadjustedlines + 1 - finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) - else - finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) - end - if protrude_chars > 0 then - statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1 - end - -- wrong: - local adjust_head = texlists.adjust_head - local pre_adjust_head = texlists.pre_adjust_head - -- - setshift(finished_line,cur_indent) - -- - -- -- this is gone: - -- - -- if par.each_line_height ~= ignored_dimen then - -- setheight(finished_line,par.each_line_height) - -- end - -- if par.each_line_depth ~= ignored_dimen then - -- setdepth(finished_line,par.each_line_depth) - -- end - -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then - -- setheight(finished_line,par.first_line_height) - -- end - -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then - -- setdepth(finished_line,par.last_line_depth) - -- end - -- - if texlists.pre_adjust_head ~= pre_adjust_head then - append_list(par, texlists.pre_adjust_head) - texlists.pre_adjust_head = pre_adjust_head - end - append_to_vlist(par,finished_line) - if texlists.adjust_head ~= adjust_head then - append_list(par, texlists.adjust_head) - texlists.adjust_head = adjust_head - end - -- - local pen - if current_line + 1 ~= par.best_line then - if current_break.passive_pen_inter then - pen = current_break.passive_pen_inter + statistics.noflines = statistics.noflines + 1 + local finished_line = nil + if adjust_spacing > 0 then + statistics.nofadjustedlines = statistics.nofadjustedlines + 1 + finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) else - pen = par.inter_line_penalty - end - if current_line == prevgraf + 1 then - pen = pen + par.club_penalty - end - if current_line + 2 == par.best_line then - if par.display then - pen = pen + par.display_widow_penalty + finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) + end + if protrude_chars > 0 then + statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1 + end + -- wrong: + local adjust_head = texlists.adjust_head + local pre_adjust_head = texlists.pre_adjust_head + -- + setshift(finished_line,cur_indent) + -- + -- -- this is gone: + -- + -- if par.each_line_height ~= ignored_dimen then + -- setheight(finished_line,par.each_line_height) + -- end + -- if par.each_line_depth ~= ignored_dimen then + -- setdepth(finished_line,par.each_line_depth) + -- end + -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then + -- setheight(finished_line,par.first_line_height) + -- end + -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then + -- setdepth(finished_line,par.last_line_depth) + -- end + -- + if texlists.pre_adjust_head ~= pre_adjust_head then + append_list(par, texlists.pre_adjust_head) + texlists.pre_adjust_head = pre_adjust_head + end + append_to_vlist(par,finished_line) + if texlists.adjust_head ~= adjust_head then + append_list(par, texlists.adjust_head) + texlists.adjust_head = adjust_head + end + -- + local pen + if current_line + 1 ~= par.best_line then + if current_break.passive_pen_inter then + pen = current_break.passive_pen_inter else - pen = pen + par.widow_penalty + pen = par.inter_line_penalty end - end - if disc_break then - if current_break.passive_pen_broken ~= 0 then - pen = pen + current_break.passive_pen_broken - else - pen = pen + par.broken_penalty + if current_line == prevgraf + 1 then + pen = pen + par.club_penalty end - end - if pen ~= 0 then - append_to_vlist(par,new_penalty(pen)) - end - end - current_line = current_line + 1 - current_break = current_break.prev_break - if current_break and not post_disc_break then - local current = head - local next = nil - while true do - next = getnext(current) - if next == current_break.cur_break then - break + if current_line + 2 == par.best_line then + if par.display then + pen = pen + par.display_widow_penalty + else + pen = pen + par.widow_penalty + end end - local id = getid(next) - if id == glyph_code then - break - elseif id == localpar_code then - -- nothing - elseif id < math_code then - -- messy criterium - break - elseif id == math_code then - -- keep the math node - setkern(next,0) -- surround - -- new in luatex - setglue(lastnode) -- zeros - break - elseif id == kern_code then - local subtype = getsubtype(next) - if subtype == fontkern_code or subtype == accentkern_code then - -- fontkerns and accent kerns as well as otf injections - break + if disc_break then + if current_break.passive_pen_broken ~= 0 then + pen = pen + current_break.passive_pen_broken + else + pen = pen + par.broken_penalty end end - current = next + if pen ~= 0 then + append_to_vlist(par,new_penalty(pen)) + end end - if current ~= head then - setnext(current) - flush_node_list(getnext(head)) - setlink(head,next) + current_line = current_line + 1 + current_break = current_break.prev_break + if current_break and not post_disc_break then + local current = head + local next = nil + while true do + next = getnext(current) + if next == current_break.cur_break then + break + end + local id = getid(next) + if id == glyph_code then + break + elseif id == localpar_code then + -- nothing + elseif id < math_code then + -- messy criterium + break + elseif id == math_code then + -- keep the math node + setkern(next,0) -- surround + -- new in luatex + setglue(lastnode) -- zeros + break + elseif id == kern_code then + local subtype = getsubtype(next) + if subtype == fontkern_code or subtype == accentkern_code then + -- fontkerns and accent kerns as well as otf injections + break + end + end + current = next + end + if current ~= head then + setnext(current) + flush_node_list(getnext(head)) + setlink(head,next) + end end end - end - -- if current_line ~= par.best_line then - -- report_parbuilders("line breaking") - -- end - par.head = nil -- needs checking - current_line = current_line - 1 - if trace_basic then - report_parbuilders("paragraph broken into %a lines",current_line) - end - texnest[texnest.ptr].prevgraf = current_line -end - -local function wrap_up(par) - if par.tracing_paragraphs then - diagnostics.stop() - end - if par.do_last_line_fit then - local best_bet = par.best_bet - local active_short = best_bet.active_short - local active_glue = best_bet.active_glue - if active_short == 0 then - if trace_lastlinefit then - report_parbuilders("disabling last line fit, no active_short") - end - par.do_last_line_fit = false - else - local glue = par.final_par_glue - setwidth(glue,getwidth(glue) + active_short - active_glue) - setfield(glue,"stretch",0) - if trace_lastlinefit then - report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue) - end + -- if current_line ~= par.best_line then + -- report_parbuilders("line breaking") + -- end + par.head = nil -- needs checking + current_line = current_line - 1 + if trace_basic then + report_parbuilders("paragraph broken into %a lines",current_line) end + texnest[texnest.ptr].prevgraf = current_line end - -- we have a bunch of glue and and temp nodes not freed - local head = par.head - if getid(head) == temp_code then - par.head = getnext(head) - flush_node(head) - end - post_line_break(par) - reset_meta(par) - register_statistics(par) - return par.head_field -end --- we could do active nodes differently ... table instead of linked list or a list --- with prev nodes but it doesn't save much (as we still need to keep indices then --- in next) - -local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled - local active = par.active - local active_width = par.active_width - prev_r.next = r.next - -- removes r - -- r = nil - if prev_r == active then - r = active.next - if r.id == delta_code then - local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw - local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw - local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw - local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw - local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw - local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw - local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw - if checked_expansion then - local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw - local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw - end - active.next = r.next - -- removes r - -- r = nil + local function wrap_up(par) + if par.tracing_paragraphs then + diagnostics.stop() end - elseif prev_r.id == delta_code then - r = prev_r.next - if r == active then - cur_active_width.size = cur_active_width.size - prev_r.size - cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch - cur_active_width.fi = cur_active_width.fi - prev_r.fi - cur_active_width.fil = cur_active_width.fil - prev_r.fil - cur_active_width.fill = cur_active_width.fill - prev_r.fill - cur_active_width.filll = cur_active_width.filll - prev_r.filll - cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink - if checked_expansion then - cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch - cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink + if par.do_last_line_fit then + local best_bet = par.best_bet + local active_short = best_bet.active_short + local active_glue = best_bet.active_glue + if active_short == 0 then + if trace_lastlinefit then + report_parbuilders("disabling last line fit, no active_short") + end + par.do_last_line_fit = false + else + local glue = par.final_par_glue + setwidth(glue,getwidth(glue) + active_short - active_glue) + setfield(glue,"stretch",0) + if trace_lastlinefit then + report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue) + end end - prev_prev_r.next = active - -- removes prev_r - -- prev_r = nil - prev_r = prev_prev_r - elseif r.id == delta_code then - local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn - local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn - local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn - local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn - local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn - local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn - local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn - if checked_expansion then - local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn - local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn + end + -- we have a bunch of glue and and temp nodes not freed + local head = par.head + if getid(head) == temp_code then + par.head = getnext(head) + flush_node(head) + end + post_line_break(par) + reset_meta(par) + register_statistics(par) + return par.head_field + end + + -- we could do active nodes differently ... table instead of linked list or a list + -- with prev nodes but it doesn't save much (as we still need to keep indices then + -- in next) + + local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled + local active = par.active + local active_width = par.active_width + prev_r.next = r.next + -- removes r + -- r = nil + if prev_r == active then + r = active.next + if r.id == delta_code then + local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw + local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw + local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw + local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw + local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw + local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw + local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw + if checked_expansion then + local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw + local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw + end + active.next = r.next + -- removes r + -- r = nil + end + elseif prev_r.id == delta_code then + r = prev_r.next + if r == active then + cur_active_width.size = cur_active_width.size - prev_r.size + cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch + cur_active_width.fi = cur_active_width.fi - prev_r.fi + cur_active_width.fil = cur_active_width.fil - prev_r.fil + cur_active_width.fill = cur_active_width.fill - prev_r.fill + cur_active_width.filll = cur_active_width.filll - prev_r.filll + cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink + if checked_expansion then + cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch + cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink + end + prev_prev_r.next = active + -- removes prev_r + -- prev_r = nil + prev_r = prev_prev_r + elseif r.id == delta_code then + local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn + local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn + local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn + local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn + local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn + local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn + local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn + if checked_expansion then + local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn + local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn + end + prev_r.next = r.next + -- removes r + -- r = nil end - prev_r.next = r.next - -- removes r - -- r = nil end + return prev_r, r end - return prev_r, r -end -local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit) - if active_short == 0 or active_glue <= 0 then - return false, 0, fit_decent_class, 0, 0 - end - if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then - return false, 0, fit_decent_class, 0, 0 - end - local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink - if adjustment <= 0 then - return false, 0, fit_decent_class, adjustment, 0 - end - adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen) - if last_line_fit < 1000 then - adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment - end - local fit_class = fit_decent_class - if adjustment > 0 then - local stretch = cur_active_width.stretch - if adjustment > shortfall then - adjustment = shortfall - end - if adjustment > 7230584 and stretch < 1663497 then - return true, fit_very_loose_class, shortfall, adjustment, infinite_badness + local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit) + if active_short == 0 or active_glue <= 0 then + return false, 0, fit_decent_class, 0, 0 end - -- if adjustment == 0 then -- badness = 0 - -- return true, shortfall, fit_decent_class, 0, 0 - -- elseif stretch <= 0 then -- badness = 10000 - -- return true, shortfall, fit_very_loose_class, adjustment, 10000 - -- end - -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch) - local badness = calculate_badness(adjustment,stretch) - if badness > 99 then - return true, shortfall, fit_very_loose_class, adjustment, badness - elseif badness > 12 then - return true, shortfall, fit_loose_class, adjustment, badness - else - return true, shortfall, fit_decent_class, adjustment, badness + if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then + return false, 0, fit_decent_class, 0, 0 end - elseif adjustment < 0 then - local shrink = cur_active_width.shrink - if -adjustment > shrink then - adjustment = -shrink + local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink + if adjustment <= 0 then + return false, 0, fit_decent_class, adjustment, 0 end - local badness = calculate_badness(-adjustment,shrink) - if badness > 12 then - return true, shortfall, fit_tight_class, adjustment, badness - else - return true, shortfall, fit_decent_class, adjustment, badness + adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen) + if last_line_fit < 1000 then + adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment end - else - return false, 0, fit_decent_class, 0, 0 - end -end - --- todo: statistics .. count tries and so - -local trialcount = 0 - -local function try_break(pi, break_type, par, first_p, current, checked_expansion) - --- trialcount = trialcount + 1 --- print(trialcount,pi,break_type,current,nuts.tostring(current)) - - if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty - local p_active = par.active - return p_active, p_active and p_active.next - elseif pi <= -infinite_penalty then -- this breakpoint will be forced - pi = eject_penalty - end - - local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code - local prev_r = par.active -- stays a step behind r - local r = nil -- runs through the active list - local no_break_yet = true -- have we found a feasible break at current? - local node_r_stays_active = false -- should node r remain in the active list? - local line_width = 0 -- the current line will be justified to this width - local line_number = 0 -- line number of current active node - local old_line_number = 0 -- maximum line number in current equivalence class of lines - - local protrude_chars = par.protrude_chars - local checked_expansion = par.checked_expansion - local break_width = par.break_width - local active_width = par.active_width - local background = par.background - local minimal_demerits = par.minimal_demerits - local best_place = par.best_place - local best_pl_line = par.best_pl_line - local best_pl_short = par.best_pl_short - local best_pl_glue = par.best_pl_glue - local do_last_line_fit = par.do_last_line_fit - local final_pass = par.final_pass - local tracing_paragraphs = par.tracing_paragraphs - -- local par_active = par.active - - local adapt_width = par.adapt_width - - local parshape = par.par_shape_ptr - - local cur_active_width = checked_expansion and { -- distance from current active node - size = active_width.size, - stretch = active_width.stretch, - fi = active_width.fi, - fil = active_width.fil, - fill = active_width.fill, - filll = active_width.filll, - shrink = active_width.shrink, - adjust_stretch = active_width.adjust_stretch, - adjust_shrink = active_width.adjust_shrink, - } or { - size = active_width.size, - stretch = active_width.stretch, - fi = active_width.fi, - fil = active_width.fil, - fill = active_width.fill, - filll = active_width.filll, - shrink = active_width.shrink, - } - - while true do - r = prev_r.next - if r.id == delta_code then - cur_active_width.size = cur_active_width.size + r.size - cur_active_width.stretch = cur_active_width.stretch + r.stretch - cur_active_width.fi = cur_active_width.fi + r.fi - cur_active_width.fil = cur_active_width.fil + r.fil - cur_active_width.fill = cur_active_width.fill + r.fill - cur_active_width.filll = cur_active_width.filll + r.filll - cur_active_width.shrink = cur_active_width.shrink + r.shrink - if checked_expansion then - cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch - cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink + local fit_class = fit_decent_class + if adjustment > 0 then + local stretch = cur_active_width.stretch + if adjustment > shortfall then + adjustment = shortfall + end + if adjustment > 7230584 and stretch < 1663497 then + return true, fit_very_loose_class, shortfall, adjustment, infinite_badness + end + -- if adjustment == 0 then -- badness = 0 + -- return true, shortfall, fit_decent_class, 0, 0 + -- elseif stretch <= 0 then -- badness = 10000 + -- return true, shortfall, fit_very_loose_class, adjustment, 10000 + -- end + -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch) + local badness = calculate_badness(adjustment,stretch) + if badness > 99 then + return true, shortfall, fit_very_loose_class, adjustment, badness + elseif badness > 12 then + return true, shortfall, fit_loose_class, adjustment, badness + else + return true, shortfall, fit_decent_class, adjustment, badness + end + elseif adjustment < 0 then + local shrink = cur_active_width.shrink + if -adjustment > shrink then + adjustment = -shrink + end + local badness = calculate_badness(-adjustment,shrink) + if badness > 12 then + return true, shortfall, fit_tight_class, adjustment, badness + else + return true, shortfall, fit_decent_class, adjustment, badness end - prev_prev_r = prev_r - prev_r = r else - line_number = r.line_number - if line_number > old_line_number then - local minimum_demerits = par.minimum_demerits - if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then - if no_break_yet then - no_break_yet = false - break_width.size = background.size - break_width.stretch = background.stretch - break_width.fi = background.fi - break_width.fil = background.fil - break_width.fill = background.fill - break_width.filll = background.filll - break_width.shrink = background.shrink - if checked_expansion then - break_width.adjust_stretch = 0 - break_width.adjust_shrink = 0 + return false, 0, fit_decent_class, 0, 0 + end + end + + -- todo: statistics .. count tries and so + + local trialcount = 0 + + local function try_break(pi, break_type, par, first_p, current, checked_expansion) + + -- trialcount = trialcount + 1 + -- print(trialcount,pi,break_type,current,nuts.tostring(current)) + + if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty + local p_active = par.active + return p_active, p_active and p_active.next + elseif pi <= -infinite_penalty then -- this breakpoint will be forced + pi = eject_penalty + end + + local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code + local prev_r = par.active -- stays a step behind r + local r = nil -- runs through the active list + local no_break_yet = true -- have we found a feasible break at current? + local node_r_stays_active = false -- should node r remain in the active list? + local line_width = 0 -- the current line will be justified to this width + local line_number = 0 -- line number of current active node + local old_line_number = 0 -- maximum line number in current equivalence class of lines + + local protrude_chars = par.protrude_chars + local checked_expansion = par.checked_expansion + local break_width = par.break_width + local active_width = par.active_width + local background = par.background + local minimal_demerits = par.minimal_demerits + local best_place = par.best_place + local best_pl_line = par.best_pl_line + local best_pl_short = par.best_pl_short + local best_pl_glue = par.best_pl_glue + local do_last_line_fit = par.do_last_line_fit + local final_pass = par.final_pass + local tracing_paragraphs = par.tracing_paragraphs + -- local par_active = par.active + + local adapt_width = par.adapt_width + + local parshape = par.par_shape_ptr + + local cur_active_width = checked_expansion and { -- distance from current active node + size = active_width.size, + stretch = active_width.stretch, + fi = active_width.fi, + fil = active_width.fil, + fill = active_width.fill, + filll = active_width.filll, + shrink = active_width.shrink, + adjust_stretch = active_width.adjust_stretch, + adjust_shrink = active_width.adjust_shrink, + } or { + size = active_width.size, + stretch = active_width.stretch, + fi = active_width.fi, + fil = active_width.fil, + fill = active_width.fill, + filll = active_width.filll, + shrink = active_width.shrink, + } + + while true do + r = prev_r.next + if r.id == delta_code then + cur_active_width.size = cur_active_width.size + r.size + cur_active_width.stretch = cur_active_width.stretch + r.stretch + cur_active_width.fi = cur_active_width.fi + r.fi + cur_active_width.fil = cur_active_width.fil + r.fil + cur_active_width.fill = cur_active_width.fill + r.fill + cur_active_width.filll = cur_active_width.filll + r.filll + cur_active_width.shrink = cur_active_width.shrink + r.shrink + if checked_expansion then + cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch + cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink + end + prev_prev_r = prev_r + prev_r = r + else + line_number = r.line_number + if line_number > old_line_number then + local minimum_demerits = par.minimum_demerits + if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then + if no_break_yet then + no_break_yet = false + break_width.size = background.size + break_width.stretch = background.stretch + break_width.fi = background.fi + break_width.fil = background.fil + break_width.fill = background.fill + break_width.filll = background.filll + break_width.shrink = background.shrink + if checked_expansion then + break_width.adjust_stretch = 0 + break_width.adjust_shrink = 0 + end + if current then + compute_break_width(par,break_type,current) + end end - if current then - compute_break_width(par,break_type,current) + if prev_r.id == delta_code then + prev_r.size = prev_r.size - cur_active_width.size + break_width.size + prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch + prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi + prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil + prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill + prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll + prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink + if checked_expansion then + prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch + prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink + end + elseif prev_r == par.active then + active_width.size = break_width.size + active_width.stretch = break_width.stretch + active_width.fi = break_width.fi + active_width.fil = break_width.fil + active_width.fill = break_width.fill + active_width.filll = break_width.filll + active_width.shrink = break_width.shrink + if checked_expansion then + active_width.adjust_stretch = break_width.adjust_stretch + active_width.adjust_shrink = break_width.adjust_shrink + end + else + local q = checked_expansion and { + id = delta_code, + subtype = nosubtype_code, + next = r, + size = break_width.size - cur_active_width.size, + stretch = break_width.stretch - cur_active_width.stretch, + fi = break_width.fi - cur_active_width.fi, + fil = break_width.fil - cur_active_width.fil, + fill = break_width.fill - cur_active_width.fill, + filll = break_width.filll - cur_active_width.filll, + shrink = break_width.shrink - cur_active_width.shrink, + adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch, + adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink, + } or { + id = delta_code, + subtype = nosubtype_code, + next = r, + size = break_width.size - cur_active_width.size, + stretch = break_width.stretch - cur_active_width.stretch, + fi = break_width.fi - cur_active_width.fi, + fil = break_width.fil - cur_active_width.fil, + fill = break_width.fill - cur_active_width.fill, + filll = break_width.filll - cur_active_width.filll, + shrink = break_width.shrink - cur_active_width.shrink, + } + prev_r.next = q + prev_prev_r = prev_r + prev_r = q end - end - if prev_r.id == delta_code then - prev_r.size = prev_r.size - cur_active_width.size + break_width.size - prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch - prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi - prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil - prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill - prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll - prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink - if checked_expansion then - prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch - prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink + local adj_demerits = par.adj_demerits + local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits + if abs_adj_demerits >= awful_badness - minimum_demerits then + minimum_demerits = awful_badness - 1 + else + minimum_demerits = minimum_demerits + abs_adj_demerits end - elseif prev_r == par.active then - active_width.size = break_width.size - active_width.stretch = break_width.stretch - active_width.fi = break_width.fi - active_width.fil = break_width.fil - active_width.fill = break_width.fill - active_width.filll = break_width.filll - active_width.shrink = break_width.shrink - if checked_expansion then - active_width.adjust_stretch = break_width.adjust_stretch - active_width.adjust_shrink = break_width.adjust_shrink + for fit_class = fit_very_loose_class, fit_tight_class do + if minimal_demerits[fit_class] <= minimum_demerits then + -- insert a new active node from best_place[fit_class] to current + par.pass_number = par.pass_number + 1 + local prev_break = best_place[fit_class] + local passive = { + id = passive_code, + subtype = nosubtype_code, + next = par.passive, + cur_break = current, + serial = par.pass_number, + prev_break = prev_break, + passive_pen_inter = par.internal_pen_inter, + passive_pen_broken = par.internal_pen_broken, + passive_last_left_box = par.internal_left_box, + passive_last_left_box_width = par.internal_left_box_width, + passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box, + passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width, + passive_right_box = par.internal_right_box, + passive_right_box_width = par.internal_right_box_width, + -- analysis = table.fastcopy(cur_active_width), + } + par.passive = passive + local q = { + id = break_type, + subtype = fit_class, + break_node = passive, + line_number = best_pl_line[fit_class] + 1, + total_demerits = minimal_demerits[fit_class], -- or 0, + next = r, + } + if do_last_line_fit then + local active_short = best_pl_short[fit_class] + local active_glue = best_pl_glue[fit_class] + q.active_short = active_short + q.active_glue = active_glue + if trace_lastlinefit then + report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class) + end + end + -- q.next = r -- already done + prev_r.next = q + prev_r = q + if tracing_paragraphs then + diagnostics.break_node(par,q,fit_class,break_type,current) + end + end + minimal_demerits[fit_class] = awful_badness end - else - local q = checked_expansion and { - id = delta_code, - subtype = nosubtype_code, - next = r, - size = break_width.size - cur_active_width.size, - stretch = break_width.stretch - cur_active_width.stretch, - fi = break_width.fi - cur_active_width.fi, - fil = break_width.fil - cur_active_width.fil, - fill = break_width.fill - cur_active_width.fill, - filll = break_width.filll - cur_active_width.filll, - shrink = break_width.shrink - cur_active_width.shrink, - adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch, - adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink, - } or { - id = delta_code, - subtype = nosubtype_code, - next = r, - size = break_width.size - cur_active_width.size, - stretch = break_width.stretch - cur_active_width.stretch, - fi = break_width.fi - cur_active_width.fi, - fil = break_width.fil - cur_active_width.fil, - fill = break_width.fill - cur_active_width.fill, - filll = break_width.filll - cur_active_width.filll, - shrink = break_width.shrink - cur_active_width.shrink, - } - prev_r.next = q - prev_prev_r = prev_r - prev_r = q - end - local adj_demerits = par.adj_demerits - local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits - if abs_adj_demerits >= awful_badness - minimum_demerits then - minimum_demerits = awful_badness - 1 - else - minimum_demerits = minimum_demerits + abs_adj_demerits - end - for fit_class = fit_very_loose_class, fit_tight_class do - if minimal_demerits[fit_class] <= minimum_demerits then - -- insert a new active node from best_place[fit_class] to current - par.pass_number = par.pass_number + 1 - local prev_break = best_place[fit_class] - local passive = { - id = passive_code, - subtype = nosubtype_code, - next = par.passive, - cur_break = current, - serial = par.pass_number, - prev_break = prev_break, - passive_pen_inter = par.internal_pen_inter, - passive_pen_broken = par.internal_pen_broken, - passive_last_left_box = par.internal_left_box, - passive_last_left_box_width = par.internal_left_box_width, - passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box, - passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width, - passive_right_box = par.internal_right_box, - passive_right_box_width = par.internal_right_box_width, --- analysis = table.fastcopy(cur_active_width), - } - par.passive = passive - local q = { - id = break_type, - subtype = fit_class, - break_node = passive, - line_number = best_pl_line[fit_class] + 1, - total_demerits = minimal_demerits[fit_class], -- or 0, + par.minimum_demerits = awful_badness + if r ~= par.active then + local q = checked_expansion and { + id = delta_code, + subtype = nosubtype_code, + next = r, + size = cur_active_width.size - break_width.size, + stretch = cur_active_width.stretch - break_width.stretch, + fi = cur_active_width.fi - break_width.fi, + fil = cur_active_width.fil - break_width.fil, + fill = cur_active_width.fill - break_width.fill, + filll = cur_active_width.filll - break_width.filll, + shrink = cur_active_width.shrink - break_width.shrink, + adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch, + adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink, + } or { + id = delta_code, + subtype = nosubtype_code, next = r, + size = cur_active_width.size - break_width.size, + stretch = cur_active_width.stretch - break_width.stretch, + fi = cur_active_width.fi - break_width.fi, + fil = cur_active_width.fil - break_width.fil, + fill = cur_active_width.fill - break_width.fill, + filll = cur_active_width.filll - break_width.filll, + shrink = cur_active_width.shrink - break_width.shrink, } - if do_last_line_fit then - local active_short = best_pl_short[fit_class] - local active_glue = best_pl_glue[fit_class] - q.active_short = active_short - q.active_glue = active_glue - if trace_lastlinefit then - report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class) - end - end -- q.next = r -- already done prev_r.next = q + prev_prev_r = prev_r prev_r = q - if tracing_paragraphs then - diagnostics.break_node(par,q,fit_class,break_type,current) - end end - minimal_demerits[fit_class] = awful_badness - end - par.minimum_demerits = awful_badness - if r ~= par.active then - local q = checked_expansion and { - id = delta_code, - subtype = nosubtype_code, - next = r, - size = cur_active_width.size - break_width.size, - stretch = cur_active_width.stretch - break_width.stretch, - fi = cur_active_width.fi - break_width.fi, - fil = cur_active_width.fil - break_width.fil, - fill = cur_active_width.fill - break_width.fill, - filll = cur_active_width.filll - break_width.filll, - shrink = cur_active_width.shrink - break_width.shrink, - adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch, - adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink, - } or { - id = delta_code, - subtype = nosubtype_code, - next = r, - size = cur_active_width.size - break_width.size, - stretch = cur_active_width.stretch - break_width.stretch, - fi = cur_active_width.fi - break_width.fi, - fil = cur_active_width.fil - break_width.fil, - fill = cur_active_width.fill - break_width.fill, - filll = cur_active_width.filll - break_width.filll, - shrink = cur_active_width.shrink - break_width.shrink, - } - -- q.next = r -- already done - prev_r.next = q - prev_prev_r = prev_r - prev_r = q end - end - if r == par.active then - return r, r and r.next -- p_active, n_active - end - if line_number > par.easy_line then - old_line_number = max_halfword - 1 - line_width = par.second_width - else - old_line_number = line_number - if line_number > par.last_special_line then + if r == par.active then + return r, r and r.next -- p_active, n_active + end + if line_number > par.easy_line then + old_line_number = max_halfword - 1 line_width = par.second_width - elseif parshape then - line_width = parshape[line_number][2] else - line_width = par.first_width + old_line_number = line_number + if line_number > par.last_special_line then + line_width = par.second_width + elseif parshape then + line_width = parshape[line_number][2] + else + line_width = par.first_width + end end - end - if adapt_width then - local l, r = adapt_width(par,line_number) - line_width = line_width - l - r - end - end - local artificial_demerits = false -- has d been forced to zero - local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations - if not r.break_node then - shortfall = shortfall - par.init_internal_left_box_width - else - shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0) - end - local pw, lp, rp -- used later on - if protrude_chars > 1 then - -- this is quite time consuming - local b = r.break_node - local l = b and b.cur_break or first_p - local o = current and getprev(current) - if current and getid(current) == disc_code then - local pre, _, _, pretail = getdisc(current,true) - if pre then - o = pretail - else - o = find_protchar_right(l,o) + if adapt_width then + local l, r = adapt_width(par,line_number) + line_width = line_width - l - r end - else - o = find_protchar_right(l,o) end - if o and getid(o) == glyph_code then - pw, rp = right_pw(o) - shortfall = shortfall + pw - end - local id = getid(l) - if id == glyph_code then - -- ok ? - elseif id == disc_code and getfield(l,"post") then - l = getfield(l,"post") -- TODO: first char could be a disc + local artificial_demerits = false -- has d been forced to zero + local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations + if not r.break_node then + shortfall = shortfall - par.init_internal_left_box_width else - l = find_protchar_left(l) - end - if l and getid(l) == glyph_code then - pw, lp = left_pw(l) - shortfall = shortfall + pw + shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0) end - end - if checked_expansion and shortfall ~= 0 then - local margin_kern_stretch = 0 - local margin_kern_shrink = 0 + local pw, lp, rp -- used later on if protrude_chars > 1 then - if lp then - local data = expansions[getfont(lp)][getchar(lp)] - if data then - margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink + -- this is quite time consuming + local b = r.break_node + local l = b and b.cur_break or first_p + local o = current and getprev(current) + if current and getid(current) == disc_code then + local pre, _, _, pretail = getdisc(current,true) + if pre then + o = pretail + else + o = find_protchar_right(l,o) end + else + o = find_protchar_right(l,o) end - if rp then - local data = expansions[getfont(lp)][getchar(lp)] - if data then - margin_kern_stretch = margin_kern_stretch + data.glyphstretch - margin_kern_shrink = margin_kern_shrink + data.glyphshrink - end + if o and getid(o) == glyph_code then + pw, rp = right_pw(o) + shortfall = shortfall + pw end - end - local total = cur_active_width.adjust_stretch + margin_kern_stretch - if shortfall > 0 and total > 0 then - if total > shortfall then - shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2 + local id = getid(l) + if id == glyph_code then + -- ok ? + elseif id == disc_code and getfield(l,"post") then + l = getfield(l,"post") -- TODO: first char could be a disc else - shortfall = shortfall - total + l = find_protchar_left(l) end - else - total = cur_active_width.adjust_shrink + margin_kern_shrink - if shortfall < 0 and total > 0 then - if total > - shortfall then - shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2 - else - shortfall = shortfall + total - end + if l and getid(l) == glyph_code then + pw, lp = left_pw(l) + shortfall = shortfall + pw end end - end - local b = 0 - local g = 0 - local fit_class = fit_decent_class - local found = false - if shortfall > 0 then - if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then - if not do_last_line_fit then - -- okay - elseif not current then - found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit) + if checked_expansion and shortfall ~= 0 then + local margin_kern_stretch = 0 + local margin_kern_shrink = 0 + if protrude_chars > 1 then + if lp then + local char, font = isglyph(lp) + local data = expansions[font][char] + if data then + margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink + end + end + if rp then + local char, font = isglyph(rp) + local data = expansions[font][char] + if data then + margin_kern_stretch = margin_kern_stretch + data.glyphstretch + margin_kern_shrink = margin_kern_shrink + data.glyphshrink + end + end + end + local total = cur_active_width.adjust_stretch + margin_kern_stretch + if shortfall > 0 and total > 0 then + if total > shortfall then + shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2 + else + shortfall = shortfall - total + end else - shortfall = 0 + total = cur_active_width.adjust_shrink + margin_kern_shrink + if shortfall < 0 and total > 0 then + if total > - shortfall then + shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2 + else + shortfall = shortfall + total + end + end end - else - local stretch = cur_active_width.stretch - if shortfall > 7230584 and stretch < 1663497 then - b = infinite_badness - fit_class = fit_very_loose_class + end + local b = 0 + local g = 0 + local fit_class = fit_decent_class + local found = false + if shortfall > 0 then + if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then + if not do_last_line_fit then + -- okay + elseif not current then + found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit) + else + shortfall = 0 + end else - b = calculate_badness(shortfall,stretch) - if b > 99 then + local stretch = cur_active_width.stretch + if shortfall > 7230584 and stretch < 1663497 then + b = infinite_badness fit_class = fit_very_loose_class - elseif b > 12 then - fit_class = fit_loose_class else - fit_class = fit_decent_class + b = calculate_badness(shortfall,stretch) + if b > 99 then + fit_class = fit_very_loose_class + elseif b > 12 then + fit_class = fit_loose_class + else + fit_class = fit_decent_class + end end end - end - else - local shrink = cur_active_width.shrink - if -shortfall > shrink then - b = infinite_badness + 1 - else - b = calculate_badness(-shortfall,shrink) - end - if b > 12 then - fit_class = fit_tight_class - else - fit_class = fit_decent_class - end - end - if do_last_line_fit and not found then - if not current then - -- g = 0 - shortfall = 0 - elseif shortfall > 0 then - g = cur_active_width.stretch - elseif shortfall < 0 then - g = cur_active_width.shrink else - g = 0 + local shrink = cur_active_width.shrink + if -shortfall > shrink then + b = infinite_badness + 1 + else + b = calculate_badness(-shortfall,shrink) + end + if b > 12 then + fit_class = fit_tight_class + else + fit_class = fit_decent_class + end end - end - -- ::FOUND:: - local continue_only = false -- brrr - if b > infinite_badness or pi == eject_penalty then - if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then - artificial_demerits = true -- set demerits zero, this break is forced - node_r_stays_active = false - elseif b > par.threshold then - prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) - continue_only = true - else - node_r_stays_active = false + if do_last_line_fit and not found then + if not current then + -- g = 0 + shortfall = 0 + elseif shortfall > 0 then + g = cur_active_width.stretch + elseif shortfall < 0 then + g = cur_active_width.shrink + else + g = 0 + end end - else - prev_r = r - if b > par.threshold then - continue_only = true + -- ::FOUND:: + local continue_only = false -- brrr + if b > infinite_badness or pi == eject_penalty then + if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then + artificial_demerits = true -- set demerits zero, this break is forced + node_r_stays_active = false + elseif b > par.threshold then + prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) + continue_only = true + else + node_r_stays_active = false + end else - node_r_stays_active = true - end - end - if not continue_only then - local d = 0 - if not artificial_demerits then - d = par.line_penalty + b - if (d >= 0 and d or -d) >= 10000 then -- abs(d) - d = 100000000 + prev_r = r + if b > par.threshold then + continue_only = true else - d = d * d + node_r_stays_active = true end - if pi == 0 then - -- nothing - elseif pi > 0 then - d = d + pi * pi - elseif pi > eject_penalty then - d = d - pi * pi - end - if break_type == hyphenated_code and r.id == hyphenated_code then - if current then - d = d + par.double_hyphen_demerits + end + if not continue_only then + local d = 0 + if not artificial_demerits then + d = par.line_penalty + b + if (d >= 0 and d or -d) >= 10000 then -- abs(d) + d = 100000000 else - d = d + par.final_hyphen_demerits + d = d * d + end + if pi == 0 then + -- nothing + elseif pi > 0 then + d = d + pi * pi + elseif pi > eject_penalty then + d = d - pi * pi + end + if break_type == hyphenated_code and r.id == hyphenated_code then + if current then + d = d + par.double_hyphen_demerits + else + d = d + par.final_hyphen_demerits + end + end + local delta = fit_class - r.subtype + if (delta >= 0 and delta or -delta) > 1 then -- abs(delta) + d = d + par.adj_demerits end end - local delta = fit_class - r.subtype - if (delta >= 0 and delta or -delta) > 1 then -- abs(delta) - d = d + par.adj_demerits + if tracing_paragraphs then + diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits) end - end - if tracing_paragraphs then - diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits) - end - d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r - if d <= minimal_demerits[fit_class] then - minimal_demerits[fit_class] = d - best_place [fit_class] = r.break_node - best_pl_line [fit_class] = line_number - if do_last_line_fit then - best_pl_short[fit_class] = shortfall - best_pl_glue [fit_class] = g - if trace_lastlinefit then - report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class) + d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r + if d <= minimal_demerits[fit_class] then + minimal_demerits[fit_class] = d + best_place [fit_class] = r.break_node + best_pl_line [fit_class] = line_number + if do_last_line_fit then + best_pl_short[fit_class] = shortfall + best_pl_glue [fit_class] = g + if trace_lastlinefit then + report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class) + end + end + if d < par.minimum_demerits then + par.minimum_demerits = d end end - if d < par.minimum_demerits then - par.minimum_demerits = d + if not node_r_stays_active then + prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) end end - if not node_r_stays_active then - prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) - end end end end -end - --- we can call the normal one for simple box building in the otr so we need --- frequent enabling/disabling -local dcolor = { [0] = "red", "green", "blue", "magenta", "cyan", "gray" } + -- we can call the normal one for simple box building in the otr so we need + -- frequent enabling/disabling -local temp_head = new_temp() + local temp_head = new_temp() -function constructors.methods.basic(head,d) - head = tonut(head) - - if trace_basic then - report_parbuilders("starting at %a",head) - end + function constructors.methods.basic(head,d) + if trace_basic then + report_parbuilders("starting at %a",head) + end - local par = initialize_line_break(head,d) + local par = initialize_line_break(head,d) - local checked_expansion = par.checked_expansion - local active_width = par.active_width - local disc_width = par.disc_width - local background = par.background - local tracing_paragraphs = par.tracing_paragraphs + local checked_expansion = par.checked_expansion + local active_width = par.active_width + local disc_width = par.disc_width + local background = par.background + local tracing_paragraphs = par.tracing_paragraphs - local dirstack = new_dir_stack() + local dirstack = new_dir_stack() - if tracing_paragraphs then - diagnostics.start() - if par.pretolerance >= 0 then - diagnostics.current_pass(par,"firstpass") + if tracing_paragraphs then + diagnostics.start() + if par.pretolerance >= 0 then + diagnostics.current_pass(par,"firstpass") + end end - end - while true do - reset_meta(par) - if par.threshold > infinite_badness then - par.threshold = infinite_badness - end - par.active.next = { - id = unhyphenated_code, - subtype = fit_decent_class, - next = par.active, - break_node = nil, - line_number = par.first_line + 1, - total_demerits = 0, - active_short = 0, - active_glue = 0, - } - active_width.size = background.size - active_width.stretch = background.stretch - active_width.fi = background.fi - active_width.fil = background.fil - active_width.fill = background.fill - active_width.filll = background.filll - active_width.shrink = background.shrink - - if checked_expansion then - active_width.adjust_stretch = 0 - active_width.adjust_shrink = 0 - end + while true do + reset_meta(par) + if par.threshold > infinite_badness then + par.threshold = infinite_badness + end + par.active.next = { + id = unhyphenated_code, + subtype = fit_decent_class, + next = par.active, + break_node = nil, + line_number = par.first_line + 1, + total_demerits = 0, + active_short = 0, + active_glue = 0, + } + active_width.size = background.size + active_width.stretch = background.stretch + active_width.fi = background.fi + active_width.fil = background.fil + active_width.fill = background.fill + active_width.filll = background.filll + active_width.shrink = background.shrink - par.passive = nil -- = 0 - par.printed_node = temp_head -- only when tracing, shared - par.pass_number = 0 --- par.auto_breaking = true + if checked_expansion then + active_width.adjust_stretch = 0 + active_width.adjust_shrink = 0 + end - setnext(temp_head,head) + par.passive = nil -- = 0 + par.printed_node = temp_head -- only when tracing, shared + par.pass_number = 0 + -- par.auto_breaking = true - local current = head - local first_p = current + setnext(temp_head,head) - local auto_breaking = true + local current = head + local first_p = current - par.font_in_short_display = 0 + local auto_breaking = true - if current then - local id = getid(current) - if id == localpar_code then - par.init_internal_left_box = getfield(current,"box_left") - par.init_internal_left_box_width = getfield(current,"box_left_width") - par.internal_pen_inter = getfield(current,"pen_inter") - par.internal_pen_broken = getfield(current,"pen_broken") - par.internal_left_box = par.init_internal_left_box - par.internal_left_box_width = par.init_internal_left_box_width - par.internal_right_box = getfield(current,"box_right") - par.internal_right_box_width = getfield(current,"box_right_width") + par.font_in_short_display = 0 + + if current then + local id = getid(current) + if id == localpar_code then + par.init_internal_left_box = getfield(current,"box_left") + par.init_internal_left_box_width = getfield(current,"box_left_width") + par.internal_pen_inter = getfield(current,"pen_inter") + par.internal_pen_broken = getfield(current,"pen_broken") + par.internal_left_box = par.init_internal_left_box + par.internal_left_box_width = par.init_internal_left_box_width + par.internal_right_box = getfield(current,"box_right") + par.internal_right_box_width = getfield(current,"box_right_width") + end end - end - -- all passes are combined in this loop so maybe we should split this into - -- three function calls; we then also need to do the wrap_up elsewhere + -- all passes are combined in this loop so maybe we should split this into + -- three function calls; we then also need to do the wrap_up elsewhere - -- split into normal and expansion loop + -- split into normal and expansion loop - -- use an active local + -- use an active local - local fontexp, lastfont -- we can pass fontexp to calculate width if needed + local fontexp, lastfont -- we can pass fontexp to calculate width if needed - -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active - -- test is fast enough (and try_break now returns the updated values); the kern helper has been - -- inlined as it did a double check on id so in fact we had hardly any code to share + -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active + -- test is fast enough (and try_break now returns the updated values); the kern helper has been + -- inlined as it did a double check on id so in fact we had hardly any code to share - local p_active = par.active - local n_active = p_active and p_active.next - local second_pass = par.second_pass + local p_active = par.active + local n_active = p_active and p_active.next + local second_pass = par.second_pass - trialcount = 0 + trialcount = 0 - while current and p_active ~= n_active do - local char, id = isglyph(current) - if char then - local wd, ht, dp = getwhd(current) - if is_rotated[par.line_break_dir] then - active_width.size = active_width.size + ht + dp - else - active_width.size = active_width.size + wd - end - if checked_expansion then - local currentfont = getfont(current) - local data = checked_expansion[currentfont] - if data then - if currentfont ~= lastfont then - fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer - lastfont = currentfont - end - if fontexps then - local expansion = fontexps[char] - if expansion then - active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch - active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink + while current and p_active ~= n_active do + local char, id = isglyph(current) + if char then + local wd, ht, dp = getwhd(current) + if is_rotated(par.line_break_dir) then + active_width.size = active_width.size + ht + dp + else + active_width.size = active_width.size + wd + end + if checked_expansion then + local font = id -- == font + local data = checked_expansion[font] + if data then + if font ~= lastfont then + fontexps = checked_expansion[font] -- a bit redundant for the par line packer + lastfont = currentfont + end + if fontexps then + local expansion = fontexps[char] + if expansion then + active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch + active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink + end end end end - end - elseif id == hlist_code or id == vlist_code then - local wd, ht, dp = getwhd(current) - if is_parallel[getdir(current)][par.line_break_dir] then - active_width.size = active_width.size + wd - else - active_width.size = active_width.size + ht + dp - end - elseif id == glue_code then --- if par.auto_breaking then - if auto_breaking then - local prev_p = getprev(current) - if prev_p and prev_p ~= temp_head then - local id = getid(prev_p) - -- we need to check this with the latest patches to the tex kernel - if (id == glyph_code) or (id < math_code) then - p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) - elseif id == kern_code then - local s = getsubtype(prev_p) - if s ~= userkern_code and s ~= italickern_code then + elseif id == hlist_code or id == vlist_code then + local wd, ht, dp = getwhd(current) + if textdir_parallel(getdirection(current),par.line_break_dir) then + active_width.size = active_width.size + wd + else + active_width.size = active_width.size + ht + dp + end + elseif id == glue_code then + -- if par.auto_breaking then + if auto_breaking then + local prev_p = getprev(current) + if prev_p and prev_p ~= temp_head then + local id = getid(prev_p) + -- we need to check this with the latest patches to the tex kernel + if (id == glyph_code) or (id < math_code) then p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) + elseif id == kern_code then + local s = getsubtype(prev_p) + if s ~= userkern_code and s ~= italickern_code then + p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) + end end end end - end - check_shrinkage(par,current) - local width, stretch, shrink, stretch_order = getglue(current) - local order = stretch_orders[stretch_order] - active_width.size = active_width.size + width - active_width[order] = active_width[order] + stretch - active_width.shrink = active_width.shrink + shrink - elseif id == disc_code then - local subtype = getsubtype(current) - if subtype ~= second_disc_code then - local line_break_dir = par.line_break_dir - if second_pass or subtype <= automatic_disc_code then - local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty - -- 0.81 : - -- local actual_pen = getpenalty(current) - -- - local pre, post, replace = getdisc(current) - if not pre then -- trivial pre-break - disc_width.size = 0 - if checked_expansion then - disc_width.adjust_stretch = 0 - disc_width.adjust_shrink = 0 - end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) - else - local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) - disc_width.size = size - active_width.size = active_width.size + size - if checked_expansion then - disc_width.adjust_stretch = adjust_stretch - disc_width.adjust_shrink = adjust_shrink - active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch - active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink + check_shrinkage(par,current) + local width, stretch, shrink, stretch_order = getglue(current) + local order = fillcodes[stretch_order] + active_width.size = active_width.size + width + active_width[order] = active_width[order] + stretch + active_width.shrink = active_width.shrink + shrink + elseif id == disc_code then + local subtype = getsubtype(current) + if subtype ~= seconddisc_code then + local line_break_dir = par.line_break_dir + if second_pass or subtype <= automaticdisc_code then + local actual_pen = subtype == automaticdisc_code and par.ex_hyphen_penalty or par.hyphen_penalty + -- 0.81 : + -- local actual_pen = getpenalty(current) + -- + local pre, post, replace = getdisc(current) + if not pre then -- trivial pre-break + disc_width.size = 0 + if checked_expansion then + disc_width.adjust_stretch = 0 + disc_width.adjust_shrink = 0 + end + p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) else - -- disc_width.adjust_stretch = 0 - -- disc_width.adjust_shrink = 0 - end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) - if subtype == first_disc_code then - local cur_p_next = getnext(current) - if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= second_disc_code then - report_parbuilders("unsupported disc at location %a",1) + local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) + disc_width.size = size + active_width.size = active_width.size + size + if checked_expansion then + disc_width.adjust_stretch = adjust_stretch + disc_width.adjust_shrink = adjust_shrink + active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch + active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink else - local pre = getfield(cur_p_next,"pre") - if pre then - local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) - disc_width.size = disc_width.size + size - if checked_expansion then - disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch - disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink - end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion) - -- - -- I will look into this some day ... comment in linebreak.w says that this fails, - -- maybe this is what Taco means with his comment in the luatex manual. - -- - -- do_one_seven_eight(sub_disc_width_from_active_width); - -- do_one_seven_eight(reset_disc_width); - -- s = vlink_no_break(vlink(current)); - -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width); - -- ext_try_break(...,first_p,vlink(current)); - -- + -- disc_width.adjust_stretch = 0 + -- disc_width.adjust_shrink = 0 + end + p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) + if subtype == firstdisc_code then + local cur_p_next = getnext(current) + if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= seconddisc_code then + report_parbuilders("unsupported disc at location %a",1) else - report_parbuilders("unsupported disc at location %a",2) + local pre = getfield(cur_p_next,"pre") + if pre then + local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) + disc_width.size = disc_width.size + size + if checked_expansion then + disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch + disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink + end + p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion) + -- + -- I will look into this some day ... comment in linebreak.w says that this fails, + -- maybe this is what Taco means with his comment in the luatex manual. + -- + -- do_one_seven_eight(sub_disc_width_from_active_width); + -- do_one_seven_eight(reset_disc_width); + -- s = vlink_no_break(vlink(current)); + -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width); + -- ext_try_break(...,first_p,vlink(current)); + -- + else + report_parbuilders("unsupported disc at location %a",2) + end end end + -- beware, we cannot restore to a saved value as the try_break adapts active_width + active_width.size = active_width.size - disc_width.size + if checked_expansion then + active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch + active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink + end end - -- beware, we cannot restore to a saved value as the try_break adapts active_width - active_width.size = active_width.size - disc_width.size + end + if replace then + local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) + active_width.size = active_width.size + size if checked_expansion then - active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch - active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink + active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch + active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink end end end - if replace then - local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) - active_width.size = active_width.size + size - if checked_expansion then - active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch - active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink + elseif id == kern_code then + local s = getsubtype(current) + if s == userkern_code or s == italickern_code then + local v = getnext(current) + -- if par.auto_breaking and getid(v) == glue_code then + if auto_breaking and getid(v) == glue_code then + p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) + end + local active_width = par.active_width + active_width.size = active_width.size + getkern(current) + else + local kern = getkern(current) + if kern ~= 0 then + active_width.size = active_width.size + kern + if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then + local stretch, shrink = kern_stretch_shrink(current,kern) + if expand_kerns == "stretch" then + active_width.adjust_stretch = active_width.adjust_stretch + stretch + elseif expand_kerns == "shrink" then + active_width.adjust_shrink = active_width.adjust_shrink + shrink + else + active_width.adjust_stretch = active_width.adjust_stretch + stretch + active_width.adjust_shrink = active_width.adjust_shrink + shrink + end + end end end - end - elseif id == kern_code then - local s = getsubtype(current) - if s == userkern_code or s == italickern_code then + elseif id == math_code then + -- par.auto_breaking = getsubtype(current) == endmath_code + auto_breaking = getsubtype(current) == endmath_code local v = getnext(current) - -- if par.auto_breaking and getid(v) == glue_code then + -- if par.auto_breaking and getid(v) == glue_code then if auto_breaking and getid(v) == glue_code then p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) end local active_width = par.active_width - active_width.size = active_width.size + getkern(current) - else - local kern = getkern(current) - if kern ~= 0 then - active_width.size = active_width.size + kern - if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then - local stretch, shrink = kern_stretch_shrink(current,kern) - if expand_kerns == "stretch" then - active_width.adjust_stretch = active_width.adjust_stretch + stretch - elseif expand_kerns == "shrink" then - active_width.adjust_shrink = active_width.adjust_shrink + shrink - else - active_width.adjust_stretch = active_width.adjust_stretch + stretch - active_width.adjust_shrink = active_width.adjust_shrink + shrink - end - end + active_width.size = active_width.size + getkern(current) -- surround + -- new in luatex + + getwidth(current) + elseif id == rule_code then + active_width.size = active_width.size + getwidth(current) + elseif id == penalty_code then + p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion) + elseif id == dir_code then + par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir + elseif id == localpar_code then + par.internal_pen_inter = getfield(current,"pen_inter") + par.internal_pen_broken = getfield(current,"pen_broken") + par.internal_left_box = getfield(current,"box_left") + par.internal_left_box_width = getfield(current,"box_left_width") + par.internal_right_box = getfield(current,"box_right") + par.internal_right_box_width = getfield(current,"box_right_width") + elseif trace_unsupported then + if id == mark_code or id == ins_code or id == adjust_code then + -- skip + else + report_parbuilders("node of type %a found in paragraph",type(id)) end end - elseif id == math_code then --- par.auto_breaking = getsubtype(current) == endmath_code - auto_breaking = getsubtype(current) == endmath_code - local v = getnext(current) --- if par.auto_breaking and getid(v) == glue_code then - if auto_breaking and getid(v) == glue_code then - p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) - end - local active_width = par.active_width - active_width.size = active_width.size + getkern(current) -- surround - -- new in luatex - + getwidth(current) - elseif id == rule_code then - active_width.size = active_width.size + getwidth(current) - elseif id == penalty_code then - p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion) - elseif id == dir_code then - par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir - elseif id == localpar_code then - par.internal_pen_inter = getfield(current,"pen_inter") - par.internal_pen_broken = getfield(current,"pen_broken") - par.internal_left_box = getfield(current,"box_left") - par.internal_left_box_width = getfield(current,"box_left_width") - par.internal_right_box = getfield(current,"box_right") - par.internal_right_box_width = getfield(current,"box_right_width") - elseif trace_unsupported then - if id == mark_code or id == ins_code or id == adjust_code then - -- skip - else - report_parbuilders("node of type %a found in paragraph",type(id)) - end + current = getnext(current) end - current = getnext(current) - end - if not current then - local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion) - if n_active ~= p_active then - local r = n_active - par.fewest_demerits = awful_badness - repeat -- use local d - if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then - par.fewest_demerits = r.total_demerits - par.best_bet = r - end - r = r.next - until r == p_active - par.best_line = par.best_bet.line_number - local asked_looseness = par.looseness - if asked_looseness == 0 then - return tonode(wrap_up(par)) - end - local r = n_active - local actual_looseness = 0 - -- minimize assignments to par but happens seldom - repeat - if r.id ~= delta_code then - local line_diff = r.line_number - par.best_line - par.line_diff = line_diff - if (line_diff < actual_looseness and asked_looseness <= line_diff) or - (line_diff > actual_looseness and asked_looseness >= line_diff) then - par.best_bet = r - actual_looseness = line_diff + if not current then + local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion) + if n_active ~= p_active then + local r = n_active + par.fewest_demerits = awful_badness + repeat -- use local d + if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then par.fewest_demerits = r.total_demerits - elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then par.best_bet = r - par.fewest_demerits = r.total_demerits end + r = r.next + until r == p_active + par.best_line = par.best_bet.line_number + local asked_looseness = par.looseness + if asked_looseness == 0 then + return wrap_up(par) + end + local r = n_active + local actual_looseness = 0 + -- minimize assignments to par but happens seldom + repeat + if r.id ~= delta_code then + local line_diff = r.line_number - par.best_line + par.line_diff = line_diff + if (line_diff < actual_looseness and asked_looseness <= line_diff) or + (line_diff > actual_looseness and asked_looseness >= line_diff) then + par.best_bet = r + actual_looseness = line_diff + par.fewest_demerits = r.total_demerits + elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then + par.best_bet = r + par.fewest_demerits = r.total_demerits + end + end + r = r.next + until r == p_active + par.best_line = par.best_bet.line_number + if actual_looseness == asked_looseness or par.final_pass then + return wrap_up(par) end - r = r.next - until r == p_active - par.best_line = par.best_bet.line_number - if actual_looseness == asked_looseness or par.final_pass then - return tonode(wrap_up(par)) end end - end - reset_meta(par) -- clean up the memory by removing the break nodes - if not second_pass then - if tracing_paragraphs then - diagnostics.current_pass(par,"secondpass") - end - par.threshold = par.tolerance - par.second_pass = true - par.final_pass = par.emergency_stretch <= 0 - else - if tracing_paragraphs then - diagnostics.current_pass(par,"emergencypass") + reset_meta(par) -- clean up the memory by removing the break nodes + if not second_pass then + if tracing_paragraphs then + diagnostics.current_pass(par,"secondpass") + end + par.threshold = par.tolerance + par.second_pass = true + par.final_pass = par.emergency_stretch <= 0 + else + if tracing_paragraphs then + diagnostics.current_pass(par,"emergencypass") + end + par.background.stretch = par.background.stretch + par.emergency_stretch + par.final_pass = true end - par.background.stretch = par.background.stretch + par.emergency_stretch - par.final_pass = true end + return wrap_up(par) end - return tonode(wrap_up(par)) + end -- standard tex logging .. will be adapted .. @@ -2531,16 +2572,19 @@ do while a do local char, id = isglyph(a) if char then - local font = getfont(a) - if font ~= font_in_short_display then - write(target,tex.fontidentifier(font) .. ' ') - font_in_short_display = font + -- id == font + if id ~= font_in_short_display then + write(target,tex.fontidentifier(id) .. ' ') + font_in_short_display = id end - -- todo: instead of components the split tounicode string - if getsubtype(a) == ligature_code then - font_in_short_display = short_display(target,getcomponents(a),font_in_short_display) + local u = chardata[id][char] + local u = u.unicode or char + if type(u) == "table" then + for i=1,#u do + write(target,utfchar(u[i])) + end else - write(target,utfchar(char)) + write(target,utfchar(u)) end elseif id == disc_code then local pre, post, replace = getdisc(a) @@ -2713,55 +2757,6 @@ do local setnodecolor = nodes.tracers.colors.set - local function glyph_width_height_depth(curdir,pdir,p) - local wd, ht, dp = getwhd(p) - if is_rotated[curdir] then - if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half - else - local half = wd / 2 - return ht + dp, half, half - end - elseif is_rotated[pdir] then - if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half - else - return ht + dp, wd, 0 -- weird - end - else - if glyphdir_is_equal[curdir][pdir] then - return wd, ht, dp - elseif is_opposite[curdir][pdir] then - return wd, dp, ht - else -- can this happen? - return ht + dp, wd, 0 - end - end - end - - local function pack_width_height_depth(curdir,pdir,p) - local wd, ht, dp = getwhd(p) - if is_rotated[curdir] then - if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half - else -- can this happen? - local half = wd / 2 - return ht + dp, half, half - end - else - if pardir_is_equal[curdir][pdir] then - return wd, ht, dp - elseif is_opposite[curdir][pdir] then - return wd, dp, ht - else -- weird dimensions, can this happen? - return ht + dp, wd, 0 - end - end - end - -- local function xpack(head,width,method,direction,analysis) -- -- -- inspect(analysis) @@ -2776,7 +2771,7 @@ do -- local hlist = new_hlist() -- -- setlist(hlist,head) - -- setdir(hlist,direction or tex.textdir) + -- setdirection(hlist,direction or tex.textdirection) -- setwhd(hlist,width,height,depth) -- -- if delta == 0 then @@ -2889,7 +2884,7 @@ do local hlist = new_hlist() - setdir(hlist,direction) + setdirection(hlist,direction) if head == nil then setwidth(hlist,width) @@ -2942,10 +2937,10 @@ do local char, id = isglyph(current) if char then if cal_expand_ratio then - local currentfont = getfont(current) - if currentfont ~= lastfont then - fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer - lastfont = currentfont + local font = id -- == font + if font ~= lastfont then + fontexps = checked_expansion[font] -- a bit redundant for the par line packer + lastfont = font end if fontexps then local expansion = fontexps[char] @@ -2958,7 +2953,7 @@ do end end -- use inline - local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ? + local wd, ht, dp = getwhd(current) natural = natural + wd if ht > height then height = ht @@ -2984,7 +2979,7 @@ do end elseif id == disc_code then local subtype = getsubtype(current) - if subtype ~= second_disc_code then + if subtype ~= seconddisc_code then -- todo : local stretch, shrink = char_stretch_shrink(s) local replace = getfield(current,"replace") if replace then @@ -3008,7 +3003,7 @@ do end elseif id == hlist_code or id == vlist_code then local sh = getshift(current) - local wd, ht, dp = pack_width_height_depth(hpack_dir,getdir(current) or hpack_dir,current) -- added: or pack_dir + local wd, ht, dp = getwhd(current) local hs, ds = ht - sh, dp + sh natural = natural + wd if hs > height then @@ -3114,14 +3109,13 @@ do local fontexps, lastfont for i=1,expansion_index do - local g = expansion_stack[i] - local e = 0 - local char = isglyph(g) + local g = expansion_stack[i] + local e = 0 + local char, font = isglyph(g) if char then - local currentfont = getfont(g) - if currentfont ~= lastfont then - fontexps = expansions[currentfont] - lastfont = currentfont + if font ~= lastfont then + fontexps = expansions[font] + lastfont = font end local data = fontexps[char] if trace_expansion then @@ -3133,7 +3127,7 @@ do local stretch, shrink = kern_stretch_shrink(g,kern) e = font_expand_ratio * stretch / 1000 end - setfield(g,"expansion_factor",e) + setexpansion(g,e) end end local tso = total_stretch[order] @@ -3171,14 +3165,13 @@ do local fontexps, lastfont for i=1,expansion_index do - local g = expansion_stack[i] - local e = 0 - local char = isglyph(g) + local g = expansion_stack[i] + local e = 0 + local char, font = isglyph(g) if char then - local currentfont = getfont(g) - if currentfont ~= lastfont then - fontexps = expansions[currentfont] - lastfont = currentfont + if font ~= lastfont then + fontexps = expansions[font] + lastfont = font end local data = fontexps[char] if trace_expansion then @@ -3190,7 +3183,7 @@ do local stretch, shrink = kern_stretch_shrink(g,kern) e = font_expand_ratio * shrink / 1000 end - setfield(g,"expansion_factor",e) + setexpansion(g,e) end end local tso = total_shrink[order] @@ -3214,7 +3207,7 @@ do local overfullrule = tex.overfullrule if fuzz > hfuzz and overfullrule > 0 then -- weird, is always called and no rules shows up - setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdir(hlist))) -- todo: find_tail + setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdirection(hlist))) -- todo: find_tail end diagnostics.overfull_hbox(hlist,line,-delta) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-met.lua b/Master/texmf-dist/tex/context/base/mkiv/node-met.lua index 12a9256bc66..f5db4babdcd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-met.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-met.lua @@ -68,65 +68,70 @@ end nodes = nodes or { } local nodes = nodes -local nodecodes = nodes.nodecodes - -nodes.tostring = node.tostring or tostring -nodes.copy = node.copy -nodes.copy_node = node.copy -nodes.copy_list = node.copy_list -nodes.delete = node.delete -nodes.dimensions = node.dimensions -nodes.rangedimensions = node.rangedimensions -nodes.end_of_math = node.end_of_math -nodes.flush = node.flush_node -nodes.flush_node = node.flush_node -nodes.flush_list = node.flush_list -nodes.free = node.free -nodes.insert_after = node.insert_after -nodes.insert_before = node.insert_before -nodes.hpack = node.hpack -nodes.new = node.new -nodes.tail = node.tail -nodes.traverse = node.traverse -nodes.traverse_id = node.traverse_id -nodes.traverse_char = node.traverse_char -nodes.slide = node.slide -nodes.vpack = node.vpack -nodes.fields = node.fields -nodes.is_node = node.is_node -nodes.setglue = node.setglue - -nodes.first_glyph = node.first_glyph -nodes.has_glyph = node.has_glyph or node.first_glyph - -nodes.current_attr = node.current_attr -nodes.has_field = node.has_field -nodes.last_node = node.last_node -nodes.usedlist = node.usedlist -nodes.protrusion_skippable = node.protrusion_skippable -nodes.check_discretionaries = node.check_discretionaries -nodes.write = node.write - -nodes.count = node.count -nodes.length = node.length - -nodes.has_attribute = node.has_attribute -nodes.set_attribute = node.set_attribute -nodes.find_attribute = node.find_attribute -nodes.unset_attribute = node.unset_attribute - -nodes.protect_glyph = node.protect_glyph -nodes.protect_glyphs = node.protect_glyphs -nodes.unprotect_glyph = node.unprotect_glyph -nodes.unprotect_glyphs = node.unprotect_glyphs -nodes.kerning = node.kerning -nodes.ligaturing = node.ligaturing -nodes.mlist_to_hlist = node.mlist_to_hlist - -nodes.effective_glue = node.effective_glue -nodes.getglue = node.getglue -nodes.setglue = node.setglue -nodes.is_zero_glue = node.is_zero_glue +local nodecodes = nodes.nodecodes + +nodes.tostring = node.tostring or tostring +nodes.copy = node.copy +nodes.copy_node = node.copy +nodes.copy_list = node.copy_list +nodes.delete = node.delete +nodes.dimensions = node.dimensions +nodes.rangedimensions = node.rangedimensions +nodes.end_of_math = node.end_of_math +nodes.flush = node.flush_node +nodes.flush_node = node.flush_node +nodes.flush_list = node.flush_list +nodes.free = node.free +nodes.insert_after = node.insert_after +nodes.insert_before = node.insert_before +nodes.hpack = node.hpack +nodes.new = node.new +nodes.tail = node.tail +nodes.traverse = node.traverse +nodes.traverse_id = node.traverse_id +nodes.traverse_char = node.traverse_char +nodes.traverse_glyph = node.traverse_glyph +nodes.traverse_list = node.traverse_list +nodes.slide = node.slide +nodes.vpack = node.vpack +nodes.fields = node.fields +nodes.is_node = node.is_node +nodes.setglue = node.setglue +nodes.uses_font = node.uses_font + +nodes.first_glyph = node.first_glyph +nodes.has_glyph = node.has_glyph or node.first_glyph + +nodes.current_attr = node.current_attr +nodes.has_field = node.has_field +nodes.last_node = node.last_node +nodes.usedlist = node.usedlist +nodes.protrusion_skippable = node.protrusion_skippable +nodes.check_discretionaries = node.check_discretionaries +nodes.write = node.write +nodes.flatten_discretionaries = node.flatten_discretionaries + +nodes.count = node.count +nodes.length = node.length + +nodes.has_attribute = node.has_attribute +nodes.set_attribute = node.set_attribute +nodes.find_attribute = node.find_attribute +nodes.unset_attribute = node.unset_attribute + +nodes.protect_glyph = node.protect_glyph +nodes.protect_glyphs = node.protect_glyphs +nodes.unprotect_glyph = node.unprotect_glyph +nodes.unprotect_glyphs = node.unprotect_glyphs +nodes.kerning = node.kerning +nodes.ligaturing = node.ligaturing +nodes.hyphenating = node.hyphenating +nodes.mlist_to_hlist = node.mlist_to_hlist + +nodes.effective_glue = node.effective_glue +nodes.getglue = node.getglue +nodes.setglue = node.setglue +nodes.is_zero_glue = node.is_zero_glue nodes.tonode = function(n) return n end nodes.tonut = function(n) return n end @@ -163,7 +168,7 @@ local n_setlink = node.setlink or -- always -- not that fast but not used often anyway local h = nil for i=1,select("#",...) do - local n = (select(i,...)) + local n = select(i,...) if not n then -- go on elseif h then @@ -621,7 +626,7 @@ local messyhack = table.tohash { -- temporary solution nodecodes.action, } -table.setmetatableindex(keys,function(t,k) +setmetatableindex(keys,function(t,k) local v = (k == "attributelist" or k == nodecodes.attributelist) and { } or getfields(k) if messyhack[k] then for i=1,#v do @@ -638,7 +643,7 @@ table.setmetatableindex(keys,function(t,k) return v end) -table.setmetatableindex(whatsitkeys,function(t,k) +setmetatableindex(whatsitkeys,function(t,k) local v = getfields(whatsit_code,k) if v[ 0] then v[#v+1] = "next" v[ 0] = nil end if v[-1] then v[#v+1] = "prev" v[-1] = nil end @@ -659,46 +664,3 @@ end nodes.keys = keys -- [id][subtype] nodes.fields = nodefields -- (n) - --- for the moment (pre 6380) - -if not nodes.unprotect_glyph then - - local protect_glyph = nodes.protect_glyph - local protect_glyphs = nodes.protect_glyphs - local unprotect_glyph = nodes.unprotect_glyph - local unprotect_glyphs = nodes.unprotect_glyphs - - local getnext = nodes.getnext - local setnext = nodes.setnext - - function nodes.protectglyphs(first,last) - if first == last then - return protect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = protect_glyphs(first) - setnext(last,nxt) - return f, b - else - return protect_glyphs(first) - end - end - - function nodes.unprotectglyphs(first,last) - if first == last then - return unprotect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = unprotect_glyphs(first) - setnext(last,nxt) - return f, b - else - return unprotect_glyphs(first) - end - end - -end - diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua b/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua index b3820a7d86c..32b09a1869c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-mig.lua @@ -89,12 +89,11 @@ local function locate(head,first,last,ni,nm) end function nodes.handlers.migrate(head,where) - local done = false if head then if trace_migrations then report_nodes("migration sweep %a",where) end - local current = tonut(head) + local current = head while current do local id = getid(current) -- inserts_too is a temp hack, we should only do them when it concerns @@ -124,13 +123,12 @@ function nodes.handlers.migrate(head,where) setlink(last,n) end setlink(current,first) - done = true current = last end end current = getnext(next) end - return head, done + return head end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua b/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua index 3e9a08b4804..6a38cca67a0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-nut.lua @@ -96,6 +96,7 @@ local fastcopy = table.fastcopy local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph local nuts = nodes.nuts or { } nodes.nuts = nuts @@ -126,11 +127,11 @@ nodes.tonut = tonut -- function nuts.reportattr() -- inspect(hash) -- end --- + -- local function track(name) -- local n = 0 --- local f = nuts[name] --- function nuts[name](...) +-- local f = direct[name] +-- direct[name] = function(...) -- n = n + 1 -- if n % 1000 == 0 then -- print(name,n) @@ -138,112 +139,81 @@ nodes.tonut = tonut -- return f(...) -- end -- end --- -- track("getfield") -- helpers -if not direct.getfam then -- LUATEXVERSION < 1.070 - - local getfield = direct.getfield - local setfield = direct.setfield - - direct.getfam = function(n) return getfield(n,"small_fam") end - direct.setfam = function(n,f) setfield(n,"small_fam",f) end - -end - -if not direct.getdirection then - - local getdir = direct.getdir - local setdir = direct.setdir - - direct.getdirection = function(n) - local d = getdir(n) - if d == "TLT" then return 0 end - if d == "+TLT" then return 0, false end - if d == "-TLT" then return 0, true end - if d == "TRT" then return 1 end - if d == "+TRT" then return 1, false end - if d == "-TRT" then return 1, true end - if d == "LTL" then return 2 end - if d == "+LTL" then return 2, false end - if d == "-LTL" then return 2, true end - if d == "RTT" then return 3 end - if d == "+RTT" then return 3, false end - if d == "-RTT" then return 3, true end - end - - direct.setdirection = function(n,d,c) - if d == 0 then if c == true then setdir(n,"-TLT") elseif c == false then setdir(n,"+TLT") else setdir(n,"TLT") end - elseif d == 1 then if c == true then setdir(n,"-TRT") elseif c == false then setdir(n,"+TRT") else setdir(n,"TRT") end - elseif d == 2 then if c == true then setdir(n,"-LTL") elseif c == false then setdir(n,"+LTL") else setdir(n,"LTL") end - elseif d == 3 then if c == true then setdir(n,"-RTT") elseif c == false then setdir(n,"+RTT") else setdir(n,"RTT") end - else if c == true then setdir(n,"-TLT") elseif c == false then setdir(n,"+TLT") else setdir(n,"TLT") end end - end - -end - -local nuts = nodes.nuts - -nuts.tostring = direct.tostring -nuts.copy = direct.copy -nuts.copy_node = direct.copy -nuts.copy_list = direct.copy_list -nuts.delete = direct.delete -nuts.dimensions = direct.dimensions -nuts.rangedimensions = direct.rangedimensions -nuts.end_of_math = direct.end_of_math -nuts.flush = direct.flush_node -nuts.flush_node = direct.flush_node -nuts.flush_list = direct.flush_list -nuts.free = direct.free -nuts.insert_after = direct.insert_after -nuts.insert_before = direct.insert_before -nuts.hpack = direct.hpack -nuts.new = direct.new -nuts.tail = direct.tail -nuts.traverse = direct.traverse -nuts.traverse_id = direct.traverse_id -nuts.traverse_char = direct.traverse_char -nuts.slide = direct.slide -nuts.writable_spec = direct.writable_spec -nuts.vpack = direct.vpack -nuts.is_node = direct.is_node -nuts.is_direct = direct.is_direct -nuts.is_nut = direct.is_direct -nuts.first_glyph = direct.first_glyph -nuts.has_glyph = direct.has_glyph or direct.first_glyph -nuts.count = direct.count -nuts.length = direct.length -nuts.find_attribute = direct.find_attribute -nuts.unset_attribute = direct.unset_attribute - -nuts.current_attr = direct.current_attr -nuts.has_field = direct.has_field -nuts.last_node = direct.last_node -nuts.usedlist = direct.usedlist -nuts.protrusion_skippable = direct.protrusion_skippable -nuts.check_discretionaries = direct.check_discretionaries -nuts.write = direct.write - -nuts.has_attribute = direct.has_attribute -nuts.set_attribute = direct.set_attribute -nuts.unset_attribute = direct.unset_attribute - -nuts.protect_glyph = direct.protect_glyph -nuts.protect_glyphs = direct.protect_glyphs -nuts.unprotect_glyph = direct.unprotect_glyph -nuts.unprotect_glyphs = direct.unprotect_glyphs -nuts.ligaturing = direct.ligaturing -nuts.kerning = direct.kerning - -if not direct.mlist_to_hlist then -- needed +local nuts = nodes.nuts + +nuts.check_discretionaries = direct.check_discretionaries +nuts.copy = direct.copy +nuts.copy_list = direct.copy_list +nuts.copy_node = direct.copy +nuts.count = direct.count +nuts.current_attr = direct.current_attr +nuts.delete = direct.delete +nuts.dimensions = direct.dimensions +nuts.end_of_math = direct.end_of_math +nuts.find_attribute = direct.find_attribute +nuts.first_glyph = direct.first_glyph +nuts.flatten_discretionaries = direct.flatten_discretionaries +nuts.flush = direct.flush_node +nuts.flush_list = direct.flush_list +nuts.flush_node = direct.flush_node +nuts.free = direct.free +nuts.get_synctex_fields = direct.get_synctex_fields +nuts.has_attribute = direct.has_attribute +nuts.has_field = direct.has_field +nuts.has_glyph = direct.has_glyph or direct.first_glyph +nuts.hpack = direct.hpack +nuts.insert_after = direct.insert_after +nuts.insert_before = direct.insert_before +nuts.is_direct = direct.is_direct +nuts.is_node = direct.is_node +nuts.is_nut = direct.is_direct +nuts.kerning = direct.kerning +nuts.hyphenating = direct.hyphenating +nuts.last_node = direct.last_node +nuts.length = direct.length +nuts.ligaturing = direct.ligaturing +nuts.new = direct.new +nuts.protect_glyph = direct.protect_glyph +nuts.protect_glyphs = direct.protect_glyphs +nuts.flush_components = direct.flush_components +nuts.protrusion_skippable = direct.protrusion_skippable +nuts.rangedimensions = direct.rangedimensions +nuts.set_attribute = direct.set_attribute +nuts.set_synctex_fields = direct.set_synctex_fields +nuts.slide = direct.slide +nuts.tail = direct.tail +nuts.tostring = direct.tostring +nuts.traverse = direct.traverse +nuts.traverse_char = direct.traverse_char +nuts.traverse_glyph = direct.traverse_glyph +nuts.traverse_id = direct.traverse_id +nuts.traverse_list = direct.traverse_list +nuts.unprotect_glyph = direct.unprotect_glyph +nuts.unprotect_glyphs = direct.unprotect_glyphs +nuts.unset_attribute = direct.unset_attribute +nuts.unset_attribute = direct.unset_attribute +nuts.usedlist = direct.usedlist +nuts.uses_font = direct.uses_font +nuts.vpack = direct.vpack +nuts.writable_spec = direct.writable_spec +nuts.write = direct.write +nuts.mlist_to_hlist = direct.mlist_to_hlist + +if not nuts.mlist_to_hlist then local n_mlist_to_hlist = node.mlist_to_hlist - function nuts.mlist_to_hlist(head) - return tonode(n_mlist_to_hlist(tonut(head))) + function nuts.mlist_to_hlist(head,...) + if head then + local head = n_mlist_to_hlist(tonode(head),...) + if head then + return tonut(head) + end + end end end @@ -276,6 +246,14 @@ nuts.setdisc = direct.setdisc nuts.getdiscretionary = direct.getdisc nuts.setdiscretionary = direct.setdisc +nuts.getdata = direct.getdata +nuts.setdata = direct.setdata +nuts.getvalue = direct.getdata +nuts.setvalue = direct.setdata + +nuts.getexpansion = direct.getexpansion +nuts.setexpansion = direct.setexpansion + nuts.getwhd = direct.getwhd nuts.setwhd = direct.setwhd nuts.getwidth = direct.getwidth @@ -286,6 +264,8 @@ nuts.getdepth = direct.getdepth nuts.setdepth = direct.setdepth nuts.getshift = direct.getshift nuts.setshift = direct.setshift +nuts.getorientation = direct.getorientation or function() end +nuts.setorientation = direct.setorientation or function() end nuts.getnucleus = direct.getnucleus nuts.setnucleus = direct.setnucleus @@ -726,14 +706,10 @@ nodes.properties = { data = propertydata, } -------.set_properties_mode(true,false) -- shallow copy ... problem: in fonts we then affect the originals too -direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-otj.lua (unless we use an intermediate table) - --- todo: --- --- function direct.set_properties_mode() --- -- we really need the set modes --- end +if direct.set_properties_mode then + direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-otj.lua (unless we use an intermediate table) + function direct.set_properties_mode() end +end -- experimental code with respect to copying attributes has been removed -- as it doesn't pay of (most attributes are only accessed once anyway) @@ -770,8 +746,22 @@ nuts.theprop = function(n) return p end -nodes.setprop = nodes.setproperty -nodes.getprop = nodes.getproperty +nuts.isdone = function(n,k) + local p = propertydata[n] + if not p then + propertydata[n] = { [k] = true } + return false + end + local v = p[k] + if v == nil then + propertydata[n] = { [k] = true } + return false + end + return v +end + +-- nodes.setprop = nodes.setproperty +-- nodes.getprop = nodes.getproperty function nuts.copy_properties(source,target,what) local newprops = propertydata[source] @@ -800,116 +790,3 @@ function nuts.copy_properties(source,target,what) end return newprops -- for checking end - --- here: - -nuts.get_synctex_fields = direct.get_synctex_fields -nuts.set_synctex_fields = direct.set_synctex_fields - --- for now - -nodes.uses_font = nodes.uses_font -nuts.uses_font = direct.uses_font - -if not nuts.uses_font then - - local glyph_code = nodecodes.glyph - local getdisc = nuts.getdisc - local getfont = nuts.getfont - local traverse_id = nuts.traverse_id - local tonut = nodes.tonut - - function nuts.uses_font(n,font) - local pre, post, replace = getdisc(n) - if pre then - -- traverse_char - for n in traverse_id(glyph_code,pre) do - if getfont(n) == font then - return true - end - end - end - if post then - for n in traverse_id(glyph_code,post) do - if getfont(n) == font then - return true - end - end - end - if replace then - for n in traverse_id(glyph_code,replace) do - if getfont(n) == font then - return true - end - end - end - return false - end - - function nodes.uses_font(n,font) - return nuts.uses_font(tonut(n),font) - end - -end - --- for the moment (pre 6380) - -if not nuts.unprotect_glyph then - - local protect_glyph = nuts.protect_glyph - local protect_glyphs = nuts.protect_glyphs - local unprotect_glyph = nuts.unprotect_glyph - local unprotect_glyphs = nuts.unprotect_glyphs - - local getnext = nuts.getnext - local setnext = nuts.setnext - - function nuts.protectglyphs(first,last) - if first == last then - return protect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = protect_glyphs(first) - setnext(last,nxt) - return f, b - else - return protect_glyphs(first) - end - end - - function nuts.unprotectglyphs(first,last) - if first == last then - return unprotect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = unprotect_glyphs(first) - setnext(last,nxt) - return f, b - else - return unprotect_glyphs(first) - end - end - -end - -if LUATEXFUNCTIONALITY < 6384 then -- LUATEXVERSION < 1.070 - - local getfield = nuts.getfield - local setfield = nuts.setfield - - function nuts.getboxglue(n,glue_set,glue_order,glue_sign) - return - getfield(n,"glue_set"), - getfield(n,"glue_order"), - getfield(n,"glue_sign") - end - - function nuts.setboxglue(n,glue_set,glue_order,glue_sign) - setfield(n,"glue_set", glue_set or 0) - setfield(n,"glue_order",glue_order or 0) - setfield(n,"glue_sign", glue_sign or 0) - end - -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-par.lua b/Master/texmf-dist/tex/context/base/mkiv/node-par.lua new file mode 100644 index 00000000000..8564c8764bd --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/node-par.lua @@ -0,0 +1,48 @@ +if not modules then modules = { } end modules ['node-par'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local sequencers = utilities.sequencers + +-- This are called a lot! + +local actions = nodes.tasks.actions("everypar") + +local function everypar(head) + starttiming(builders) + head = actions(head) + stoptiming(builders) + return head +end + +callbacks.register("insert_local_par",everypar,"after paragraph start") + +local actions = sequencers.new { + name = "newgraf", + arguments = "mode,indented", + returnvalues = "indented", + results = "indented", +} + +sequencers.appendgroup(actions,"before") -- user +sequencers.appendgroup(actions,"system") -- private +sequencers.appendgroup(actions,"after" ) -- user + +local function newgraf(mode,indented) + local runner = actions.runner + if runner then + starttiming(builders) + indent = runner(mode,indented) + stoptiming(builders) + end + return indented +end + +callbacks.register("new_graf",newgraf,"before paragraph start") diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua index 5ebfca87d14..485e742b64a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ppt.lua @@ -26,12 +26,14 @@ local getid = nuts.getid local getnext = nuts.getnext local getprev = nuts.getprev local getsubtype = nuts.getsubtype -local getfield = nuts.getfield local getlist = nuts.getlist local setlist = nuts.setlist +local getprop = nuts.getprop + local removenode = nuts.remove -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id + +local nextnode = nuts.traversers.node +local nextwhatsit = nuts.traversers.whatsit local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes @@ -39,18 +41,17 @@ local whatsitcodes = nodes.whatsitcodes local whatsit_code = nodecodes.whatsit local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local userdefined_code = whatsitcodes.userdefined + +local userdefinedwhatsit_code = whatsitcodes.userdefined local nodepool = nodes.pool -local new_usernumber = nodepool.usernumber +local new_usernode = nodepool.usernode local variables = interfaces.variables local v_before = variables.before local v_after = variables.after local v_here = variables.here -local cache = { } -local nofslots = 0 local property_id = nodepool.userids["property"] local properties = nodes.properties @@ -71,15 +72,8 @@ local function register(where,data,...) where = v_after end if data then - local data = { where, data, ... } nofslots = nofslots + 1 - if nofslots > 1 then - cache[nofslots] = data - else - -- report("restarting attacher") - cache = { data } -- also forces collection - end - return new_usernumber(property_id,nofslots) + return new_usernode(property_id,{ where, data, ... }) end end @@ -108,17 +102,9 @@ local f_delayed = formatters["return function(target,head,where,propdata,paren local f_immediate = formatters["return function(target,head,where,propdata) %s end"] local nofdelayed = 0 -- better is to keep track of it per page ... we can have deleted nodes with properties +local nofslots = 0 function actions.delayed(target,head,where,propdata,code,...) -- this one is used at the tex end --- local kind = type(code) --- if kind == "string" then --- code, err = load(f_delayed(code)) --- if code then --- code = code() --- end --- elseif kind ~= "function" then --- code = nil --- end if code then local delayed = propdata.delayed if delayed then @@ -131,15 +117,6 @@ function actions.delayed(target,head,where,propdata,code,...) -- this one is use end function actions.fdelayed(target,head,where,propdata,code,...) -- this one is used at the tex end --- local kind = type(code) --- if kind == "string" then --- code, err = load(f_delayed(code)) --- if code then --- code = code() --- end --- elseif kind ~= "function" then --- code = nil --- end if code then local delayed = propdata.delayed if delayed then @@ -170,81 +147,41 @@ function actions.immediate(target,head,where,propdata,code,...) -- this one is u end end --- another experiment (a table or function closure are equally efficient); a function --- is easier when we want to experiment with different (compatible) implementations - --- local nutpool = nuts.pool --- local nut_usernumber = nutpool.usernumber - --- function nodes.nuts.pool.deferredfunction(...) --- nofdelayed = nofdelayed + 1 --- local n = nut_usernumber(property_id,0) --- propertydata[n] = { deferred = { ... } } --- return n --- end - --- function nodes.nuts.pool.deferredfunction(f) --- nofdelayed = nofdelayed + 1 --- local n = nut_usernumber(property_id,0) --- propertydata[n] = { deferred = f } --- return n --- end - --- maybe actions will get parent too - local function delayed(head,parent) -- direct based - for target in traverse(head) do + for target, id in nextnode, head do local p = propertydata[target] if p then - -- local deferred = p.deferred -- kind of late lua (but too soon as we have no access to pdf.h/v) - -- if deferred then - -- -- if #deferred > 0 then - -- -- deferred[1](unpack(deferred,2)) - -- -- else - -- -- deferred[1]() - -- -- end - -- deferred() - -- p.deferred = false - -- if nofdelayed == 1 then - -- nofdelayed = 0 - -- return head - -- else - -- nofdelayed = nofdelayed - 1 - -- end - -- else - local delayed = p.delayed - if delayed then - for i=1,#delayed do - local d = delayed[i] - local code = d[2] - local kind = type(code) - if kind == "string" then - code, err = load(f_delayed(code)) - if code then - code = code() - end - end - local where = d[1] - if where then - local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent - if h and h ~= head then - head = h - end - else - code(unpack(d,3)) + local delayed = p.delayed + if delayed then + for i=1,#delayed do + local d = delayed[i] + local code = d[2] + local kind = type(code) + if kind == "string" then + code, err = load(f_delayed(code)) + if code then + code = code() end end - p.delayed = nil - if nofdelayed == 1 then - nofdelayed = 0 - return head + local where = d[1] + if where then + local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent + if h and h ~= head then + head = h + end else - nofdelayed = nofdelayed - 1 + code(unpack(d,3)) end end - -- end + p.delayed = nil + if nofdelayed == 1 then + nofdelayed = 0 + return head + else + nofdelayed = nofdelayed - 1 + end + end end - local id = getid(target) if id == hlist_code or id == vlist_code then local list = getlist(target) if list then @@ -268,14 +205,13 @@ function properties.delayed(head) -- if nofdelayed > 0 then -- if next(propertydata) then starttiming(properties) - head = delayed(tonut(head)) + head = delayed(head) stoptiming(properties) - return tonode(head), true -- done in shipout anyway -- else -- delayed = 0 - -- end + -- end end - return head, false + return head end -- more explicit ones too @@ -284,7 +220,7 @@ local anchored = { [v_before] = function(n) while n do n = getprev(n) - if getid(n) == whatsit_code and getsubtype(n) == user_code and getfield(n,"user_id") == property_id then + if getid(n) == whatsit_code and getsubtype(n) == user_code and getprop(n,"id") == property_id then -- continue else return n @@ -296,7 +232,7 @@ local anchored = { n = getnext(n) if getid(n) == whatsit_code then local subtype = getsubtype(n) - if (subtype == userdefined_code and getfield(n,"user_id") == property_id) then + if (subtype == userdefinedwhatsit_code and getprop(n,"id") == property_id) then -- continue else return n @@ -320,26 +256,22 @@ end) function properties.attach(head) if nofslots <= 0 then - return head, false + return head end - local done = false local last = nil - local head = tonut(head) starttiming(properties) - for source in traverse_id(whatsit_code,head) do - if getsubtype(source) == userdefined_code then + for source, subtype in nextwhatsit, head do + if subtype == userdefinedwhatsit_code then if last then removenode(head,last,true) last = nil end - if getfield(source,"user_id") == property_id then - local slot = getfield(source,"value") - local data = cache[slot] + if getprop(source,"id") == property_id then + local data = getprop(source,"data") if data then - cache[slot] = nil local where = data[1] local target = anchored[where](source) if target then @@ -393,7 +325,7 @@ function properties.attach(head) target,nodecodes[getid(target)],serialize(propertydata[target],false)) end end - if nofslots == 1 then + if nofslots == 1 then nofslots = 0 last = source break @@ -412,25 +344,22 @@ function properties.attach(head) stoptiming(properties) - return head, done + return head end -local tasks = nodes.tasks - -- maybe better hard coded in-place --- tasks.prependaction("processors","before","nodes.properties.attach") --- tasks.appendaction("shipouts","normalizers","nodes.properties.delayed") - statistics.register("properties processing time", function() return statistics.elapsedseconds(properties) end) -- only for development +-- local tasks = nodes.tasks +-- -- local function show(head,level,report) --- for target in traverse(head) do +-- for target in nextnode, head do -- local p = propertydata[target] -- if p then -- report("level %i, node %i, id %s, data %s", diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua b/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua index 4509bac18db..b6b1305886f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-pro.lua @@ -35,7 +35,7 @@ do local n = 0 local function reconstruct(head) -- we probably have a better one - local t, n, h = { }, 0, tonut(head) + local t, n, h = { }, 0, head while h do n = n + 1 local char, id = isglyph(h) @@ -49,7 +49,7 @@ do return concat(t) end - function processors.tracer(what,state,head,groupcode,before,after,show) + function processors.tracer(what,head,groupcode,before,after,show) if not groupcode then groupcode = "unknown" elseif groupcode == "" then @@ -57,16 +57,14 @@ do end n = n + 1 if show then - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s, stream: %s",what,n,state,groupcode,before,after,reconstruct(head)) + report_nodes("%s: location %a, group %a, # before %a, # after %s, stream: %s",what,n,groupcode,before,after,reconstruct(head)) else - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after) + report_nodes("%s: location %a, group %a, # before %a, # after %s",what,n,groupcode,before,after) end end end -local tracer = processors.tracer - processors.enabled = true -- this will become a proper state (like trackers) do @@ -74,154 +72,131 @@ do local has_glyph = nodes.has_glyph local count_nodes = nodes.countall - function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction + local texget = tex.get + + local tracer = processors.tracer + + local function pre_linebreak_filter(head,groupcode) local found = force_processors or has_glyph(head) if found then if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode) -- ,size,packtype,direction + head = actions(head,groupcode) local after = count_nodes(head,true) - if done then - tracer("pre_linebreak","changed",head,groupcode,before,after,true) - else - tracer("pre_linebreak","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("pre_linebreak",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode) -- ,size,packtype,direction - return done and head or true + head = actions(head,groupcode) end elseif trace_callbacks then local n = count_nodes(head,false) - tracer("pre_linebreak","no chars",head,groupcode,n,n) + tracer("pre_linebreak",head,groupcode,n,n) end - return true + return head end local function hpack_filter(head,groupcode,size,packtype,direction,attributes) local found = force_processors or has_glyph(head) if found then + -- + -- yes or no or maybe an option + -- + if not direction then + direction = texget("textdir") + end + -- if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode,size,packtype,direction,attributes) + head = actions(head,groupcode,size,packtype,direction,attributes) local after = count_nodes(head,true) - if done then - tracer("hpack","changed",head,groupcode,before,after,true) - else - tracer("hpack","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("hpack",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode,size,packtype,direction,attributes) - return done and head or true + head = actions(head,groupcode,size,packtype,direction,attributes) end elseif trace_callbacks then local n = count_nodes(head,false) - tracer("hpack","no chars",head,groupcode,n,n) + tracer("hpack",head,groupcode,n,n) end - return true + return head end - processors.hpack_filter = hpack_filter + processors.pre_linebreak_filter = pre_linebreak_filter + processors.hpack_filter = hpack_filter do - local setfield = nodes.setfield - local hpack = nodes.hpack + local hpack = nodes.hpack function nodes.fullhpack(head,...) - local ok = hpack_filter(head) - if not done or done == true then - ok = head - end - local hp, b = hpack(ok,...) - setfield(hp,"prev",nil) - setfield(hp,"next",nil) - return hp, b + return hpack((hpack_filter(head)),...) end end do - local setboth = nuts.setboth - local hpack = nuts.hpack + local hpack = nuts.hpack function nuts.fullhpack(head,...) - local ok = hpack_filter(tonode(head)) - if not done or done == true then - ok = head - else - ok = tonut(ok) - end - local hp, b = hpack(...) - setboth(hp) - return hp, b + return hpack(tonut(hpack_filter(tonode(head))),...) end end - callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)") - callbacks.register('hpack_filter' , processors.hpack_filter, "all kind of horizontal manipulations (before hbox creation)") + callbacks.register('pre_linebreak_filter', pre_linebreak_filter, "horizontal manipulations (before par break)") + callbacks.register('hpack_filter' , hpack_filter, "horizontal manipulations (before hbox creation)") end do + -- Beware, these are packaged boxes so no first_glyph test needed. Maybe some day I'll add a hash + -- with valid groupcodes. Watch out, much can pass twice, for instance vadjust passes two times, local actions = tasks.actions("finalizers") -- head, where local count_nodes = nodes.countall - -- beware, these are packaged boxes so no first_glyph test - -- maybe some day a hash with valid groupcodes - -- - -- beware, much can pass twice, for instance vadjust passes two times - -- - -- something weird here .. group mvl when making a vbox + local tracer = processors.tracer - function processors.post_linebreak_filter(head,groupcode) + local function post_linebreak_filter(head,groupcode) if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode) + head = actions(head,groupcode) local after = count_nodes(head,true) - if done then - tracer("post_linebreak","changed",head,groupcode,before,after,true) - else - tracer("post_linebreak","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("post_linebreak",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode) - return done and head or true + head = actions(head,groupcode) end + return head end - callbacks.register('post_linebreak_filter', processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)") + processors.post_linebreak_filter = post_linebreak_filter + + callbacks.register("post_linebreak_filter", post_linebreak_filter,"horizontal manipulations (after par break)") end do - local texnest = tex.nest + local texnest = tex.nest - local getlist = nodes.getlist - local setlist = nodes.setlist - local getsubtype = nodes.getsubtype + local getlist = nodes.getlist + local setlist = nodes.setlist + local getsubtype = nodes.getsubtype - local line_code = nodes.listcodes.line + local linelist_code = nodes.listcodes.line - local actions = tasks.actions("contributers") + local actions = tasks.actions("contributers") function processors.contribute_filter(groupcode) if groupcode == "box" then -- "pre_box" local whatever = texnest[texnest.ptr] if whatever then local line = whatever.tail - if line and getsubtype(line) == line_code then + if line and getsubtype(line) == linelist_code then local head = getlist(line) if head then - local okay, done = actions(head,groupcode,line) - if okay and okay ~= head then - setlist(line,okay) + local result = actions(head,groupcode,line) + if result and result ~= head then + setlist(line,result) end end end @@ -229,7 +204,7 @@ do end end - callbacks.register('contribute_filter', processors.contribute_filter,"things done with lines") + callbacks.register("contribute_filter", processors.contribute_filter,"things done with lines") end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua index 1ec77e83de3..e12bd95bdd6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua @@ -67,21 +67,25 @@ local getattr = nuts.getattr local setattr = nuts.setattr local getsubtype = nuts.getsubtype local getwhd = nuts.getwhd -local getdir = nuts.getdir +local getdirection = nuts.getdirection local setshift = nuts.setshift local getboxglue = nuts.getboxglue local hpack_list = nuts.hpack local vpack_list = nuts.vpack -local list_dimensions = nuts.dimensions -local list_rangedimensions = nuts.rangedimensions +local getdimensions = nuts.dimensions +local getrangedimensions = nuts.rangedimensions local traverse = nuts.traverse local find_node_tail = nuts.tail local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local listcodes = nodes.listcodes +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local glue_code = nodecodes.glue @@ -90,11 +94,11 @@ local rule_code = nodecodes.rule local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local leftskip_code = skipcodes.leftskip -local rightskip_code = skipcodes.rightskip -local parfillskip_code = skipcodes.parfillskip +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip +local parfillskip_code = gluecodes.parfillskip -local line_code = listcodes.line +----- linelist_code = listcodes.line local new_rule = nodepool.rule local new_kern = nodepool.kern @@ -113,9 +117,9 @@ local implement = interfaces.implement local function hlist_dimensions(start,stop,parent) local last = stop and getnext(stop) if parent then - return list_rangedimensions(parent,start,last) + return getrangedimensions(parent,start,last) else - return list_dimensions(start,last) + return getdimensions(start,last) end end @@ -250,11 +254,13 @@ local function dimensions(parent,start,stop) -- in principle we could move some end end --- is pardir important at all? - local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir) local width, height, depth, line = dimensions(parent,first,last) - if txtdir == "+TRT" or (txtdir == "===" and pardir == "TRT") then -- KH: textdir == "===" test added + if txtdir == righttoleft_code then + width = - width + elseif textdir == lefttoright_code then + -- go on + elseif pardir == righttoleft_code then width = - width end local result, resolved = make(width,height,depth,reference) @@ -264,7 +270,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t local l = getlist(line) if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","line", - reference,pardir or "---",txtdir or "---", + reference,pardir or "?",txtdir or "?", tosequence(l,nil,true),width,height,depth) end setlist(line,result) @@ -273,7 +279,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t elseif head == first then if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","head", - reference,pardir or "---",txtdir or "---", + reference,pardir or "?",txtdir or "?", tosequence(first,last,true),width,height,depth) end setlink(result,first) @@ -281,7 +287,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t else if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","middle", - reference,pardir or "---",txtdir or "---", + reference,pardir or "?",txtdir or "?", tosequence(first,last,true),width,height,depth) end if first == last and getid(parent) == vlist_code and getid(first) == hlist_code then @@ -306,7 +312,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) local correction = 0 local moveright = false local first = getlist(current) - if id == hlist_code then -- box_code line_code + if id == hlist_code then -- boxlist_code linelist_code -- can be either an explicit hbox or a line and there is no way -- to recognize this; anyway only if ht/dp (then inline) local sr = stack[reference] @@ -337,7 +343,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) correction = height + depth height, depth = depth, height -- ugly hack, needed because pdftex backend does something funny end - if pardir == "TRT" then + if pardir == righttoleft_code then width = - width end local result, resolved = make(width,height,depth,reference) @@ -345,7 +351,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) if result and resolved then if trace_areas then report_area("%s: %04i %s %s %s: w=%p, h=%p, d=%p, c=%S","box", - reference,pardir or "---",txtdir or "----","[]",width,height,depth,resolved) + reference,pardir or "?",txtdir or "?","[]",width,height,depth,resolved) end if not first then setlist(current,result) @@ -370,12 +376,6 @@ end local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main local first, last, firstdir, reference - if not pardir then - pardir = "===" - end - if not texdir then - txtdir = "===" - end local current = head while current do local id = getid(current) @@ -404,8 +404,8 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx end local list = getlist(current) if list then - local h, ok - h, ok, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) + local h + h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) if h ~= current then setlist(current,h) end @@ -416,9 +416,12 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? -- elseif id == dir_code then - txtdir = getdir(current) - elseif id == localpar_code then -- only test at begin - pardir = getdir(current) + local direction, pop = getdirection(current) + txtdir = not pop and direction -- we might need a stack + elseif id == localpar_code then + if getsubtype(current) == 0 then + pardir = getdirection(current) + end else local r = getattr(current,attribute) if not r then @@ -441,46 +444,183 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx if reference and (done[reference] or 0) == 0 then head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) end - return head, true, pardir, txtdir + return head, pardir, txtdir end --- local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular ! --- if not pardir then --- pardir = "===" --- end --- if not texdir then --- txtdir = "===" +-- -- not faster either: +-- +-- local findattr = node.direct.find_attribute +-- +-- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main +-- local first, last, firstdir, reference +-- local someatt = findattr(head,attribute) +-- if someatt then +-- local current = head +-- while current do +-- local id = getid(current) +-- if id == hlist_code or id == vlist_code then +-- local r = getattr(current,attribute) +-- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] +-- -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)] +-- -- if r and (not skip or r >) skip then -- maybe no > test +-- -- inject_list(id,current,r,make,stack,pardir,txtdir) +-- -- end +-- if r then +-- if not reference then +-- reference, first, last, firstdir = r, current, current, txtdir +-- elseif r == reference then +-- -- same link +-- last = current +-- elseif (done[reference] or 0) == 0 then +-- if not skip or r > skip then -- maybe no > test +-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- reference, first, last, firstdir = nil, nil, nil, nil +-- end +-- else +-- reference, first, last, firstdir = r, current, current, txtdir +-- end +-- done[r] = (done[r] or 0) + 1 +-- end +-- local list = getlist(current) +-- if list then +-- local h +-- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) +-- if h ~= current then +-- setlist(current,h) +-- end +-- end +-- if r then +-- done[r] = done[r] - 1 +-- end +-- elseif id == dir_code then +-- local direction, pop = getdirection(current) +-- txtdir = not pop and direction -- we might need a stack +-- elseif id == localpar_code then -- only test at begin +-- pardir = getdirection(current) +-- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? +-- -- +-- else +-- local r = getattr(current,attribute) +-- if not r then +-- -- just go on, can be kerns +-- elseif not reference then +-- reference, first, last, firstdir = r, current, current, txtdir +-- elseif r == reference then +-- last = current +-- elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code +-- if not skip or r > skip then -- maybe no > test +-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- reference, first, last, firstdir = nil, nil, nil, nil +-- end +-- else +-- reference, first, last, firstdir = r, current, current, txtdir +-- end +-- end +-- current = getnext(current) +-- end +-- if reference and (done[reference] or 0) == 0 then +-- head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- end +-- else +-- local current = head +-- while current do +-- local id = getid(current) +-- if id == hlist_code or id == vlist_code then +-- local list = getlist(current) +-- if list then +-- local h = inject_areas(list,attribute,make,stack,done,skip or 0,current,pardir,txtdir) +-- if h ~= current then +-- setlist(current,h) +-- end +-- end +-- elseif id == dir_code then +-- local direction, pop = getdirection(current) +-- txtdir = not pop and direction -- we might need a stack +-- elseif id == localpar_code then -- only test at begin +-- pardir = getdirection(current) +-- end +-- current = getnext(current) +-- end -- end +-- return head, pardir, txtdir +-- end + +-- -- maybe first check for glyphs and use a goto: +-- +-- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main +-- local first, last, firstdir, reference -- local current = head -- while current do -- local id = getid(current) --- if id == hlist_code or id == vlist_code then --- local r = getattr(current,attribute) --- if r and not done[r] then --- done[r] = true --- inject_list(id,current,r,make,stack,pardir,txtdir) +-- local r -- else scope message due to goto +-- if id == glyph_code then +-- goto rest +-- elseif id == hlist_code or id == vlist_code then +-- r = getattr(current,attribute) +-- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] +-- -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)] +-- -- if r and (not skip or r >) skip then -- maybe no > test +-- -- inject_list(id,current,r,make,stack,pardir,txtdir) +-- -- end +-- if r then +-- if not reference then +-- reference, first, last, firstdir = r, current, current, txtdir +-- elseif r == reference then +-- -- same link +-- last = current +-- elseif (done[reference] or 0) == 0 then +-- if not skip or r > skip then -- maybe no > test +-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- reference, first, last, firstdir = nil, nil, nil, nil +-- end +-- else +-- reference, first, last, firstdir = r, current, current, txtdir +-- end +-- done[r] = (done[r] or 0) + 1 -- end -- local list = getlist(current) -- if list then --- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir) +-- local h +-- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) -- if h ~= current then -- setlist(current,h) -- end -- end +-- if r then +-- done[r] = done[r] - 1 +-- end +-- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? +-- -- -- elseif id == dir_code then --- txtdir = getdir(current) --- elseif id == localpar_code then --- pardir = getdir(current) --- else --- local r = getattr(current,attribute) --- if r and not done[r] then --- done[r] = true --- head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir) +-- local direction, pop = getdirection(current) +-- txtdir = not pop and direction -- we might need a stack +-- elseif id == localpar_code then -- only test at begin +-- pardir = getdirection(current) +-- end +-- goto next +-- ::rest:: +-- r = getattr(current,attribute) +-- if not r then +-- -- just go on, can be kerns +-- elseif not reference then +-- reference, first, last, firstdir = r, current, current, txtdir +-- elseif r == reference then +-- last = current +-- elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code +-- if not skip or r > skip then -- maybe no > test +-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- reference, first, last, firstdir = nil, nil, nil, nil -- end +-- else +-- reference, first, last, firstdir = r, current, current, txtdir -- end +-- ::next:: -- current = getnext(current) -- end --- return head, true +-- if reference and (done[reference] or 0) == 0 then +-- head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) +-- end +-- return head, pardir, txtdir -- end -- tracing: todo: use predefined colors @@ -595,11 +735,11 @@ nodes.references = { -- todo: get rid of n (n is just a number, can be used for tracing, obsolete) -local function setreference(h,d,r) +local function setreference(h,d,r) -- h and d can be nil topofstack = topofstack + 1 -- the preroll permits us to determine samepage (but delayed also has some advantages) -- so some part of the backend work is already done here - stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) } + stack[topofstack] = { r, h or false, d or false, codeinjections.prerollreference(r) } -- texsetattribute(attribute,topofstack) -- todo -> at tex end texsetcount("lastreferenceattribute",topofstack) end @@ -615,7 +755,11 @@ local function makereference(width,height,depth,reference) -- height and depth a if trace_references then report_reference("resolving attribute %a",reference) end - local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5] + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local set = sr[4] + local n = sr[5] -- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth) if ht then if height < ht then height = ht end @@ -672,11 +816,9 @@ end function nodes.references.handler(head) if head and topofstack > 0 then - local head = tonut(head) - local head, done = inject_areas(head,attribute,makereference,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makereference,stack,done)) else - return head, false + return head end end @@ -706,7 +848,11 @@ local function makedestination(width,height,depth,reference) if trace_destinations then report_destination("resolving attribute %a",reference) end - local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local name = sr[4] + local view = sr[5] if ht then if height < ht then height = ht end if depth < dp then depth = dp end @@ -783,21 +929,12 @@ local function makedestination(width,height,depth,reference) end end --- function nodes.destinations.handler(head) --- if head and topofstack > 0 then --- return inject_area(head,attribute,makedestination,stack,done) -- singular --- else --- return head, false --- end --- end function nodes.destinations.handler(head) if head and topofstack > 0 then - local head = tonut(head) - local head, done = inject_areas(head,attribute,makedestination,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makedestination,stack,done)) else - return head, false + return head end end @@ -907,15 +1044,3 @@ statistics.register("interactive elements", function() return nil end end) - -function references.enableinteraction() - enableaction("shipouts","nodes.references.handler") - enableaction("shipouts","nodes.destinations.handler") - function references.enableinteraction() end -end - -implement { - name = "enableinteraction", - actions = references.enableinteraction, - onlyonce = true -} diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-res.lua b/Master/texmf-dist/tex/context/base/mkiv/node-res.lua index a6211e80e4c..d9999968ae6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-res.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-res.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['node-res'] = { license = "see context related readme files" } +local type, next = type, next local gmatch, format = string.gmatch, string.format --[[ldx-- @@ -13,34 +14,39 @@ local gmatch, format = string.gmatch, string.format for debugging node management.

--ldx]]-- -local report_nodes = logs.reporter("nodes","housekeeping") - local nodes, node = nodes, node -nodes.pool = nodes.pool or { } -local nodepool = nodes.pool +local report_nodes = logs.reporter("nodes","housekeeping") -local whatsitcodes = nodes.whatsitcodes -local skipcodes = nodes.skipcodes -local kerncodes = nodes.kerncodes -local rulecodes = nodes.rulecodes -local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes -local boundarycodes = nodes.boundarycodes -local usercodes = nodes.usercodes +nodes.pool = nodes.pool or { } +local nodepool = nodes.pool -local glyph_code = nodecodes.glyph +local whatsitcodes = nodes.whatsitcodes +local gluecodes = nodes.gluecodes +local kerncodes = nodes.kerncodes +local rulecodes = nodes.rulecodes +local nodecodes = nodes.nodecodes +local leadercodes = nodes.leadercodes +local boundarycodes = nodes.boundarycodes +local usercodes = nodes.usercodes -local allocate = utilities.storage.allocate +local nodeproperties = nodes.properties.data -local texgetcount = tex.getcount +local glyph_code = nodecodes.glyph +local rule_code = nodecodes.rule +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local whatsit_code = nodecodes.whatsit -local reserved, nofreserved = { }, 0 +local currentfont = font.current +local texgetcount = tex.getcount --- user nodes +local allocate = utilities.storage.allocate -local userids = allocate() -local lastid = 0 +local reserved = { } +local nofreserved = 0 +local userids = allocate() +local lastid = 0 setmetatable(userids, { __index = function(t,k) @@ -89,6 +95,9 @@ local setwidth = nuts.setwidth local setsubtype = nuts.setsubtype local setleader = nuts.setleader +local setdata = nuts.setdata +local setvalue = nuts.setvalue + local copy_nut = nuts.copy local new_nut = nuts.new local flush_nut = nuts.flush @@ -147,68 +156,68 @@ nutpool.register = register_node -- could be register_nut -- so far -local disc = register_nut(new_nut("disc")) -local kern = register_nut(new_nut("kern",kerncodes.userkern)) -local fontkern = register_nut(new_nut("kern",kerncodes.fontkern)) -local italickern = register_nut(new_nut("kern",kerncodes.italiccorrection)) -local penalty = register_nut(new_nut("penalty")) -local glue = register_nut(new_nut("glue")) -- glue.spec = nil -local glue_spec = register_nut(new_nut("glue_spec")) -local glyph = register_nut(new_nut("glyph",0)) +local disc = register_nut(new_nut(nodecodes.disc)) +local kern = register_nut(new_nut(kern_code,kerncodes.userkern)) +local fontkern = register_nut(new_nut(kern_code,kerncodes.fontkern)) +local italickern = register_nut(new_nut(kern_code,kerncodes.italiccorrection)) +local penalty = register_nut(new_nut(nodecodes.penalty)) +local glue = register_nut(new_nut(glue_code)) -- glue.spec = nil +local glue_spec = register_nut(new_nut(nodecodes.gluespec)) +local glyph = register_nut(new_nut(glyph_code,0)) -local textdir = register_nut(new_nut("dir")) +local textdir = register_nut(new_nut(nodecodes.dir)) -local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua)) -local special = register_nut(new_nut("whatsit",whatsitcodes.special)) +local latelua = register_nut(new_nut(whatsit_code,whatsitcodes.latelua)) +local savepos = register_nut(new_nut(whatsit_code,whatsitcodes.savepos)) -local user_node = new_nut("whatsit",whatsitcodes.userdefined) +local user_node = new_nut(whatsit_code,whatsitcodes.userdefined) -local user_number = register_nut(copy_nut(user_node)) setfield(user_number, "type",usercodes.number) -local user_nodes = register_nut(copy_nut(user_node)) setfield(user_nodes, "type",usercodes.node) -local user_string = register_nut(copy_nut(user_node)) setfield(user_string, "type",usercodes.string) -local user_tokens = register_nut(copy_nut(user_node)) setfield(user_tokens, "type",usercodes.token) ------ user_lua = register_nut(copy_nut(user_node)) setfield(user_lua, "type",usercodes.lua) -- in > 0.95 -local user_attributes = register_nut(copy_nut(user_node)) setfield(user_attributes,"type",usercodes.attribute) +if CONTEXTLMTXMODE < 2 then + setfield(user_node,"type",usercodes.number) +end -local left_margin_kern = register_nut(new_nut("margin_kern",0)) -local right_margin_kern = register_nut(new_nut("margin_kern",1)) +local left_margin_kern = register_nut(new_nut(nodecodes.marginkern,0)) +local right_margin_kern = register_nut(new_nut(nodecodes.marginkern,1)) -local lineskip = register_nut(new_nut("glue",skipcodes.lineskip)) -local baselineskip = register_nut(new_nut("glue",skipcodes.baselineskip)) -local leftskip = register_nut(new_nut("glue",skipcodes.leftskip)) -local rightskip = register_nut(new_nut("glue",skipcodes.rightskip)) +local lineskip = register_nut(new_nut(glue_code,gluecodes.lineskip)) +local baselineskip = register_nut(new_nut(glue_code,gluecodes.baselineskip)) +local leftskip = register_nut(new_nut(glue_code,gluecodes.leftskip)) +local rightskip = register_nut(new_nut(glue_code,gluecodes.rightskip)) -local temp = register_nut(new_nut("temp",0)) +local temp = register_nut(new_nut(nodecodes.temp,0)) -local noad = register_nut(new_nut("noad")) -local delimiter = register_nut(new_nut("delim")) -local fence = register_nut(new_nut("fence")) -local submlist = register_nut(new_nut("sub_mlist")) -local accent = register_nut(new_nut("accent")) -local radical = register_nut(new_nut("radical")) -local fraction = register_nut(new_nut("fraction")) -local subbox = register_nut(new_nut("sub_box")) -local mathchar = register_nut(new_nut("math_char")) -local mathtextchar = register_nut(new_nut("math_text_char")) -local choice = register_nut(new_nut("choice")) +local noad = register_nut(new_nut(nodecodes.noad)) +local delimiter = register_nut(new_nut(nodecodes.delim)) +local fence = register_nut(new_nut(nodecodes.fence)) +local submlist = register_nut(new_nut(nodecodes.submlist)) +local accent = register_nut(new_nut(nodecodes.accent)) +local radical = register_nut(new_nut(nodecodes.radical)) +local fraction = register_nut(new_nut(nodecodes.fraction)) +local subbox = register_nut(new_nut(nodecodes.subbox)) +local mathchar = register_nut(new_nut(nodecodes.mathchar)) +local mathtextchar = register_nut(new_nut(nodecodes.mathtextchar)) +local choice = register_nut(new_nut(nodecodes.choice)) -local boundary = register_nut(new_nut("boundary",boundarycodes.user)) -local wordboundary = register_nut(new_nut("boundary",boundarycodes.word)) +local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user)) +local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word)) -local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0) +local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,leadercodes.cleaders) setglue(cleader,0,65536,0,2,0) -- the dir field needs to be set otherwise crash: -local rule = register_nut(new_nut("rule")) setdir(rule, "TLT") -local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setdir(rule, "TLT") -local userrule = register_nut(new_nut("rule",rulecodes.user)) setdir(rule, "TLT") -local hlist = register_nut(new_nut("hlist")) setdir(hlist,"TLT") -local vlist = register_nut(new_nut("vlist")) setdir(vlist,"TLT") +local lefttoright_code = nodes.dirvalues.lefttoright + +local rule = register_nut(new_nut(rule_code)) setdirection(rule, lefttoright_code) +local emptyrule = register_nut(new_nut(rule_code,rulecodes.empty)) setdirection(rule, lefttoright_code) +local userrule = register_nut(new_nut(rule_code,rulecodes.user)) setdirection(rule, lefttoright_code) +local outlinerule = register_nut(new_nut(rule_code,rulecodes.outline)) setdirection(rule, lefttoright_code) +local hlist = register_nut(new_nut(nodecodes.hlist)) setdirection(hlist,lefttoright_code) +local vlist = register_nut(new_nut(nodecodes.vlist)) setdirection(vlist,lefttoright_code) function nutpool.glyph(fnt,chr) local n = copy_nut(glyph) if fnt then - setfont(n,fnt,chr) + setfont(n,fnt == true and currentfont() or fnt,chr) elseif chr then setchar(n,chr) end @@ -234,7 +243,7 @@ end function nutpool.boundary(v) local n = copy_nut(boundary) if v and v ~= 0 then - setfield(n,"value",v) + setvalue(n,v) end return n end @@ -242,7 +251,7 @@ end function nutpool.wordboundary(v) local n = copy_nut(wordboundary) if v and v ~= 0 then - setfield(n,"value",v) + setvalue(n,v) end return n end @@ -335,7 +344,7 @@ function nutpool.disc(pre,post,replace) return d end -function nutpool.textdir(dir) +function nutpool.textdir(dir) -- obsolete ! local t = copy_nut(textdir) if dir then setdir(t,dir) @@ -355,35 +364,49 @@ function nutpool.direction(dir,swap) return t end -function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt +function nutpool.rule(width,height,depth,direction) -- w/h/d == nil will let them adapt local n = copy_nut(rule) if width or height or depth then setwhd(n,width,height,depth) end - if dir then - setdir(n,dir) + if direction then + setdirection(n,direction) end return n end -function nutpool.emptyrule(width,height,depth,dir) -- w/h/d == nil will let them adapt +function nutpool.emptyrule(width,height,depth,direction) -- w/h/d == nil will let them adapt local n = copy_nut(emptyrule) if width or height or depth then setwhd(n,width,height,depth) end - if dir then - setdir(n,dir) + if direction then + setdirection(n,direction) end return n end -function nutpool.userrule(width,height,depth,dir) -- w/h/d == nil will let them adapt +function nutpool.userrule(width,height,depth,direction) -- w/h/d == nil will let them adapt local n = copy_nut(userrule) if width or height or depth then setwhd(n,width,height,depth) end - if dir then - setdir(n,dir) + if direction then + setdirection(n,direction) + end + return n +end + +function nutpool.outlinerule(width,height,depth,line,direction) -- w/h/d == nil will let them adapt + local n = copy_nut(outlinerule) + if width or height or depth then + setwhd(n,width,height,depth) + end + if line then + setfield(n,"transform",line) + end + if direction then + setdirection(n,direction) end return n end @@ -399,13 +422,32 @@ function nutpool.leader(width,list) return n end -function nutpool.latelua(code) - local n = copy_nut(latelua) - setfield(n,"string",code) - return n +function nutpool.savepos() + return copy_nut(savepos) end -nutpool.lateluafunction = nutpool.latelua +if CONTEXTLMTXMODE > 1 then + + function nutpool.latelua(code) + local n = copy_nut(latelua) + nodeproperties[n] = { data = code } + return n + end + +else + + function nutpool.latelua(code) + local n = copy_nut(latelua) + if type(code) == "table" then + local action = code.action + local specification = code.specification or code + code = function() action(specification) end + end + setdata(n,code) + return n + end + +end function nutpool.leftmarginkern(glyph,width) local n = copy_nut(left_margin_kern) @@ -494,86 +536,21 @@ function nodepool.vlist(list,width,height,depth,shift) return tonode(new_vlist(list and tonut(list),width,height,depth,shift)) end --- local num = userids["my id"] --- local str = userids[num] - -function nutpool.usernumber(id,num) - local n = copy_nut(user_number) - if num then - setfield(n,"user_id",id) - setfield(n,"value",num) - elseif id then - setfield(n,"value",id) - end - return n -end - -function nutpool.userlist(id,list) - local n = copy_nut(user_nodes) - if list then - setfield(n,"user_id",id) - setfield(n,"value",list) - else - setfield(n,"value",id) - end - return n -end - -function nutpool.userstring(id,str) - local n = copy_nut(user_string) - if str then - setfield(n,"user_id",id) - setfield(n,"value",str) - else - setfield(n,"value",id) - end - return n -end - -function nutpool.usertokens(id,tokens) - local n = copy_nut(user_tokens) - if tokens then - setfield(n,"user_id",id) - setfield(n,"value",tokens) - else - setfield(n,"value",id) - end - return n -end - -function nutpool.userlua(id,code) - local n = copy_nut(user_lua) - if code then - setfield(n,"user_id",id) - setfield(n,"value",code) - else - setfield(n,"value",id) - end - return n -end - -function nutpool.userattributes(id,attr) - local n = copy_nut(user_attributes) - if attr then - setfield(n,"user_id",id) - setfield(n,"value",attr) - else - setfield(n,"value",id) - end - return n -end - -function nutpool.special(str) - local n = copy_nut(special) - setfield(n,"data",str) +function nutpool.usernode(id,data) + local n = copy_nut(user_node) + nodeproperties[n] = { + id = id, + data = data, + } return n end -- housekeeping local function cleanup(nofboxes) -- todo - if nodes.tracers.steppers then -- to be resolved - nodes.tracers.steppers.reset() -- todo: make a registration subsystem + local tracers = nodes.tracers + if tracers and tracers.steppers then -- to be resolved + tracers.steppers.reset() -- todo: make a registration subsystem end local nl = 0 local nr = nofreserved @@ -624,3 +601,45 @@ statistics.register("node memory usage", function() -- comes after cleanup ! end) lua.registerfinalizer(cleanup, "cleanup reserved nodes") + +-- experiment + +do + + local glyph = tonode(glyph) + local traverse_id = nodes.traverse_id + + local traversers = table.setmetatableindex(function(t,k) + local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph) + t[k] = v + return v + end) + + traversers.node = nodes.traverse (glyph) + traversers.char = nodes.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph(glyph) end + if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end + + nodes.traversers = traversers + +end + +do + + local glyph = glyph + local traverse_id = nuts.traverse_id + + local traversers = table.setmetatableindex(function(t,k) + local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph) + t[k] = v + return v + end) + + traversers.node = nuts.traverse (glyph) + traversers.char = nuts.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph(glyph) end + if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end + + nuts.traversers = traversers + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua index 2b0368c2bc5..ea0e5c7a0c8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-rul.lua @@ -37,18 +37,20 @@ local setlink = nuts.setlink local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid -local getdir = nuts.getdir +local getdirection = nuts.getdirection local getattr = nuts.getattr local setattr = nuts.setattr local getfont = nuts.getfont local getsubtype = nuts.getsubtype local getlist = nuts.getlist local setwhd = nuts.setwhd -local setdir = nuts.setdir local setattrlist = nuts.setattrlist local setshift = nuts.setshift local getwidth = nuts.getwidth local setwidth = nuts.setwidth +local setfield = nuts.setfield + +local isglyph = nuts.isglyph local flushlist = nuts.flush_list local effective_glue = nuts.effective_glue @@ -56,17 +58,16 @@ local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local find_tail = nuts.tail local setglue = nuts.setglue -local traverse_id = nuts.traverse_id -local list_dimensions = nuts.rangedimensions +local getrangedimensions = nuts.rangedimensions local hpack_nodes = nuts.hpack -local current_attr = nuts.current_attr local copy_list = nuts.copy_list +local nexthlist = nuts.traversers.hlist + local nodecodes = nodes.nodecodes local rulecodes = nodes.rulecodes local gluecodes = nodes.gluecodes local listcodes = nodes.listcodes -local kerncodes = nodes.kerncodes local glyph_code = nodecodes.glyph local localpar_code = nodecodes.localpar @@ -74,8 +75,8 @@ local dir_code = nodecodes.dir local glue_code = nodecodes.glue local hlist_code = nodecodes.hlist -local indent_code = listcodes.indent -local line_code = listcodes.line +local indentlist_code = listcodes.indent +local linelist_code = listcodes.line local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip @@ -121,8 +122,8 @@ local setmetatableindex = table.setmetatableindex -- -local striprange = nodes.striprange -local processwords = nodes.processwords +local striprange = nuts.striprange +local processwords = nuts.processwords -- @@ -144,7 +145,7 @@ local function usernutrule(t,noattributes) if noattributes == false or noattributes == nil then -- avoid fuzzy ones else - setattrlist(r,current_attr()) + setattrlist(r,true) end properties[r] = t return r @@ -156,9 +157,11 @@ local function userrule(t,noattributes) return tonode(usernutrule(t,noattributes)) end -rules.userrule = userrule -local ruleactions = { } -rules.ruleactions = ruleactions +rules.userrule = userrule +local ruleactions = { } + +rules .ruleactions = ruleactions +nutrules.ruleactions = ruleactions -- convenient local function mathradical(n,h,v) ----- size = getfield(n,"index") @@ -203,18 +206,18 @@ local subtypeactions = { [rulecodes.radical] = mathradical, } -callbacks.register( - "process_rule", - function(n,h,v) - local n = tonut(n) - local s = getsubtype(n) - local a = subtypeactions[s] - if a then - a(n,h,v) - end - end, - "handle additional user rule features" -) +local function process_rule(n,h,v) + local n = tonut(n) + local s = getsubtype(n) + local a = subtypeactions[s] + if a then + a(n,h,v) + end +end + +callbacks.register("process_rule",process_rule,"handle additional user rule features") + +callbacks.functions.process_rule = process_rule -- @@ -239,9 +242,9 @@ end local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose local font = nil - local id = getid(f) - if id == glyph_code then - font = getfont(f) + local char, id = isglyph(f) + if char then + font = id elseif id == hlist_code then font = getattr(f,a_runningtext) end @@ -263,7 +266,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a if not f then return head end - local w, ht, dp = list_dimensions(parent,f,getnext(l)) + local w, ht, dp = getrangedimensions(parent,f,getnext(l)) local method = d.method local empty = d.empty == v_yes local offset = d.offset @@ -331,7 +334,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a end end if mp and mp ~= "" then - local r = userrule { + local r = usernutrule { width = w, height = ht, depth = dp, @@ -344,16 +347,17 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a ca = color, ta = transparency, } - inject(tonut(r),w,ht,dp) + inject(r,w,ht,dp) else local tx = d.text if tx then - tx = copy_list(tx) + local l = copy_list(tx) if d["repeat"] == v_yes then - tx = new_leader(w,tx) + l = new_leader(w,l) + setattrlist(l,tx) end - local r = hpack_nodes(tx,w,"exactly") - inject(r,w,ht,dp) + l = hpack_nodes(l,w,"exactly") + inject(l,w,ht,dp) else for i=1,level do local ht = (offset+(i-1)*dy)*e + rulethickness - m @@ -373,10 +377,8 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a return head end -local process = nodes.processwords - rules.handler = function(head) - return process(a_ruled,data,flush_ruled,head) + return processwords(a_ruled,data,flush_ruled,head) end function rules.enable() @@ -409,7 +411,7 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha local next = getnext(last) setprev(first) setnext(last) - local width, height, depth = list_dimensions(parent,first,next) + local width, height, depth = getrangedimensions(parent,first,next) local list = hpack_nodes(first,width,"exactly") -- we can use a simple pack if first == head then head = list @@ -429,9 +431,9 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha return head end -local process = nodes.processwords - -nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end +nodes.shifts.handler = function(head) + return processwords(a_shifted,data,flush_shifted,head) +end function nodes.shifts.enable() enableaction("shipouts","nodes.shifts.handler") @@ -459,7 +461,7 @@ local function linefiller(current,data,width,location) local ca = data.ca local ta = data.ta if mp and mp ~= "" then - return tonut(userrule { + return usernutrule { width = width, height = height, depth = depth, @@ -470,18 +472,56 @@ local function linefiller(current,data,width,location) ca = ca, ta = ta, option = location, - direction = getdir(current), - }) + direction = getdirection(current), + } else - local linefiller = new_rule(width,height,depth) + local rule = new_rule(width,height,depth) if ca then - setattr(linefiller,a_colorspace,ma) - setattr(linefiller,a_color,ca) + setattr(rule,a_colorspace,ma) + setattr(rule,a_color,ca) end if ta then - setattr(linefiller,a_transparency,ta) + setattr(rule,a_transparency,ta) + end + return rule + end +end + +function nodes.linefillers.filler(current,data,width,height,depth) + if width and width > 0 then + local height = height or data.height or 0 + local depth = depth or data.depth or 0 + if (height + depth) ~= 0 then + local mp = data.mp + local ma = data.ma + local ca = data.ca + local ta = data.ta + if mp and mp ~= "" then + return usernutrule { + width = width, + height = height, + depth = depth, + type = "mp", + line = data.rulethickness, + data = mp, + ma = ma, + ca = ca, + ta = ta, + option = location, + direction = getdirection(current), + } + else + local rule = new_rule(width,height,depth) + if ca then + setattr(rule,a_colorspace,ma) + setattr(rule,a_color,ca) + end + if ta then + setattr(rule,a_transparency,ta) + end + return rule + end end - return linefiller end end @@ -496,119 +536,115 @@ local function find_attr(head,attr) end function nodes.linefillers.handler(head) --- local current = tonut(head) -- when we hook into the contributers - for current in traverse_id(hlist_code,tonut(head)) do - if getsubtype(current) == line_code then - local list = getlist(current) - if list then - -- why doesn't leftskip take the attributes - -- or list[linefiller] or maybe first match (maybe we need a fast helper for that) - local a = getattr(current,a_linefiller) - if a then - local class = a % 1000 - local data = data[class] - if data then - local location = data.location - local scope = data.scope - local distance = data.distance - local threshold = data.threshold - local leftlocal = false - local rightlocal = false - -- - if scope == v_right then - leftlocal = true - elseif scope == v_left then - rightlocal = true - elseif scope == v_local then - leftlocal = true - rightlocal = true - end - -- - if location == v_left or location == v_both then - local lskip = nil -- leftskip - local iskip = nil -- indentation - local head = list - while head do - local id = getid(head) - if id == glue_code then - if getsubtype(head) == leftskip_code then - lskip = head - else - break - end - elseif id == localpar_code or id == dir_code then - -- go on - elseif id == hlist_code then - if getsubtype(head) == indent_code then - iskip = head - end - break + for current, subtype, list in nexthlist, head do + if list and subtype == linelist_code then + -- why doesn't leftskip take the attributes + -- or list[linefiller] or maybe first match (maybe we need a fast helper for that) + local a = getattr(current,a_linefiller) + if a then + local class = a % 1000 + local data = data[class] + if data then + local location = data.location + local scope = data.scope + local distance = data.distance + local threshold = data.threshold + local leftlocal = false + local rightlocal = false + -- + if scope == v_right then + leftlocal = true + elseif scope == v_left then + rightlocal = true + elseif scope == v_local then + leftlocal = true + rightlocal = true + end + -- + if location == v_left or location == v_both then + local lskip = nil -- leftskip + local iskip = nil -- indentation + local head = list + while head do + local id = getid(head) + if id == glue_code then + if getsubtype(head) == leftskip_code then + lskip = head else break end - head = getnext(head) + elseif id == localpar_code or id == dir_code then + -- go on + elseif id == hlist_code then + if getsubtype(head) == indentlist_code then + iskip = head + end + break + else + break end - if head then - local indentation = iskip and getwidth(iskip) or 0 - local leftfixed = lskip and getwidth(lskip) or 0 - local lefttotal = lskip and effective_glue(lskip,current) or 0 - local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance - if width > threshold then - if iskip then - setwidth(iskip,0) + head = getnext(head) + end + if head then + local indentation = iskip and getwidth(iskip) or 0 + local leftfixed = lskip and getwidth(lskip) or 0 + local lefttotal = lskip and effective_glue(lskip,current) or 0 + local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance + if width > threshold then + if iskip then + setwidth(iskip,0) + end + if lskip then + setglue(lskip,leftlocal and getwidth(lskip) or nil) + if distance > 0 then + insert_node_after(list,lskip,new_kern(distance)) end - if lskip then - setglue(lskip,leftlocal and getwidth(lskip) or nil) - if distance > 0 then - insert_node_after(list,lskip,new_kern(distance)) - end - insert_node_after(list,lskip,linefiller(current,data,width,"left")) - else - insert_node_before(list,head,linefiller(current,data,width,"left")) - if distance > 0 then - insert_node_before(list,head,new_kern(distance)) - end + insert_node_after(list,lskip,linefiller(current,data,width,"left")) + else + insert_node_before(list,head,linefiller(current,data,width,"left")) + if distance > 0 then + insert_node_before(list,head,new_kern(distance)) end end end end - -- - if location == v_right or location == v_both then - local pskip = nil -- parfillskip - local rskip = nil -- rightskip - local tail = find_tail(list) - while tail and getid(tail) == glue_code do - local subtype = getsubtype(tail) - if subtype == rightskip_code then - rskip = tail - elseif subtype == parfillskip_code then - pskip = tail - else - break - end - tail = getprev(tail) + end + -- + if location == v_right or location == v_both then + local pskip = nil -- parfillskip + local rskip = nil -- rightskip + local tail = find_tail(list) + while tail and getid(tail) == glue_code do + local subtype = getsubtype(tail) + if subtype == rightskip_code then + rskip = tail + elseif subtype == parfillskip_code then + pskip = tail + else + break end - if tail then - local rightfixed = rskip and getwidth(rskip) or 0 - local righttotal = rskip and effective_glue(rskip,current) or 0 - local parfixed = pskip and getwidth(pskip) or 0 - local partotal = pskip and effective_glue(pskip,current) or 0 - local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance - if width > threshold then - if pskip then - setglue(pskip) + tail = getprev(tail) + end + if tail then + local rightfixed = rskip and getwidth(rskip) or 0 + local righttotal = rskip and effective_glue(rskip,current) or 0 + local parfixed = pskip and getwidth(pskip) or 0 + local partotal = pskip and effective_glue(pskip,current) or 0 + local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance + if width > threshold then + if pskip then + setglue(pskip) + end + if rskip then + setglue(rskip,rightlocal and getwidth(rskip) or nil) + if distance > 0 then + insert_node_before(list,rskip,new_kern(distance)) end - if rskip then - setglue(rskip,rightlocal and getwidth(rskip) or nil) - if distance > 0 then - insert_node_before(list,rskip,new_kern(distance)) - end - insert_node_before(list,rskip,linefiller(current,data,width,"right")) - else - insert_node_after(list,tail,linefiller(current,data,width,"right")) - if distance > 0 then - insert_node_after(list,tail,new_kern(distance)) - end + insert_node_before(list,rskip,linefiller(current,data,width,"right")) + else + insert_node_after(list,tail,linefiller(current,data,width,"right")) + if distance > 0 then + insert_node_after(list,tail,new_kern(distance)) end end end @@ -708,3 +744,35 @@ implement { onlyonce = true, actions = nodes.linefillers.enable } + +-- We add a bonus feature here: + +interfaces.implement { + name = "autorule", + arguments = { + { + { "width", "dimension" }, + { "height", "dimension" }, + { "depth", "dimension" }, + { "left", "dimension" }, + { "right", "dimension" }, + }, + }, + actions = function(t) + local l = t.left + local r = t.right + local n = new_rule( + t.width, + t.height, + t.depth + ) + setattrlist(n,true) + if l then + setfield(n,"left",l) + end + if r then + setfield(n,"right",r) + end + context(tonode(n)) + end +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv index 643e93c428d..19f398eb900 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/node-rul.mkiv @@ -71,7 +71,7 @@ %definesystemattribute[ruled] %definesystemattribute[shifted] -\registerctxluafile{node-rul}{} +\registerctxluafile{node-rul}{optimize} \installcorenamespace{bar} \installcorenamespace{barindex} @@ -146,6 +146,8 @@ {\node_rules_set{#1}\barparameter\c!left}% {\relax\barparameter\c!right}} +% store in properties + \unexpanded\def\node_rules_set#1% maybe reverse the 1000 (also maybe use more attributes instead of settings) {\edef\currentbar{#1}% \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor @@ -571,4 +573,39 @@ \c!distance=.25\emwidth, \c!rulethickness=.25\exheight] +%D Bonus: +%D +%D \starttyping +%D \startuseMPgraphic{foo} +%D fill unitsquare +%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) +%D shifted (-ExHeight/8,ExHeight/16) +%D withcolor RuleColor ; +%D \stopuseMPgraphic +%D +%D \definelinefiller[foo][mp=foo,color=darkred] +%D +%D \linefillerhbox[foo]{OEPS} +%D \stoptyping + +\unexpanded\def\node_backgrounds_filler_box#1#2[#3]% + {\bgroup + \clf_enablebackgroundboxes + \dowithnextbox{% + \node_linefiller_set{#3}% already sets the attribute + #1% + attr \backgroundattribute \plusone + % attr \linefillerattribute \the\attribute\linefillerattribute + {\box\nextbox}% + \egroup}% + #2} + +\unexpanded\def\linefillerhbox{\node_backgrounds_filler_box\hpack\hbox} +\unexpanded\def\linefillervbox{\node_backgrounds_filler_box\vpack\vbox} +\unexpanded\def\linefillervtop{\node_backgrounds_filler_box\tpack\vtop} + +%D Bonus: + +\unexpanded\def\autorule{\clf_autorule} + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/node-scn.lua index b294b30131d..a40a5271a9e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-scn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-scn.lua @@ -12,8 +12,6 @@ local attributes = attributes local nodes = nodes local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -26,9 +24,8 @@ local setlist = nuts.setlist local end_of_math = nuts.end_of_math local nodecodes = nodes.nodecodes -local rulecodes = nodes.rulecodes +local leadercodes = nodes.leadercodes local gluecodes = nodes.gluecodes -local listcodes = nodes.listcodes local kerncodes = nodes.kerncodes local glyph_code = nodecodes.glyph @@ -46,7 +43,8 @@ local vlist_code = nodecodes.vlist local userskip_code = gluecodes.userskip local spaceskip_code = gluecodes.spaceskip local xspaceskip_code = gluecodes.xspaceskip -local leader_code = gluecodes.leaders + +local leaders_code = leadercodes.leaders local fontkern_code = kerncodes.fontkern @@ -97,7 +95,7 @@ local function striprange(first,last) -- todo: dir return first, last end -nodes.striprange = striprange +nuts.striprange = striprange -- todo: order and maybe other dimensions @@ -205,7 +203,7 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl elseif id == glue_code then -- catch \underbar{a} \underbar{a} (subtype test is needed) local subtype = getsubtype(n) - if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leader_code)) then + if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leaders_code)) then l = n else head, done = flush(head,f,l,d,level,parent,strip), true @@ -228,17 +226,11 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl end end -nodes.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir - head = tonut(head) - if parent then - parent = tonut(parent) - end - local head, done = processwords(attribute,data,flush,head,parent) - return tonode(head), done +nuts.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir + return processwords(attribute,data,flush,head,parent) end -- works on lines ! - -- todo: stack because skip can change when nested local function processranges(attribute,flush,head,parent,depth,skip) @@ -319,11 +311,6 @@ local function processranges(attribute,flush,head,parent,depth,skip) end end -nodes.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir - head = tonut(head) - if parent then - parent = tonut(parent) - end - local head, done = processranges(attribute,flush,head,parent,0) - return tonode(head), done +nuts.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir + return processranges(attribute,flush,head,parent,0) end diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua index 7ed2b8d00d8..6fc2b7ea4cf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ser.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['node-ser'] = { -- beware, some field names will change in a next releases -- of luatex; this is pretty old code that needs an overhaul -local type = type +local type, tostring = type, tostring local concat, tohash, sortedkeys, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.print, table.serialize local formatters, format, rep = string.formatters, string.format, string.rep @@ -24,16 +24,17 @@ local is_node = nodes.is_node local nodecodes = nodes.nodecodes local subtcodes = nodes.codes -local noadcodes = nodes.noadcodes local getfields = nodes.fields local tonode = nodes.tonode +local tonut = nodes.tonut local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist ----- utfchar = utf.char local f_char = formatters["%U"] +local f_attr = formatters["<%i>"] ----- fontchars = { } table.setmetatableindex(fontchars,function(t,k) fontchars = fonts.hashes.characters return fontchars[k] end) ----- f_char = utilities.strings.chkuni -- formatters["%!chkuni!"] @@ -87,7 +88,7 @@ local ignore = allocate ( tohash { local dimension = allocate ( tohash { "width", "height", "depth", "shift", "stretch", "shrink", - "xoffset", "yoffset", "xadvance", + "xoffset", "yoffset", "surround", "kern", "box_left_width", "box_right_width" @@ -145,6 +146,7 @@ local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true if ignore[v] then -- skip elseif noattributes and v == "attr" then + tt[v] = f_attr(tonut(nv)) -- skip elseif v == "prev" then tt[v] = "" diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua b/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua index 2e7a3529a54..306e38f6a58 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-shp.lua @@ -13,50 +13,51 @@ local format = string.format local concat, sortedpairs = table.concat, table.sortedpairs local setmetatableindex = table.setmetatableindex -local nodecodes = nodes.nodecodes -local whatsitcodes = nodes.whatsitcodes -local disccodes = nodes.disccodes +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local disccodes = nodes.disccodes -local tasks = nodes.tasks -local handlers = nodes.handlers +local tasks = nodes.tasks +local handlers = nodes.handlers -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local disc_code = nodecodes.disc -local whatsit_code = nodecodes.whatsit +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local disc_code = nodecodes.disc +local whatsit_code = nodecodes.whatsit -local fulldisc_code = disccodes.discretionary +local discretionarydisc_code = disccodes.discretionary -local texgetbox = tex.getbox +local implement = interfaces.implement -local implement = interfaces.implement +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode +local remove_node = nuts.remove -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local remove_node = nuts.remove -local traverse_nodes = nuts.traverse +local nextnode = nuts.traversers.node -local setfield = nuts.setfield -local setlink = nuts.setlink -local setprev = nuts.setprev -local setnext = nuts.setnext -local getid = nuts.getid -local getdisc = nuts.getdisc -local getboth = nuts.getboth -local getnext = nuts.getnext -local getlist = nuts.getlist -local getsubtype = nuts.getsubtype +local setfield = nuts.setfield +local setlink = nuts.setlink +local setprev = nuts.setprev +local setnext = nuts.setnext +local getid = nuts.getid +local getdisc = nuts.getdisc +local getboth = nuts.getboth +local getnext = nuts.getnext +local getlist = nuts.getlist +local getsubtype = nuts.getsubtype -local setlist = nuts.setlist +local setlist = nuts.setlist -local removables = { +local getbox = nuts.getbox + +local removables = { [whatsitcodes.open] = true, [whatsitcodes.close] = true, [whatsitcodes.write] = true, [whatsitcodes.savepos] = true, [whatsitcodes.latelua] = true, - [whatsitcodes.pdfdest] = true, + -- [whatsitcodes.pdfdest] = true, } -- About 10% of the nodes make no sense for the backend. By (at least) @@ -72,7 +73,7 @@ local function cleanup_redundant(head) -- better name is: flatten_page while start do local id = getid(start) if id == disc_code then - if getsubtype(start) == fulldisc_code then + if getsubtype(start) == discretionarydisc_code then local _, _, replace, _, _ tail = getdisc(start,true) if replace then local prev, next = getboth(start) @@ -117,6 +118,8 @@ local function cleanup_redundant(head) -- better name is: flatten_page return head end +handlers.cleanuppage = cleanup_redundant -- nut + local function cleanup_flushed(head) -- rough local start = head while start do @@ -143,26 +146,20 @@ local function cleanup_flushed(head) -- rough return head end -function handlers.cleanuppage(head) - return tonode(cleanup_redundant(tonut(head))), true -end - -function handlers.cleanupbox(head) - return tonode(cleanup_flushed(tonut(head))), true +function handlers.cleanupbox(box) + cleanup_flushed(getbox(box)) end local actions = tasks.actions("shipouts") -function handlers.finalize(head,where) -- problem, attr loaded before node, todo ... - return actions(head,where) +function handlers.finalizebox(box) + actions(getbox(box)) -- nut end --- handlers.finalize = actions - -- interface -implement { name = "cleanupbox", actions = { texgetbox, cleanup_flushed }, arguments = "integer" } -implement { name = "finalizebox", actions = { texgetbox, actions }, arguments = "integer" } +implement { name = "cleanupbox", actions = handlers.cleanupbox, arguments = "integer" } +implement { name = "finalizebox", actions = handlers.finalizebox, arguments = "integer" } -- just in case we want to optimize lookups: @@ -192,8 +189,7 @@ local function count(head,data,subcategory) -- no components, pre, post, replace .. can maybe an option .. but -- we use this for optimization so it makes sense to look the the -- main node only - for n in traverse_nodes(tonut(head)) do - local id = getid(n) + for n, id in nextnode, tonut(head) do local dn = data[nodecodes[id]] -- we could use id and then later convert to nodecodes dn[subcategory] = dn[subcategory] + 1 if id == hlist_code or id == vlist_code then diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-syn.lua b/Master/texmf-dist/tex/context/base/mkiv/node-syn.lua index 9d716c44a52..a00dc65ec53 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-syn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-syn.lua @@ -24,7 +24,16 @@ if not modules then modules = { } end modules ['node-syn'] = { -- I only tested SumatraPDF with SciTE, for which one needs to configure in the -- viewer: -- --- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $ +-- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $ +-- +-- In fact, a way more powerful implementation would have been not to add a library +-- to a viewer, but letthe viewer call an external program: +-- +-- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $ +-- +-- which would (re)launch the editor in the right spot. That way we can really +-- tune well to the macro package used and also avoid the fuzzy heuristics of +-- the library. -- -- Unfortunately syntex always removes the files at the end and not at the start -- (this happens in synctexterminate) so we need to work around that by using an @@ -124,10 +133,9 @@ local openfile, renamefile, removefile = io.open, os.rename, os.remove local report_system = logs.reporter("system") local tex = tex +local texget = tex.get local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getid = nuts.getid local getlist = nuts.getlist @@ -168,14 +176,9 @@ local set_synctex_tag = tex.set_synctex_tag local force_synctex_tag = tex.force_synctex_tag local force_synctex_line = tex.force_synctex_line ----- get_synctex_tag = tex.get_synctex_tag ------ get_synctex_line = tex.get_synctex_line +local get_synctex_line = tex.get_synctex_line local set_synctex_mode = tex.set_synctex_mode -local getpos = function() - getpos = backends.codeinjections.getpos - return getpos() - end - local foundintree = resolvers.foundintree local eol = "\010" @@ -199,6 +202,8 @@ local f_vlist_2 = formatters["v%i,%i:%i,%s:%i,%i,%i\010"] local synctex = luatex.synctex or { } luatex.synctex = synctex +local getpos ; getpos = function() getpos = job.positions.getpos return getpos() end + -- status stuff local enabled = false @@ -268,6 +273,34 @@ function synctex.resetfilename() end end +do + + local nesting = 0 + local ignored = false + + function synctex.pushline() + nesting = nesting + 1 + if nesting == 1 then + local l = get_synctex_line() + ignored = l and l > 0 + if not ignored then + force_synctex_line(texget("inputlineno")) + end + end + end + + function synctex.popline() + if nesting == 1 then + if not ignored then + force_synctex_line() + ignored = false + end + end + nesting = nesting - 1 + end + +end + -- the node stuff local filehandle = nil @@ -324,6 +357,7 @@ end function synctex.wrapup() if tmpfile then renamefile(tmpfile,logfile) + tmpfile = nil end end @@ -340,9 +374,15 @@ local function flushpostamble() enabled = false end +local getpagedimensions getpagedimensions = function() + getpagedimensions = backends.codeinjections.getpagedimensions + return getpagedimensions() +end + -- local function doaction(action,t,l,w,h,d) +-- local pagewidth, pageheight = getpagedimensions() -- local x, y = getpos() --- filehandle:write(action(t,l,x,tex.pageheight-y,w,h,d)) +-- filehandle:write(action(t,l,x,pageheight-y,w,h,d)) -- nofobjects = nofobjects + 1 -- end -- @@ -378,24 +418,27 @@ end -- generic -- -- local function doaction(t,l,w,h,d) +-- local pagewidth, pageheight = getpagedimensions() -- local x, y = getpos() --- filehandle:write(f_hlist_1(t,l,x,tex.pageheight-y,w,h,d)) +-- filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d)) -- nofobjects = nofobjects + 1 -- end local x_hlist do local function doaction_1(t,l,w,h,d) + local pagewidth, pageheight = getpagedimensions() local x, y = getpos() - filehandle:write(f_hlist_1(t,l,x,tex.pageheight-y,w,h,d)) + filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d)) nofobjects = nofobjects + 1 end -- local lastx, lasty, lastw, lasth, lastd -- -- local function doaction_2(t,l,w,h,d) + -- local pagewidth, pageheight = getpagedimensions() -- local x, y = getpos() - -- y = tex.pageheight-y + -- y = pageheight-y -- filehandle:write(f_hlist_2(t,l, -- x == lastx and "=" or x, -- y == lasty and "=" or y, @@ -412,8 +455,9 @@ local x_hlist do local lasty = false local function doaction_2(t,l,w,h,d) + local pagewidth, pageheight = getpagedimensions() local x, y = getpos() - y = tex.pageheight - y + y = pageheight - y filehandle:write(f_hlist_2(t,l,x,y == lasty and "=" or y,w,h,d)) lasty = y nofobjects = nofobjects + 1 @@ -623,16 +667,10 @@ end collect = collect_max function synctex.collect(head,where) - if enabled then - if where == "object" then - return head, false - else - local h = tonut(head) - h = collect(h,h) - return tonode(h), true - end + if enabled and where ~= "object" then + return collect(head,head) else - return head, false + return head end end @@ -645,10 +683,9 @@ function synctex.start() writeanchor() filehandle:write("{",nofsheets,eol) -- this seems to work: - local h = tex.pageheight - local w = tex.pagewidth + local pagewidth, pageheight = getpagedimensions() filehandle:write(z_hlist) - filehandle:write(f_vlist_1(0,0,0,h,w,h,0)) + filehandle:write(f_vlist_1(0,0,0,pageheight,pagewidth,pageheight,0)) end end end @@ -678,7 +715,7 @@ function synctex.enable() enabled = true set_synctex_mode(3) -- we want details if not used then - nodes.tasks.appendaction("shipouts", "after", "luatex.synctex.collect") + nodes.tasks.enableaction("shipouts","luatex.synctex.collect") report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!") used = true end @@ -786,11 +823,21 @@ implement { } implement { - name = "synctexpause", - actions = synctex.pause, + name = "synctexpause", + actions = synctex.pause, } implement { - name = "synctexresume", - actions = synctex.resume, + name = "synctexresume", + actions = synctex.resume, +} + +interfaces.implement { + name = "synctexpushline", + actions = synctex.pushline, +} +interfaces.implement { + name = "synctexpopline", + actions = synctex.popline, } + diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua index c9d3091df23..5857fd2e65b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-tex.lua @@ -6,33 +6,40 @@ if not modules then modules = { } end modules ['node-tex'] = { license = "see context related readme files" } -builders = builders or { } -local kernel = builders.kernel or { } -builders.kernel = kernel - -local hyphenate = lang.hyphenate -local ligaturing = node.ligaturing -local kerning = node.kerning - -kernel.originals = { - hyphenate = hyphenate, - ligaturing = ligaturing, - kerning = kerning, -} +builders = builders or { } +local kernel = builders.kernel or { } +builders.kernel = kernel + +local nuts = nodes.nuts + +local hyphenate = lang.hyphenate +local hyphenating = nuts.hyphenating +local ligaturing = nuts.ligaturing +local kerning = nuts.kerning +local cleanup = nuts.flush_components function kernel.hyphenation(head) - local done = hyphenate(head) - return head, done + return (hyphenate(head)) -- nodes ! +end + +function kernel.hyphenating(head) + return (hyphenating(head)) end function kernel.ligaturing(head) - local head, tail, done = ligaturing(head) -- we return 3 values indeed - return head, done + return (ligaturing(head)) end function kernel.kerning(head) - local head, tail, done = kerning(head) -- we return 3 values indeed - return head, done + return (kerning(head)) +end + +if cleanup then + + function kernel.cleanup(head) + return (cleanup(head)) + end + end callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua index f1259986644..e1b6927fbce 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-tra.lua @@ -21,68 +21,67 @@ local report_nodes = logs.reporter("nodes","tracing") local nodes, node, context = nodes, node, context -local texgetattribute = tex.getattribute - -local tracers = nodes.tracers or { } -nodes.tracers = tracers - -local tasks = nodes.tasks or { } -nodes.tasks = tasks - -local handlers = nodes.handlers or {} -nodes.handlers = handlers - -local injections = nodes.injections or { } -nodes.injections = injections - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getchar = nuts.getchar -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getdisc = nuts.getdisc -local setattr = nuts.setattr -local getglue = nuts.getglue -local isglyph = nuts.isglyph -local getcomponents = nuts.getcomponents -local getdir = nuts.getdir -local getwidth = nuts.getwidth - -local flush_list = nuts.flush_list -local count_nodes = nuts.countall -local used_nodes = nuts.usedlist - -local traverse_by_id = nuts.traverse_id -local traverse_nodes = nuts.traverse -local d_tostring = nuts.tostring - -local nutpool = nuts.pool -local new_rule = nutpool.rule - -local nodecodes = nodes.nodecodes -local whatcodes = nodes.whatcodes -local skipcodes = nodes.skipcodes -local fillcodes = nodes.fillcodes - -local glyph_code = nodecodes.glyph -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local disc_code = nodecodes.disc -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local rule_code = nodecodes.rule -local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar -local whatsit_code = nodecodes.whatsit - -local dimenfactors = number.dimenfactors -local fillorders = nodes.fillcodes -local formatters = string.formatters +local texgetattribute = tex.getattribute + +local tracers = nodes.tracers or { } +nodes.tracers = tracers + +local tasks = nodes.tasks or { } +nodes.tasks = tasks + +local handlers = nodes.handlers or {} +nodes.handlers = handlers + +local injections = nodes.injections or { } +nodes.injections = injections + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist +local getdisc = nuts.getdisc +local setattr = nuts.setattr +local getglue = nuts.getglue +local isglyph = nuts.isglyph +local getdirection = nuts.getdirection +local getwidth = nuts.getwidth + +local flush_list = nuts.flush_list +local count_nodes = nuts.countall +local used_nodes = nuts.usedlist + +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph + +local d_tostring = nuts.tostring + +local nutpool = nuts.pool +local new_rule = nutpool.rule + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local fillcodes = nodes.fillcodes + +local subtypes = nodes.subtypes + +local glyph_code = nodecodes.glyph +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local rule_code = nodecodes.rule +local dir_code = nodecodes.dir +local localpar_code = nodecodes.localpar +local whatsit_code = nodecodes.whatsit + +local dimenfactors = number.dimenfactors +local formatters = string.formatters -- this will be reorganized: @@ -90,23 +89,26 @@ function nodes.showlist(head, message) if message then report_nodes(message) end - for n in traverse_nodes(tonut(head)) do + for n in nextnode, tonut(head) do report_nodes(d_tostring(n)) end end function nodes.handlers.checkglyphs(head,message) - local h = tonut(head) + local h = tonut(head) -- tonut needed? local t = { } - for g in traverse_by_id(glyph_code,h) do - t[#t+1] = formatters["%U:%s"](getchar(g),getsubtype(g)) + local n = 0 + local f = formatters["%U:%s"] + for g, char, font in nextglyph, h do + n = n + 1 + t[n] = f(char,getsubtype(g)) end - if #t > 0 then - if message and message ~= "" then - report_nodes("%s, %s glyphs: % t",message,#t,t) - else - report_nodes("%s glyphs: % t",#t,t) - end + if n == 0 then + -- nothing to report + elseif message and message ~= "" then + report_nodes("%s, %s glyphs: % t",message,n,t) + else + report_nodes("%s glyphs: % t",n,t) end return false end @@ -114,8 +116,8 @@ end function nodes.handlers.checkforleaks(sparse) local l = { } local q = used_nodes() - for p in traverse_nodes(q) do - local s = table.serialize(nodes.astable(p,sparse),nodecodes[getid(p)]) + for p, id in nextnode, q do + local s = table.serialize(nodes.astable(p,sparse),nodecodes[id]) l[s] = (l[s] or 0) + 1 end flush_list(q) @@ -124,42 +126,51 @@ function nodes.handlers.checkforleaks(sparse) end end -local f_sequence = formatters["U+%04X:%s"] -local f_subrange = formatters["[[ %s ][ %s ][ %s ]]"] +local fontcharacters -- = fonts.hashes.descriptions local function tosequence(start,stop,compact) if start then + if not fontcharacters then + fontcharacters = fonts.hashes.descriptions + if not fontcharacters then + return "[no char data]" + end + end + local f_sequence = formatters["U+%04X:%s"] + local f_subrange = formatters["[[ %s ][ %s ][ %s ]]"] start = tonut(start) stop = stop and tonut(stop) local t = { } + local n = 0 while start do local c, id = isglyph(start) if c then - if compact then - local components = getcomponents(start) - if components then - t[#t+1] = tosequence(components,nil,compact) - else - t[#t+1] = utfchar(c) + local u = fontcharacters[id][c] -- id == font id + u = u and u.unicode or c + if type(u) == "table" then + local tt = { } + for i=1,#u do + local c = u[i] + tt[i] = compact and utfchar(c) or f_sequence(c,utfchar(c)) end + n = n + 1 ; t[n] = "(" .. concat(tt," ") .. ")" else - t[#t+1] = f_sequence(c,utfchar(c)) + n = n + 1 ; t[n] = compact and utfchar(c) or f_sequence(c,utfchar(c)) end elseif id == disc_code then local pre, post, replace = getdisc(start) t[#t+1] = f_subrange(pre and tosequence(pre),post and tosequence(post),replace and tosequence(replace)) elseif id == rule_code then - if compact then - t[#t+1] = "|" - else - t[#t+1] = nodecodes[id] - end - elseif id == dir_code or id == localpar_code then - t[#t+1] = "[" .. getdir(start) .. "]" + n = n + 1 ; t[n] = compact and "|" or nodecodes[id] or "?" + elseif id == dir_code then + local d, p = getdirection(start) + n = n + 1 ; t[n] = "[<" .. (p and "-" or "+") .. d .. ">]" -- todo l2r etc + elseif id == localpar_code and getsubtype(start) == 0 then + n = n + 1 ; t[n] = "[<" .. getdirection(start) .. ">]" -- todo l2r etc elseif compact then - t[#t+1] = "[]" + n = n + 1 ; t[n] = "[]" else - t[#t+1] = nodecodes[id] + n = n + 1 ; t[n] = nodecodes[id] end if start == stop then break @@ -180,13 +191,13 @@ end nodes.tosequence = tosequence nuts .tosequence = tosequence -function nodes.report(t,done) - report_nodes("output %a, changed %a, %s nodes",status.output_active,done,count_nodes(tonut(t))) +function nodes.report(t) + report_nodes("output %a, %s nodes",status.output_active,count_nodes(t)) end function nodes.packlist(head) local t = { } - for n in traverse_nodes(tonut(head)) do + for n in nextnode, tonut(head) do t[#t+1] = d_tostring(n) end return t @@ -198,10 +209,11 @@ function nodes.idstostring(head,tail) local t = { } local last_id = nil local last_n = 0 - for n in traverse_nodes(head,tail) do -- hm, does not stop at tail - local id = getid(n) + local f_two = formatters["[%s*%s]"] + local f_one = formatters["[%s]"] + for n, id, subtype in nextnode, head do if id == whatsit_code then - id = whatcodes[getsubtype(n)] + id = whatsitcodes[subtype] else id = nodecodes[id] end @@ -212,9 +224,9 @@ function nodes.idstostring(head,tail) last_n = last_n + 1 else if last_n > 1 then - t[#t+1] = formatters["[%s*%s]"](last_n,last_id) + t[#t+1] = f_two(last_n,last_id) else - t[#t+1] = formatters["[%s]"](last_id) + t[#t+1] = f_one(last_id) end last_id = id last_n = 1 @@ -227,14 +239,29 @@ function nodes.idstostring(head,tail) t[#t+1] = "no nodes" else if last_n > 1 then - t[#t+1] = formatters["[%s*%s]"](last_n,last_id) + t[#t+1] = f_two(last_n,last_id) else - t[#t+1] = formatters["[%s]"](last_id) + t[#t+1] = f_one(last_id) end end return concat(t," ") end +function nodes.idsandsubtypes(head) + local h = tonut(head) + local t = { } + local f = formatters["%s:%s"] + for n, id, subtype in nextnode, h do + local c = nodecodes[id] + if subtype then + t[#t+1] = f(c,subtypes[id][subtype]) + else + t[#t+1] = c + end + end + return concat(t, " ") +end + -- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks -- head = tonut(head) -- tail = tonut(tail) @@ -299,17 +326,19 @@ nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end local function listtoutf(h,joiner,textonly,last,nodisc) local w = { } local n = 0 + local g = formatters["<%i>"] + local d = formatters["[%s|%s|%s]"] while h do local c, id = isglyph(h) if c then - n = n + 1 ; w[n] = c >= 0 and utfchar(c) or formatters["<%i>"](c) + n = n + 1 ; w[n] = c >= 0 and utfchar(c) or g(c) if joiner then n = n + 1 ; w[n] = joiner end elseif id == disc_code then local pre, pos, rep = getdisc(h) if not nodisc then - n = n + 1 ; w[n] = formatters["[%s|%s|%s]"] ( + n = n + 1 ; w[n] = d( pre and listtoutf(pre,joiner,textonly) or "", pos and listtoutf(pos,joiner,textonly) or "", rep and listtoutf(rep,joiner,textonly) or "" @@ -354,11 +383,9 @@ local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" } local function showboxes(n,symbol,depth) depth = depth or 0 symbol = symbol or "." - for n in traverse_nodes(tonut(n)) do - local id = getid(n) + for n, id, subtype in nextnode, tonut(n) do if id == hlist_code or id == vlist_code then - local s = getsubtype(n) - report_nodes(rep(symbol,depth) .. what[s] or s) + report_nodes(rep(symbol,depth) .. what[subtype] or subtype) showboxes(getlist(n),symbol,depth+1) end end @@ -401,17 +428,17 @@ local function nodetodimen(n) width = width / 65536 if stretch_order ~= 0 then if shrink_order ~= 0 then - return f_f_f(width,stretch,fillorders[stretch_order],shrink,fillorders[shrink_order]) + return f_f_f(width,stretch,fillcodes[stretch_order],shrink,fillcodes[shrink_order]) elseif shrink ~= 0 then - return f_f_m(width,stretch,fillorders[stretch_order],shrink) + return f_f_m(width,stretch,fillcodes[stretch_order],shrink) else - return f_f_z(width,stretch,fillorders[stretch_order]) + return f_f_z(width,stretch,fillcodes[stretch_order]) end elseif shrink_order ~= 0 then if stretch ~= 0 then - return f_p_f(width,stretch,shrink,fillorders[shrink_order]) + return f_p_f(width,stretch,shrink,fillcodes[shrink_order]) else - return f_z_f(width,shrink,fillorders[shrink_order]) + return f_z_f(width,shrink,fillcodes[shrink_order]) end elseif stretch ~= 0 then if shrink ~= 0 then @@ -631,6 +658,9 @@ end tracers.setproperties = setproperties +-- setting attrlist entries instead of attr for successive entries doesn't +-- speed up much (this function is only used in tracers anyway) + function tracers.setlist(n,c,s) local nn = tonut(n) local mc = m_color[c] diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua index 1ce7ab1dc85..0378c14c62a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-tsk.lua @@ -52,19 +52,21 @@ end function tasks.new(specification) -- was: name,arguments,list local name = specification.name - local arguments = specification.arguments or 0 local sequence = specification.sequence if name and sequence then local tasklist = newsequencer { + name = name -- we can move more to the sequencer now .. todo } tasksdata[name] = { + name = name, list = tasklist, runner = false, - arguments = arguments, - -- sequence = sequence, frozen = { }, - processor = specification.processor or nodeprocessor + processor = specification.processor or nodeprocessor, + -- could be metatable but best freeze it + arguments = specification.arguments or 0, + templates = specification.templates, } for l=1,#sequence do appendgroup(tasklist,sequence[l]) @@ -170,18 +172,26 @@ function tasks.disablegroup(name,group) end end -function tasks.appendaction(name,group,action,where,kind) +function tasks.appendaction(name,group,action,where,kind,state) local data = validgroup(name,"append action") if data then - appendaction(data.list,group,action,where,kind) + local list = data.list + appendaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end data.runner = false end end -function tasks.prependaction(name,group,action,where,kind) +function tasks.prependaction(name,group,action,where,kind,state) local data = validgroup(name,"prepend action") if data then - prependaction(data.list,group,action,where,kind) + local list = data.list + prependaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end data.runner = false end end @@ -216,112 +226,29 @@ statistics.register("node list callback tasks", function() end end) -function tasks.actions(name) -- we optimize for the number or arguments (no ...) +local function create(data,t) + created = created + 1 + local runner = compile(data.list,data.processor,t) + if trace_tasks then + report_tasks("creating runner %a, %i actions enabled",t.name,data.list.steps or 0) + end + data.runner = runner + return runner +end + +function tasks.actions(name) local data = tasksdata[name] if data then - local n = data.arguments or 0 - if n == 0 then - return function(head) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a",name) - end - runner = compile(data.list,data.processor,0) - data.runner = runner - end - return runner(head) - end - elseif n == 1 then - return function(head,one) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,1) - end - runner = compile(data.list,data.processor,1) - data.runner = runner - end - return runner(head,one) - end - elseif n == 2 then - return function(head,one,two) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,2) - end - runner = compile(data.list,data.processor,2) - data.runner = runner - end - return runner(head,one,two) - end - elseif n == 3 then - return function(head,one,two,three) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,3) - end - runner = compile(data.list,data.processor,3) - data.runner = runner - end - return runner(head,one,two,three) - end - elseif n == 4 then - return function(head,one,two,three,four) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,4) - end - runner = compile(data.list,data.processor,4) - data.runner = runner - end - return runner(head,one,two,three,four) - end - elseif n == 5 then - return function(head,one,two,three,four,five) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,5) - end - runner = compile(data.list,data.processor,5) - data.runner = runner - end - return runner(head,one,two,three,four,five) - end - else - return function(head,...) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,n) - end - runner = compile(data.list,data.processor,"n") - data.runner = runner - end - return runner(head,...) + local t = data.templates + if t then + t.name = data.name + return function(...) + total = total + 1 + return (data.runner or create(data,t))(...) end end - else - return nil end + return nil end function tasks.table(name) --maybe move this to task-deb.lua @@ -351,12 +278,132 @@ function tasks.table(name) --maybe move this to task-deb.lua end end --- this will move +-- -- shipouts everypar -- -- + +-- the shipout handlers acts on boxes so we don't need to return something +-- and also don't need to keep the state (done) + +local templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + +} + +tasks.new { + name = "shipouts", + processor = nodeprocessor, + sequence = { + "before", -- users + "normalizers", -- system + "finishers", -- system + "after", -- users + "wrapup", -- system + }, + templates = templates +} + +tasks.new { + name = "everypar", + processor = nodeprocessor, + sequence = { + "before", -- users + "normalizers", -- system + "after", -- users + }, + templates = templates, +} + +-- -- finalizers -- -- + +tasks.new { + name = "finalizers", + sequence = { + "before", -- for users + "normalizers", + "fonts", + "lists", + "after", -- for users + }, + processor = nodeprocessor, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + + } +} + +-- -- processors -- -- tasks.new { name = "processors", - arguments = 5, -- often only the first is used, and the last three are only passed in hpack filter --- arguments = 2, processor = nodeprocessor, sequence = { "before", -- for users @@ -366,56 +413,297 @@ tasks.new { "fonts", "lists", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,direction,attributes) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,direction,attributes))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,direction,attributes) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + } } tasks.new { name = "finalizers", - arguments = 1, processor = nodeprocessor, sequence = { "before", -- for users "normalizers", --- "characters", --- "finishers", "fonts", "lists", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + } } tasks.new { - name = "shipouts", - arguments = 1, - -- nostate = true, -- maybe but only for main ones so little gain + name = "mvlbuilders", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", - "finishers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + } } tasks.new { - name = "mvlbuilders", - arguments = 1, + name = "vboxbuilders", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,maxdepth,direction) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + } + } tasks.new { - name = "vboxbuilders", - arguments = 5, + name = "contributers", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,line) + local nuthead = tonut(head) + local nutline = tonut(line) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,line))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,nutline) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,line) +]], + +nonut = [[ + %action%(nuthead,groupcode,nutline) +]], + + } +} + +-- -- math -- -- + +tasks.new { + name = "math", + processor = nodeprocessor, + sequence = { + "before", + "normalizers", + "builders", + "after", + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,style,penalties) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),style,penalties))) +]], + +nut = [[ + nuthead = %action%(nuthead,style,penalties) +]], + +nohead = [[ + %action%(tonode(nuthead),style,penalties) +]], + +nonut = [[ + %action%(nuthead,style,penalties) +]], + } } @@ -441,14 +729,69 @@ tasks.new { -- } -- } -tasks.new { - name = "contributers", - arguments = 2, -- [head] where parent - processor = nodeprocessor, - sequence = { - "before", -- for users - "normalizers", - "after", -- for users - } -} +-- for now quite useless (too fuzzy) +-- +-- tasks.new { +-- name = "listbuilders", +-- processor = nodeprocessor, +-- sequence = { +-- "before", -- for users +-- "normalizers", +-- "after", -- for users +-- }, +-- templates = { +-- -- we don't need a default +-- default = [[ +-- return function(box,location,prevdepth) +-- return box, prevdepth +-- end +-- ]], +-- process = [[ +-- %localize% +-- return function(box,location,prevdepth,mirrored) +-- %actions% +-- return box, prevdepth +-- end +-- ]], +-- step = [[ +-- box, prevdepth = %action%(box,location,prevdepth,mirrored) +-- ]], +-- }, +-- } + +-- -- math -- -- + +-- not really a node processor +-- tasks.new { +-- name = "newpar", +-- processor = nodeprocessor, +-- sequence = { +-- "before", +-- "normalizers", +-- "after", +-- }, +-- templates = { +-- +-- default = [[ +-- return function(mode,indent) +-- return indent +-- end +-- ]], +-- +-- process = [[ +-- %localize% +-- +-- return function(mode,indent) +-- +-- %actions% +-- return indent +-- end +-- ]], +-- +-- step = [[ +-- indent = %action%(mode,indent) +-- ]], +-- +-- } +-- } diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua b/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua index 7ad35bd711e..0dacff37532 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-tst.lua @@ -10,7 +10,7 @@ local nodes, node = nodes, node local chardata = characters.data local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local glue_code = nodecodes.glue local penalty_code = nodecodes.penalty @@ -19,10 +19,10 @@ local glyph_code = nodecodes.glyph local whatsit_code = nodecodes.whatsit local hlist_code = nodecodes.hlist -local leftskip_code = skipcodes.leftskip -local rightskip_code = skipcodes.rightskip -local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip -local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip +local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip +local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip local nuts = nodes.nuts diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv index 06eeebd1411..b67d6f14b28 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-bar.mkiv @@ -72,16 +72,16 @@ \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} \unexpanded\def\horizontalgrowingbar[#1]% - {\hbox to \hsize + {\hpack to \hsize {\setuppositionbar[#1]% \usepositionbarstyleandcolor\c!style\c!color - \leaders\vrule\hskip\zeropoint\s!plus \numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill + \leaders\vrule\hskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill \vrule\s!width\zeropoint\s!height\positionbarparameter\c!height\s!depth\positionbarparameter\c!depth \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}} \unexpanded\def\verticalgrowingbar[#1]% - {\vbox to \vsize + {\vpack to \vsize {\setuppositionbar[#1]% \usepositionbarstyleandcolor\c!style\c!color \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi b/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi index 346e7df575e..9f9d843cef7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-bck.mkvi @@ -245,18 +245,42 @@ %D \macros %D {backgroundline} -\unexpanded\def\backgroundline[#color]% - {\dontleavehmode - \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox} +% \unexpanded\def\backgroundline[#color]% +% {\dontleavehmode +% \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox} +% +% \unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper +% {\hpack +% {\dousecolorparameter{#color}% +% \vrule +% \??width \nextboxwd +% \??height\nextboxht +% \??depth \nextboxdp +% \hskip-\nextboxwd +% \flushnextbox}} + +%D We implement this elsewhere avoiding the rule. -\unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper - {\hbox - {\dousecolorparameter{#color}% - \vrule - \!!width \nextboxwd - \!!height\nextboxht - \!!depth \nextboxdp - \hskip-\nextboxwd - \flushnextbox}} +% \unexpanded\def\backgroundline +% {\dontleavehmode +% \pack_backgrounds_add_to_nextbox\hbox\hpack} +% +% \unexpanded\def\pack_backgrounds_add_to_nextbox#box#pack[#color]% +% {\dontleavehmode +% \dowithnextbox{\pack_backgrounds_add_to_nextbox_indeed#pack{#color}}#box} +% +% \unexpanded\def\pack_backgrounds_add_to_nextbox_indeed#pack#color% handy helper +% {#pack% +% {\dousecolorparameter{#color}% +% \vrule +% \??width \nextboxwd +% \??height\nextboxht +% \??depth \nextboxdp +% \hskip-\nextboxwd +% \flushnextbox}} +% +% \unexpanded\def\backgroundhbox{\pack_backgrounds_add_to_nextbox\hbox\hpack} +% \unexpanded\def\backgroundvtop{\pack_backgrounds_add_to_nextbox\vtop\tpack} +% \unexpanded\def\backgroundvbox{\pack_backgrounds_add_to_nextbox\vbox\vpack} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv index c53b4520ce6..bf6d4662dac 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-box.mkiv @@ -108,6 +108,7 @@ {\global\advance\c_pack_anchors_n\plusone \pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]% \putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors +% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}% \doglobal\appendetoks \pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}% \to \t_pack_anchors_flush diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv index 59354208e13..1c6f2de7361 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-com.mkiv @@ -73,7 +73,7 @@ \newsystemmode{combination} \appendtoks - \global\resetsystemmode{combination}% + \globalresetsystemmode{combination}% \to \everyinsidefloat \newcount\c_pack_combinations_nesting % local @@ -113,7 +113,7 @@ \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption \else - \global\setsystemmode{combination}% why global + \globalsetsystemmode{combination}% why global \fi} \def\pack_combinations_pop @@ -126,7 +126,7 @@ \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved \else - \global\resetsystemmode{combination}% why global + \globalresetsystemmode{combination}% why global \fi \advance\c_pack_combinations_nesting\minusone} @@ -205,7 +205,7 @@ % {\bgroup % \scratchtoks{{}}% % \dorecurse\c_pack_combinations_y -% {\scratchtoks\expandafter{\the\scratchtoks{}{}}}% +% {\toksapp{{}{}}}% % \expandafter\egroup\the\scratchtoks % \egroup % \dostoptagged @@ -290,7 +290,7 @@ \alignmark\alignmark \m_pack_combinations_rightfiller \aligntab - \tabskip\zeropoint \s!plus 1fill + \tabskip\zeropoint \s!plus 1fill % \fillskip \alignmark\alignmark \cr \pack_combinations_pickup} @@ -437,10 +437,10 @@ \nointerlineskip % indeed \combinationparameter\c!inbetween \global\c_pack_combinations_x\c_pack_combinations_max - \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes \else \global\setbox\b_pack_combinations_captions\emptybox - \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop \fi}% \pack_combinations_flush_captions_indeed \crcr} @@ -656,7 +656,7 @@ \newsystemmode{pairedbox} \appendtoks - \global\resetsystemmode{pairedbox}% + \globalresetsystemmode{pairedbox}% \to \everyinsidefloat \installcorenamespace {pairedbox} @@ -720,7 +720,7 @@ \let\startcaption\pack_common_caption_start \let\stopcaption \pack_common_caption_stop % - \global\setsystemmode{pairedbox}% + \globalsetsystemmode{pairedbox}% \pack_pairedboxes_before \assumelongusagecs\pack_pairedboxes_first_pickup} diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv index ffd0251d5ae..84c14d648e5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-cut.mkiv @@ -65,85 +65,87 @@ \def\cutmarkrulethickness{\onepoint} \unexpanded\def\horizontalcuts - {\normalhbox to \d_pack_cutmarks_width - {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\normalhfill}% + {\hpack to \d_pack_cutmarks_width + {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\hfill}% \unskip}} \unexpanded\def\verticalcuts - {\normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + {\vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax {\hsize\cutmarklength - \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\normalvfill}% + \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\vfill}% \unskip}} \unexpanded\def\baselinecuts {\ifdim\d_pack_cutmarks_depth>\zeropoint - \normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax + \vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax {\hsize\dimexpr\cutmarklength/2\relax - \normalvskip\zeropoint\s!plus\d_pack_cutmarks_height + \vskip\zeropoint\s!plus\d_pack_cutmarks_height \vrule\s!height\cutmarkrulethickness\s!width\hsize - \normalvskip\zeropoint\s!plus\d_pack_cutmarks_depth}% + \vskip\zeropoint\s!plus\d_pack_cutmarks_depth}% \fi} \unexpanded\def\cutmarksymbols#1% - {\normalhbox to \d_pack_cutmarks_width - {\setbox\scratchbox\normalhbox to \cutmarklength - {\normalhss\infofont\cutmarksymbol\normalhss}% - \normalhss - \normalvbox to \cutmarklength + {\hpack to \d_pack_cutmarks_width + {\setbox\scratchbox\hbox to \cutmarklength + {\hss\infofont\cutmarksymbol\hss}% + \hss + \vpack to \cutmarklength {\scratchdimen\dimexpr\cutmarklength/2\relax \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi - \normalvss - \hpack to \d_pack_cutmarks_width - {\llap{\copy\scratchbox\normalhskip\scratchskip}% - \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen - \rlap{\normalhskip\scratchskip\copy\scratchbox}}% - \normalvss}% - \normalhss}} + \vss + \hbox to \d_pack_cutmarks_width + {\llap{\copy\scratchbox\hskip\scratchskip}% + \hskip\scratchdimen\hss + \infofont#1% + \hss\hskip\scratchdimen + \rlap{\hskip\scratchskip\copy\scratchbox}}% + \vss}% + \hss}} \unexpanded\def\makecutbox#1% {\bgroup \d_pack_cutmarks_height\ht#1% \d_pack_cutmarks_depth \dp#1% \d_pack_cutmarks_width \wd#1% - \setbox#1\normalhbox + \setbox#1\hpack {\dontcomplain \forgetall \boxmaxdepth\maxdimen \offinterlineskip \scratchdimen\dimexpr\cutmarklength/2\relax \hsize\d_pack_cutmarks_width - \setbox\scratchbox\normalvbox - {\setbox\scratchbox\normalhbox{\horizontalcuts}% + \setbox\scratchbox\vpack + {\setbox\scratchbox\hpack{\horizontalcuts}% \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi - \tlap{\copy\scratchbox\normalvskip\scratchskip}% + \tlap{\copy\scratchbox\vskip\scratchskip}% \hpack to \d_pack_cutmarks_width {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi - \setbox\scratchbox\normalhbox{\verticalcuts}% - \llap{\copy\scratchbox\normalhskip\scratchskip}% + \setbox\scratchbox\hpack{\verticalcuts}% + \llap{\copy\scratchbox\hskip\scratchskip}% \ifdim\d_pack_cutmarks_depth=\zeropoint - \normalhfill + \hfill \else \bgroup - \setbox\scratchbox\normalhbox{\baselinecuts}% - \llap{\copy\scratchbox\normalhskip\scratchskip}% - \normalhfill - \rlap{\normalhskip\scratchskip\copy\scratchbox}% + \setbox\scratchbox\hpack{\baselinecuts}% + \llap{\copy\scratchbox\hskip\scratchskip}% + \hfill + \rlap{\hskip\scratchskip\copy\scratchbox}% \egroup \fi - \rlap{\normalhskip\scratchskip\copy\scratchbox}}% - \blap{\normalvskip\scratchskip\copy\scratchbox}}% + \rlap{\hskip\scratchskip\copy\scratchbox}}% + \blap{\vskip\scratchskip\copy\scratchbox}}% \ht\scratchbox\d_pack_cutmarks_height \dp\scratchbox\d_pack_cutmarks_depth \wd\scratchbox\zeropoint \startcolor[\defaulttextcolor]% \box\scratchbox \ifx\cutmarksymbol\relax \else - \setbox\scratchbox\normalvbox + \setbox\scratchbox\vpack {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi \vskip-\dimexpr\scratchskip+\cutmarklength\relax - \normalhbox{\cutmarksymbols\cutmarktoptext}% + \hpack{\cutmarksymbols\cutmarktoptext}% \vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax - \normalhbox{\cutmarksymbols\cutmarkbottomtext}}% + \hpack{\cutmarksymbols\cutmarkbottomtext}}% \ht\scratchbox\d_pack_cutmarks_height \dp\scratchbox\d_pack_cutmarks_depth \wd\scratchbox\zeropoint @@ -156,8 +158,8 @@ \dp#1\d_pack_cutmarks_depth \egroup} -\unexpanded\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox} -\unexpanded\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox} -\unexpanded\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop} +\unexpanded\def\cuthbox{\hpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\hbox} +\unexpanded\def\cutvbox{\vpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vbox} +\unexpanded\def\cutvtop{\tpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vtop} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv index 8661fe57a5e..e7070cfdec1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-lyr.mkiv @@ -293,8 +293,8 @@ {\setbox\b_layers\emptybox \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax - \globallet\lastlayerxpos\!!zeropoint - \globallet\lastlayerypos\!!zeropoint + \glet\lastlayerxpos\!!zeropoint + \glet\lastlayerypos\!!zeropoint \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions @@ -540,24 +540,85 @@ % todo: pass the layer with \lastnamedcs +% \def\pack_layers_flush_single +% {\startoverlay +% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% +% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}% +% \stopoverlay} +% +% \def\pack_layers_flush_double#1% +% {\startoverlay +% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% +% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}% +% {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}% +% {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}% +% \stopoverlay} + +% optimized: + \def\pack_layers_flush_single - {\startoverlay - {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% - {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}% - \stopoverlay} + {\ifcsname\??layerbox\currentlayer\endcsname + \ifvoid\lastnamedcs + \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else + \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi + \else + \chardef\b_layer_one\lastnamedcs + \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs\else + \chardef\b_layer_two\lastnamedcs + \startoverlay + {\pack_layers_flush_indeed\plusone \currentlayer \b_layer_one}% + {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}% + \stopoverlay + \fi + \else + \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one + \fi + \fi + \else\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcs + % nothing + \else + \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi\fi} + +% less optimized: \def\pack_layers_flush_double#1% {\startoverlay - {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% - {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}% - {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}% - {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}% + {\ifcsname\??layerbox\currentlayer\endcsname + \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox#1\currentlayer\endcsname + \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two + \fi + \fi}% + {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname + \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs + \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two + \fi + \fi}% \stopoverlay} \let\pack_layers_top_fill \relax \let\pack_layers_bottom_fill\vss -\def\pack_layers_flush_indeed#1#2% quite core, so optimized +%def\pack_layers_flush_indeed#1#2% +\def\pack_layers_flush_indeed#1#2#3% {\begingroup % already grouped \offinterlineskip \edef\p_pack_layers_preset{\layerparameter\c!preset}% @@ -587,7 +648,8 @@ \fi\fi \fi \fi - \chardef\b_layers\csname\??layerbox#2\endcsname % trick + %chardef\b_layers\csname\??layerbox#2\endcsname % trick + \let\b_layers#3% % we need to copy in order to retain the negative offsets for a next % stage of additions, i.e. llx/lly accumulate in repeat mode and the % compensation may differ each flush depending on added content diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv index 85aa3ad04ed..665d245b346 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-mrl.mkiv @@ -39,7 +39,7 @@ \installsimplecommandhandler \??blackrules {blackrules} \unexpanded\def\blackrule - {\hbox\bgroup + {\hpack\bgroup \doifelsenextoptionalcs\pack_black_rule_pickup\pack_black_rule_indeed} \def\pack_black_rule_pickup[#1]% @@ -99,7 +99,7 @@ %D would probably have taken more tokens. \unexpanded\def\blackrules % probably never used - {\hbox\bgroup + {\hpack\bgroup \doifelsenextoptionalcs\pack_black_rules_pickup\pack_black_rules_indeed} \def\pack_black_rules_pickup[#1]% @@ -121,23 +121,25 @@ \fi \fi \useblackrulesstyleandcolor\c!style\c!color - \edef\brule - {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname - \lastnamedcs - \else - \vrule - \fi}% - \dorecurse\scratchcounter % a typical case of where we can use a simple loop - {\brule - \s!width \scratchwidth - \s!height\scratchheight - \s!depth \scratchdepth - \ifzeropt\scratchdistance\else - \hskip\scratchdistance - \fi}% + % a typical case of where we can use a simple loop or even a leaders + \dorecurse\scratchcounter\pack_black_rules_step \unskip \egroup} +\def\pack_black_rules_step + {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname + \lastnamedcs + \else + \vrule + \fi + \s!width \scratchwidth + \s!height\scratchheight + \s!depth \scratchdepth + \relax + \ifzeropt\scratchdistance\else + \hskip\scratchdistance + \fi} + \installcorenamespace{blackruletype} \setvalue{\??blackruletype mp}% @@ -578,7 +580,7 @@ {\page[\v!preference] % interferes \directtextrulesparameter\c!before\relax \blank[\v!samepage,\v!nowhite]% - \pack_textrule_with_text{#1}% + \pack_textrule_with_text_yes{#1}% \blank[\v!samepage,\v!nowhite]% \directtextrulesparameter\c!inbetween\relax \endgraf} @@ -598,9 +600,10 @@ \directtextrulesparameter\c!inbetween\relax \page[\v!preference]} -\def\pack_textrule_with_text#1% - {\bgroup - \setbox\scratchbox\hbox to \availablehsize +\def\pack_textrule_with_text_yes#1% + {\noindent % this will force side floats to be calculated + \bgroup + \setbox\scratchbox\hpack to \availablehsize {\scratchwidth \directtextrulesparameter\c!rulethickness\relax \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax @@ -611,19 +614,41 @@ #1% \hskip\leftmargindistance}} {\color[\directtextrulesparameter\c!rulecolor] - {\vrule\s!height\scratchheight\s!depth\scratchdepth\s!width\directtextrulesparameter\c!width}% + {\vrule + \s!height\scratchheight + \s!depth \scratchdepth + \s!width \directtextrulesparameter\c!width}% \hbox spread 2\dimexpr\directtextrulesparameter\c!distance\relax {\hss \usetextrulesstyleandcolor\c!style\c!color \strut#1% \hss}}}% \color[\directtextrulesparameter\c!rulecolor] - {\leaders\hrule\s!height\scratchheight\s!depth\scratchdepth\hfill}}% + {\leaders\hrule + \s!height\scratchheight + \s!depth \scratchdepth + \hfill}}% \ht\scratchbox\strutht \dp\scratchbox\strutdp - \noindent\box\scratchbox + \box\scratchbox + %\carryoverpar \egroup} +\def\pack_textrule_with_text_nop#1% + {\ifhmode + \endgraf + \fi + \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on + \pack_textrule_correct_depth_yes + \pack_textrule_correct_depth_nop + \nointerlineskip + \noindent\vpack % was \dontleavehmode + {\color[\directtextrulesparameter\c!rulecolor] + {\hrule + \s!depth \directtextrulesparameter\c!rulethickness + \s!height\zeropoint + \s!width \availablehsize}}} + \def\pack_textrule_correct_depth_yes {\vskip\dimexpr \strutdp +.5\exheight @@ -643,15 +668,9 @@ \def\pack_textrule_following#1% {\doifelsenothing{#1} - {\ifhmode - \endgraf - \fi - \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on\pack_textrule_correct_depth_yes\pack_textrule_correct_depth_nop - \nointerlineskip - \noindent\vbox % was \dontleavehmode - {\color[\directtextrulesparameter\c!rulecolor] - {\hrule\s!depth\directtextrulesparameter\c!rulethickness\s!height\zeropoint\s!width\availablehsize}}} - {\pack_textrule_with_text{#1}}% + \pack_textrule_with_text_nop + \pack_textrule_with_text_yes + {#1}% \ifvmode \prevdepth\zeropoint \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua index 3f2b2edfeff..ea36b10de7a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.lua @@ -13,9 +13,11 @@ reusable components.

local context = context local codeinjections = backends.codeinjections - local ctx_doifelse = commands.doifelse +local report = logs.reporter("objects") +local trace = false trackers.register("objects",function(v) trace = v end) + local nuts = nodes.nuts local setlink = nuts.setlink @@ -26,10 +28,7 @@ local new_latelua = nuts.pool.latelua local settexdimen = tokens.setters.dimen -local gettexbox = tokens.getters.box -local settexbox = tokens.setters.box -local gettexdimen = tokens.getters.dimen -local gettexcount = tokens.getters.count +local getcount = tex.getcount local implement = interfaces.implement local setmacro = interfaces.setmacro @@ -54,8 +53,16 @@ end job.register('job.objects.collected', tobesaved, initializer, nil) local function saveobject(tag,number,page) - local t = { number, page } - tobesaved[tag], collected[tag] = t, t + local data = { number, page } + tobesaved[tag] = data + collected[tag] = data +end + +local function saveobjectspec(specification) + local tag = specification.tag + local data = { specification.number, specification.page } + tobesaved[tag] = data + collected[tag] = data end local function setobject(tag,number,page) @@ -128,8 +135,9 @@ objects = { local objects = objects function objects.register(ns,id,b,referenced,offset,mode) - objects.n = objects.n + 1 - nodes.handlers.finalize(gettexbox(b),"object") + local n = objects.n + 1 + objects.n = n + nodes.handlers.finalizebox(b) if mode == 0 then -- tex data[ns][id] = { @@ -147,6 +155,9 @@ function objects.register(ns,id,b,referenced,offset,mode) mode, } end + if trace then + report("registering object %a (n=%i)",id,n) + end end function objects.restore(ns,id) -- why not just pass a box number here too (ok, we also set offset) @@ -159,9 +170,12 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok, local hbox = codeinjections.restoreboxresource(index) -- a nut ! if status then local list = getlist(hbox) - local page = new_latelua(function() - saveobject(ns .. "::" .. id,index,gettexcount("realpageno")) - end) + local page = new_latelua { + action = saveobjectspec, + tag = ns .. "::" .. id, + number = index, + page = getcount("realpageno"), + } setlink(list,page) end setbox("objectbox",hbox) @@ -170,6 +184,9 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok, setbox("objectbox",nil) settexdimen("objectoff",0) -- for good old times end + if trace then + report("restoring object %a",id) + end end function objects.dimensions(index) @@ -191,7 +208,7 @@ function objects.reference(ns,id) end function objects.page(ns,id) - return getobjectpage(ns .."::" .. id,gettexcount("realpageno")) + return getobjectpage(ns .."::" .. id,getcount("realpageno")) end function objects.found(ns,id) diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv index aeb5cb4f412..d08c664944f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-obj.mkiv @@ -51,7 +51,8 @@ \newdimen\objectht \def\objectheight{\the\objectht} \newdimen\objectdp \def\objectdepth {\the\objectdp} -%D If I have time I will use the unreferenced variant for e.g. mp reuse. +%D If I have time I will use the unreferenced variant for e.g. mp reuse. This can be +%D rewritten in \LUA\ anyway. \unexpanded\def\setreferencedobject #1#2{\begingroup\synctexpause\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}} \unexpanded\def\settightreferencedobject #1#2{\begingroup\synctexpause\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}} @@ -65,14 +66,8 @@ \newconstant\c_pack_objects_offset_mode % 0=tex 1=box -\unexpanded\def\pack_objects_temp_check % this will go away - {\ifnum\texenginefunctionality<6401\relax - \c_pack_objects_offset_mode\zerocount - \fi} - \unexpanded\def\pack_objects_set_yes#1#2% - {\pack_objects_temp_check % this will go away - \ifcase\c_pack_objects_offset_mode + {\ifcase\c_pack_objects_offset_mode \ifzeropt\objectoff \pack_objects_package_nop\nextbox \else @@ -86,8 +81,7 @@ \endgroup} \unexpanded\def\pack_objects_set_nop#1#2% - {\pack_objects_temp_check % this will go away - \ifcase\c_pack_objects_offset_mode + {\ifcase\c_pack_objects_offset_mode \ifzeropt\objectoff \pack_objects_package_nop\nextbox \else diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua index c9771546c9b..455d0bff832 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.lua @@ -20,42 +20,50 @@ if not modules then modules = { } end modules ['pack-rul'] = { local type = type -local context = context - -local hlist_code = nodes.nodecodes.hlist -local vlist_code = nodes.nodecodes.vlist -local box_code = nodes.listcodes.box -local line_code = nodes.listcodes.line -local equation_code = nodes.listcodes.equation - -local texsetdimen = tex.setdimen -local texsetcount = tex.setcount - -local implement = interfaces.implement - -local nuts = nodes.nuts - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getlist = nuts.getlist -local setlist = nuts.setlist -local getwhd = nuts.getwhd -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox -local getdir = nuts.getdir -local setshift = nuts.setshift -local setwidth = nuts.setwidth -local getwidth = nuts.getwidth -local setboxglue = nuts.setboxglue -local getboxglue = nuts.getboxglue - -local hpack = nuts.hpack -local traverse_id = nuts.traverse_id -local list_dimensions = nuts.dimensions -local flush_node = nuts.flush - -local checkformath = false +local context = context + +local nodecodes = nodes.nodecodes +local listcodes = nodes.listcodes + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist + +local boxlist_code = listcodes.box +local linelist_code = listcodes.line +local equationlist_code = listcodes.equation + +local texsetdimen = tex.setdimen +local texsetcount = tex.setcount + +local implement = interfaces.implement + +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getlist = nuts.getlist +local setlist = nuts.setlist +local getwhd = nuts.getwhd +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getdirection = nuts.getdirection +local setshift = nuts.setshift +local setwidth = nuts.setwidth +local getwidth = nuts.getwidth +local setboxglue = nuts.setboxglue +local getboxglue = nuts.getboxglue + +local hpack = nuts.hpack +local getdimensions = nuts.dimensions +local flush_node = nuts.flush + +local traversers = nuts.traversers +local nexthlist = traversers.hlist +local nextvlist = traversers.vlist +local nextlist = traversers.list + +local checkformath = false directives.register("framed.checkmath",function(v) checkformath = v end) -- experiment @@ -76,24 +84,25 @@ local function doreshapeframedbox(n) if boxwidth ~= 0 then -- and h.subtype == vlist_code local list = getlist(box) if list then - local function check(n,repack) + local hdone = false + for n, id, subtype, list in nextlist, list do -- no dir etc needed local width, height, depth = getwhd(n) if not firstheight then firstheight = height end lastdepth = depth noflines = noflines + 1 - local l = getlist(n) - if l then - if repack then - local subtype = getsubtype(n) - if subtype == box_code or subtype == line_code then - lastlinelength = list_dimensions(l,getdir(n)) + if list then + if id == hlist_code then + if subtype == boxlist_code or subtype == linelist_code then + lastlinelength = getdimensions(list) else lastlinelength = width end + hdone = true else lastlinelength = width + -- vdone = true end if lastlinelength > maxwidth then maxwidth = lastlinelength @@ -107,31 +116,19 @@ local function doreshapeframedbox(n) totalwidth = totalwidth + lastlinelength end end - local hdone = false - for h in traverse_id(hlist_code,list) do -- no dir etc needed - check(h,true) - hdone = true - end - -- local vdone = false - for v in traverse_id(vlist_code,list) do -- no dir etc needed - check(v,false) - -- vdone = true - end if not firstheight then -- done) elseif maxwidth ~= 0 then if hdone then - for h in traverse_id(hlist_code,list) do - local l = getlist(h) - if l then - local subtype = getsubtype(h) - if subtype == box_code or subtype == line_code then - local p = hpack(l,maxwidth,'exactly',getdir(h)) -- multiple return value + for h, id, subtype, list in nextlist, list do + if list and id == hlist_code then + if subtype == boxlist_code or subtype == linelist_code then + local p = hpack(list,maxwidth,'exactly',getdirection(h)) -- multiple return value local set, order, sign = getboxglue(p) setboxglue(h,set,order,sign) setlist(p) flush_node(p) - elseif checkformath and subtype == equation_code then + elseif checkformath and subtype == equationlist_code then -- display formulas use a shift if nofnonzero == 1 then setshift(h,0) @@ -142,7 +139,7 @@ local function doreshapeframedbox(n) end end -- if vdone then - -- for v in traverse_id(vlist_code,list) do + -- for v in nextvlist, list do -- local width = getwidth(n) -- if width > maxwidth then -- setwidth(v,maxwidth) @@ -164,7 +161,7 @@ local function doreshapeframedbox(n) texsetdimen("global","framedaveragewidth",averagewidth) end -local function doanalyzeframedbox(n) +local function doanalyzeframedbox(n) -- traverse_list local box = getbox(n) local noflines = 0 local firstheight = nil @@ -172,7 +169,7 @@ local function doanalyzeframedbox(n) if getwidth(box) ~= 0 then local list = getlist(box) if list then - local function check(n) + for n in nexthlist, list do local width, height, depth = getwhd(n) if not firstheight then firstheight = height @@ -180,11 +177,13 @@ local function doanalyzeframedbox(n) lastdepth = depth noflines = noflines + 1 end - for h in traverse_id(hlist_code,list) do - check(h) - end - for v in traverse_id(vlist_code,list) do - check(v) + for n in nextvlist, list do + local width, height, depth = getwhd(n) + if not firstheight then + firstheight = height + end + lastdepth = depth + noflines = noflines + 1 end end end @@ -210,16 +209,11 @@ local function maxboxwidth(box) end local lastlinelength = 0 local maxwidth = 0 - local function check(n,repack) + for n, subtype in nexthlist, list do -- no dir etc needed local l = getlist(n) if l then - if repack then - local subtype = getsubtype(n) - if subtype == box_code or subtype == line_code then - lastlinelength = list_dimensions(l,getdir(n)) - else - lastlinelength = getwidth(n) - end + if subtype == boxlist_code or subtype == linelist_code then + lastlinelength = getdimensions(l) else lastlinelength = getwidth(n) end @@ -228,11 +222,14 @@ local function maxboxwidth(box) end end end - for h in traverse_id(hlist_code,list) do -- no dir etc needed - check(h,true) - end - for v in traverse_id(vlist_code,list) do -- no dir etc needed - check(v,false) + for n, subtype in nextvlist, list do -- no dir etc needed + local l = getlist(n) + if l then + lastlinelength = getwidth(n) + if lastlinelength > maxwidth then + maxwidth = lastlinelength + end + end end return maxwidth end diff --git a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv index c208baaf014..3d03942aab2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/pack-rul.mkiv @@ -18,7 +18,7 @@ %D packaging and expansion we also keep tracing reasonable. For instance, multiple %D stacked backgrounds can slow down a run if not optimized this way. -\registerctxluafile{pack-rul}{} +\registerctxluafile{pack-rul}{optimize} \unprotect @@ -141,6 +141,7 @@ \setupframed [\c!width=\v!fit, \c!height=\v!broad, + %\c!minheight=\zeropoint, %\c!lines=, \c!offset=.25\exheight, % \defaultframeoffset \c!empty=\v!no, @@ -239,7 +240,6 @@ \let\p_framed_backgroundcolor \empty \let\p_framed_framecolor \empty \let\p_framed_component \empty -\let\p_framed_region \empty \let\p_framed_background \empty \let\p_framed_rulethickness \empty \let\p_framed_foregroundcolor \empty @@ -443,6 +443,8 @@ \newdimen\d_overlay_offset \newdimen\d_overlay_linewidth +\let\m_overlay_region\empty + % expandable ... in a future version the space will go (in my one can use Overlay*) \def\overlaywidth {\the\d_overlay_width \space} % We preset the variables @@ -450,6 +452,7 @@ \def\overlaydepth {\the\d_overlay_depth \space} % values. \def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) \def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. +\def\overlayregion {\m_overlay_region} % public but kind of protected @@ -553,40 +556,36 @@ \def\pack_framed_process_background_indeed_internal#1% % : in name {\bgroup - \setbox\b_framed_extra\hbox{%\bgroup - \ifzeropt\framedbackgroundoffset - %\csname\??overlaybuiltin\m_framed_background\endcsname - #1 - \else + \setbox\b_framed_extra\hpack\bgroup + \ifzeropt\framedbackgroundoffset\else \kern-\framedbackgroundoffset - %\hbox{\csname\??overlaybuiltin\m_framed_background\endcsname}% - \hbox{#1}% \fi - }%\egroup + \hbox\bgroup#1\egroup + \egroup \wd\b_framed_extra\zeropoint \ht\b_framed_extra\framedbackgroundheight \dp\b_framed_extra\framedbackgrounddepth \box\b_framed_extra \egroup} -\def\pack_framed_process_background_indeed_external#1% +% \def\pack_framed_process_background_indeed_external#1% +% {\pack_framed_overlay_initialize +% \bgroup +% \setbox\b_framed_extra\hpack\bgroup +% \ifzeropt\framedbackgroundoffset\else +% \kern-\framedbackgroundoffset +% \fi +% \hbox\bgroup#1\egroup +% \egroup +% \wd\b_framed_extra\zeropoint +% \ht\b_framed_extra\framedbackgroundheight +% \dp\b_framed_extra\framedbackgrounddepth +% \box\b_framed_extra +% \egroup} + +\def\pack_framed_process_background_indeed_external {\pack_framed_overlay_initialize - \bgroup - \setbox\b_framed_extra\hbox{%\bgroup - \ifzeropt\framedbackgroundoffset - %\csname\??overlay\m_framed_background\endcsname - #1% - \else - \kern-\framedbackgroundoffset - %\hbox{\csname\??overlay\m_framed_background\endcsname}% - \hbox{#1}% - \fi - }%\egroup - \wd\b_framed_extra\zeropoint - \ht\b_framed_extra\framedbackgroundheight - \dp\b_framed_extra\framedbackgrounddepth - \box\b_framed_extra - \egroup} + \pack_framed_process_background_indeed_internal} \def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground) {\edef\m_framed_background{#1}% @@ -606,15 +605,23 @@ \def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise {\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight -\def\pack_framed_add_region % experiment - {\ifx\p_framed_region\v!yes - \anch_mark_region_box\b_framed_normal - \else - \anch_mark_tagged_box\b_framed_normal\p_framed_region +\def\pack_framed_set_region % experiment + {\ifx\m_overlay_region\v!yes + \edef\m_overlay_region{\reservedautoregiontag}% \fi} +% \def\pack_framed_add_region % experiment +% {\ifx\m_overlay_region\v!yes +% \anch_mark_region_box\b_framed_normal +% \else +% \anch_mark_tagged_box\b_framed_normal\m_overlay_region +% \fi} + +\def\pack_framed_add_region % experiment + {\anch_mark_tagged_box\b_framed_normal\m_overlay_region} + \def\pack_framed_add_background - {\setbox\b_framed_normal\hbox % was vbox % see also *1* + {\setbox\b_framed_normal\hpack % was vbox % see also *1* {%\pack_framed_forgetall % can be relaxed \boxmaxdepth\maxdimen \framedbackgroundoffset\d_framed_backgroundoffset @@ -631,7 +638,7 @@ \setlayoutcomponentattribute{\v!background:\p_framed_component}% \fi \let\foregroundbox\pack_framed_background_box_content - \hbox \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay + \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay \the\everybackgroundbox % moved \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it \box\b_framed_normal @@ -692,10 +699,10 @@ \scratchdimen\zeropoint \fi \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background - \setbox\b_framed_extra\hbox + \setbox\b_framed_extra\hpack {\kern-\d_framed_frameoffset \raise\scratchdimen - \hbox{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}% + \hpack{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}% \wd\b_framed_extra\wd\b_framed_normal \ht\b_framed_extra\ht\b_framed_normal \dp\b_framed_extra\dp\b_framed_normal @@ -724,26 +731,45 @@ % \dp\scratchbox\d_framed_target_dp % \box\scratchbox} -\def\pack_framed_stroked_box_normal +\def\pack_framed_stroked_box_normal_opened {\setbox\scratchbox\vpack \bgroup - \csname \??framedtop\p_framed_frame\framedparameter\c!topframe \endcsname + \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname \nointerlineskip % new (needed for fences) - \hbox \bgroup - \csname \??framedleft\p_framed_frame\framedparameter\c!leftframe \endcsname + \hpack \bgroup + \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname \novrule \s!width \d_framed_target_wd \s!height\d_framed_target_ht \s!depth \d_framed_target_dp - \csname \??framedright\p_framed_frame\framedparameter\c!rightframe \endcsname + \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname \egroup \nointerlineskip % new (needed for fences) - \csname \??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname + \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname \egroup \wd\scratchbox\d_framed_target_wd \ht\scratchbox\d_framed_target_ht \dp\scratchbox\d_framed_target_dp \box\scratchbox} +\def\pack_framed_stroked_box_normal_closed + {\hpack\bgroup + \scratchdimen.5\d_framed_linewidth + \hskip\scratchdimen + \clf_framedoutline + \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax + \dimexpr\d_framed_target_ht-\scratchdimen\relax + \dimexpr\d_framed_target_dp-\scratchdimen\relax + \d_framed_linewidth + \relax + \egroup} + +\def\pack_framed_stroked_box_normal + {\ifx\p_framed_frame\v!closed + \pack_framed_stroked_box_normal_closed + \else + \pack_framed_stroked_box_normal_opened + \fi} + \def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth} \def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth} \def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth} @@ -836,7 +862,7 @@ %D for passing this identifier between brackets lays in the mere fact that this way %D we can use the optional argument grabbers. -\def\defaultframeoffset{.25ex} +\def\defaultframeoffset{.25\exheight} \installcorenamespace{regularframedlevel} @@ -999,9 +1025,11 @@ \edef\currentframed{#1}% \pack_framed_initialize \setbox\b_framed_normal\hbox{#4}% - \edef\p_framed_region{\framedparameter\c!region}% - \ifx\p_framed_region\v!yes % maybe later named - \pack_framed_add_region + \iftrialtypesetting \else + \edef\m_overlay_region{\framedparameter\c!region}% + \ifx\m_overlay_region\empty\else + \pack_framed_set_region + \fi \fi \setupcurrentframed[#3]% \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds @@ -1028,6 +1056,11 @@ \pack_framed_add_background \fi \pack_framed_restore_depth + \iftrialtypesetting \else + \ifx\m_overlay_region\empty\else + \pack_framed_add_region + \fi + \fi \box\b_framed_normal \egroup} @@ -1036,9 +1069,9 @@ \unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2 - \edef\p_framed_region{\framedparameter\c!region}% - \ifx\p_framed_region\empty\else - \pack_framed_add_region + \edef\m_overlay_region{\framedparameter\c!region}% + \ifx\m_overlay_region\empty\else + \pack_framed_set_region \fi \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds @@ -1061,6 +1094,9 @@ \edef\p_framed_component{#1}% \pack_framed_add_background \fi + \ifx\m_overlay_region\empty\else + \pack_framed_add_region + \fi \box\b_framed_normal \egroup} @@ -1602,6 +1638,13 @@ \fi \ifconditional\c_framed_has_height \ht\b_framed_normal\d_framed_height + \else + \edef\p_framed_minheight{\framedparameter\c!minheight}% + \ifx\p_framed_minheight\empty \else + \ifdim\ht\b_framed_normal<\p_framed_minheight + \ht\b_framed_normal\p_framed_minheight + \fi + \fi \fi \edef\p_framed_empty{\framedparameter\c!empty}% \ifx\p_framed_empty\v!yes @@ -1609,9 +1652,9 @@ \fi \pack_framed_stop_orientation % moved here at 2014-05-25 \iftrialtypesetting \else - \edef\p_framed_region{\framedparameter\c!region}% - \ifx\p_framed_region\empty\else - \pack_framed_add_region + \edef\m_overlay_region{\framedparameter\c!region}% + \ifx\m_overlay_region\empty\else + \pack_framed_set_region \fi \fi \d_framed_applied_offset @@ -1649,6 +1692,11 @@ \fi \fi \pack_framed_locator_after\p_framed_location + \iftrialtypesetting \else + \ifx\m_overlay_region\empty\else + \pack_framed_add_region + \fi + \fi \box\b_framed_normal \global\frameddimensionstate % global so to be used directly afterwards ! \ifconditional\c_framed_has_width @@ -2203,7 +2251,7 @@ \ignorespaces} \def\dododoformatonelinerbox - {\hbox to \hsize % maybe \hpack + {\hpack to \hsize % was \hbox {\ifcase\raggedstatus\or\hss\or\hss \fi \unhbox\nextbox \removeunwantedspaces \ifcase\raggedstatus\or \or\hss\or\hss\fi}% @@ -2324,7 +2372,7 @@ \doformatonelinerbox} \def\pack_framed_format_format_vsize - {\vbox to \d_framed_height + {\vbox to \d_framed_height % no vpack .. maybe grid \bgroup \let\postprocessframebox\relax % \pack_framed_forgetall @@ -2551,9 +2599,9 @@ \par \kern-\d_framed_linewidth \dontleavehmode - \hpack to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% + \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}% \hfill - \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}% + \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}% \par \nointerlineskip \kern\scratchoffset @@ -2792,7 +2840,7 @@ \csname\??framedtextlocation\framedtextparameter\c!location\endcsname \resetframedtextparameter\c!location \pack_framed_text_check - \setbox\b_framed_normal\vbox + \setbox\b_framed_normal\vbox % \vpack \startboxedcontent \hsize\localhsize % \insidefloattrue % ? better @@ -3069,7 +3117,7 @@ \fi} \def\pack_framed_start_content_indeed - {\setbox\b_framed_normal\hbox\bgroup % maybe \hpack + {\setbox\b_framed_normal\hpack\bgroup \setlocalhsize \hsize\localhsize \scratchleftoffset \framedcontentparameter\c!leftoffset \relax @@ -3079,16 +3127,16 @@ \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax \kern\scratchleftoffset - \vbox\bgroup + \vpack\bgroup \vskip\scratchtopoffset - \vbox\bgroup - \forgetall - \blank[\v!disable]} + \vbox\bgroup + \forgetall + \blank[\v!disable]} \def\pack_framed_stop_content_indeed - {\removelastskip - \egroup - \vskip\scratchbottomoffset + {\removelastskip + \egroup + \vskip\scratchbottomoffset \egroup \kern\scratchrightoffset \egroup @@ -3132,4 +3180,16 @@ \let\themaxboxwidth\clf_themaxboxwidth +%D New: slow but ok for most cases: + +\unexpanded\def\doifelseframed#1% + {\ifcase\numexpr\zerocount + \immediateassignment\edef\tempstring{#1\c!frame }\ifx\tempstring\v!on +\plusone\fi + \immediateassignment\edef\tempstring{#1\c!topframe }\ifx\tempstring\v!on +\plusone\fi + \immediateassignment\edef\tempstring{#1\c!bottomframe}\ifx\tempstring\v!on +\plusone\fi + \immediateassignment\edef\tempstring{#1\c!leftframe }\ifx\tempstring\v!on +\plusone\fi + \immediateassignment\edef\tempstring{#1\c!rightframe }\ifx\tempstring\v!on +\plusone\fi + \immediateassignment\edef\tempstring{#1\c!background }\ifx\tempstring\empty\else+\plusone\fi + \relax\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv index b44910bbe6c..1ec7cdbb86e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-bck.mkiv @@ -52,7 +52,7 @@ \let\currentotrbackground\empty -%D This is the only spot where we hav ea low level dependency on the way +%D This is the only spot where we have a low level dependency on the way %D parent chains are defined but we want the speed. \unexpanded\def\page_backgrounds_check_background diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi index 083a94390e5..10d5916319f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-box.mkvi @@ -15,7 +15,7 @@ \unprotect -%D The often two step approach (_indeed) saves skippign tokens +%D The often two step approach (_indeed) saves skipping tokens %D which is nicer for tracing. %D Centering the paper area on the print area is determined @@ -251,14 +251,25 @@ \def\page_boxes_apply_offsets#1% {\setbox#1\vpack to \paperheight {\hsize\paperwidth - \vskip\topspace - \doifbothsides - {\hskip\backspace} - {\hskip\backspace} - {\hskip\dimexpr\paperwidth-\backspace-\makeupwidth\relax}% + \vkern\topspace +% \parfillskip\zeropoint + \hkern\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}% \box#1}% \dp#1\zeropoint} +% \def\page_boxes_apply_offset#box% +% {\scratchwidth \wd#box% +% \scratchheight\ht#box% +% \scratchdepth \dp#box% +% \setbox#box\vpack +% {\offinterlineskip +% \vkern\topoffset +% \hkern\doifbothsides\backoffset\backoffset{-\backoffset}% +% \box#box}% +% \wd#box\scratchwidth +% \ht#box\scratchheight +% \dp#box\scratchdepth} + % \let\page_boxes_apply_clip_paper \gobbleoneargument % \let\page_boxes_apply_clip_print_left \gobbleoneargument % \let\page_boxes_apply_clip_print_right\gobbleoneargument diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua b/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua index 155d6e8b0d1..1c2f5fc0b48 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/page-cst.lua @@ -19,87 +19,86 @@ local trace_cells = false trackers.register("columnsets.cells", function(v) t local report = logs.reporter("column sets") -local setmetatableindex = table.setmetatableindex - -local properties = nodes.properties - -local nodecodes = nodes.nodecodes -local rulecodes = nodes.rulecodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue -local penalty_code = nodecodes.penalty -local rule_code = nodecodes.rule - -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local hpack = nuts.hpack -local vpack = nuts.vpack -local flushlist = nuts.flush_list ------ removenode = nuts.remove - -local setlink = nuts.setlink -local setlist = nuts.setlist -local setnext = nuts.setnext -local setprev = nuts.setprev -local setsubtype = nuts.setsubtype -local setbox = nuts.setbox -local getwhd = nuts.getwhd -local setwhd = nuts.setwhd -local getkern = nuts.getkern -local getpenalty = nuts.getpenalty -local getwidth = nuts.getwidth -local getheight = nuts.getheight - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getsubtype = nuts.getsubtype -local takebox = nuts.takebox -local takelist = nuts.takelist -local splitbox = nuts.splitbox -local getattribute = nuts.getattribute -local copylist = nuts.copy_list - -local getbox = nuts.getbox -local getcount = tex.getcount -local getdimen = tex.getdimen - -local texsetbox = tex.setbox -local texsetcount = tex.setcount -local texsetdimen = tex.setdimen - -local theprop = nuts.theprop - -local nodepool = nuts.pool - -local new_vlist = nodepool.vlist -local new_trace_rule = nodepool.rule -local new_empty_rule = nodepool.emptyrule - -local context = context -local implement = interfaces.implement - -local variables = interfaces.variables -local v_here = variables.here -local v_fixed = variables.fixed -local v_top = variables.top -local v_bottom = variables.bottom -local v_repeat = variables["repeat"] -local v_yes = variables.yes -local v_page = variables.page -local v_first = variables.first -local v_last = variables.last ------ v_wide = variables.wide - -pagebuilders = pagebuilders or { } -- todo: pages.builders -pagebuilders.columnsets = pagebuilders.columnsets or { } -local columnsets = pagebuilders.columnsets +local setmetatableindex = table.setmetatableindex + +local properties = nodes.properties + +local nodecodes = nodes.nodecodes + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local rule_code = nodecodes.rule + +local nuts = nodes.nuts +local tonode = nuts.tonode +local tonut = nuts.tonut + +local hpack = nuts.hpack +local vpack = nuts.vpack +local flushlist = nuts.flush_list +----- removenode = nuts.remove + +local setlink = nuts.setlink +local setlist = nuts.setlist +local setnext = nuts.setnext +local setprev = nuts.setprev +local setsubtype = nuts.setsubtype +local setbox = nuts.setbox +local getwhd = nuts.getwhd +local setwhd = nuts.setwhd +local getkern = nuts.getkern +local getpenalty = nuts.getpenalty +local getwidth = nuts.getwidth +local getheight = nuts.getheight + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getlist = nuts.getlist +local getsubtype = nuts.getsubtype +local takebox = nuts.takebox +local takelist = nuts.takelist +local splitbox = nuts.splitbox +local getattribute = nuts.getattribute +local copylist = nuts.copy_list + +local getbox = nuts.getbox +local getcount = tex.getcount +local getdimen = tex.getdimen + +local texsetbox = tex.setbox +local texsetcount = tex.setcount +local texsetdimen = tex.setdimen + +local theprop = nuts.theprop + +local nodepool = nuts.pool + +local new_vlist = nodepool.vlist +local new_trace_rule = nodepool.rule +local new_empty_rule = nodepool.emptyrule + +local context = context +local implement = interfaces.implement + +local variables = interfaces.variables +local v_here = variables.here +local v_fixed = variables.fixed +local v_top = variables.top +local v_bottom = variables.bottom +local v_repeat = variables["repeat"] +local v_yes = variables.yes +local v_page = variables.page +local v_first = variables.first +local v_last = variables.last +----- v_wide = variables.wide + +pagebuilders = pagebuilders or { } -- todo: pages.builders +pagebuilders.columnsets = pagebuilders.columnsets or { } +local columnsets = pagebuilders.columnsets local data = { [""] = { } } diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv index f6eede68a52..37df4e8b17c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-cst.mkiv @@ -765,7 +765,7 @@ % state start | repeat -% for now (transition) +%D The old one: \let\definecolumnset \definepagegrid \let\setupcolumnset \setuppagegrid @@ -782,5 +782,6 @@ \let\setupcolumnsetarea \setuppagegridarea \let\setupcolumnsetareatext\setuppagegridareatext -\protect +%D It ends here. +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ffl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-ffl.mkiv index 5536371a79e..414cae4ac11 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-ffl.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-ffl.mkiv @@ -84,26 +84,29 @@ \def\strc_floats_facing_flush {\ifnum\c_strc_floats_flushed<\c_strc_floats_saved - \global\advance\c_strc_floats_flushed\plusone - \floatingpenalty\zerocount - \insert\namedinsertionnumber\s!topfloat\bgroup - \forgetall - \ifconditional\c_page_one_top_of_insert - \ifconditional\c_page_one_correct_top_insert - \topskipcorrection % [xx] new: see icare topbleed - \kern-\lineskip - \par - \prevdepth\maxdimen - \fi + \strc_floats_facing_flush_indeed % less tracing + \fi} + +\def\strc_floats_facing_flush_indeed + {\global\advance\c_strc_floats_flushed\plusone + \floatingpenalty\zerocount + \insert\namedinsertionnumber\s!topfloat\bgroup + \forgetall + \ifconditional\c_page_one_top_of_insert + \ifconditional\c_page_one_correct_top_insert + \topskipcorrection % [xx] new: see icare topbleed + \kern-\lineskip + \par + \prevdepth\maxdimen \fi - \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_flushed}% - \vskip\s_page_one_between_top_insert - \egroup - \ifnum\c_strc_floats_saved=\c_strc_floats_flushed - \global\c_strc_floats_saved \zerocount - \global\c_strc_floats_flushed\zerocount - \resetboxesincache{\currentfacingfloat}% \fi + \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_flushed}% + \vkern\s_page_one_between_top_insert + \egroup + \ifnum\c_strc_floats_saved=\c_strc_floats_flushed + \global\c_strc_floats_saved \zerocount + \global\c_strc_floats_flushed\zerocount + \resetboxesincache{\currentfacingfloat}% \fi} \unexpanded\def\strc_floats_facing_setup diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv index a06c90ec12c..83e2b49547a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-flt.mkiv @@ -284,16 +284,16 @@ \doifnotinset\v!low\floatspecification\vfill}% \page_otr_fill_and_eject_page} -\let\m_page_otf_checked_page_float\relax +\let\m_page_otr_checked_page_float\relax \unexpanded\def\page_floats_flush_page_floats % used in postpone - {\edef\m_page_otf_checked_page_float{\clf_checkedpagefloat}% - \ifx\m_page_otf_checked_page_float\empty + {\edef\m_page_otr_checked_page_float{\clf_checkedpagefloat}% + \ifx\m_page_otr_checked_page_float\empty % nothing - \else\ifx\m_page_otf_checked_page_float\v!empty + \else\ifx\m_page_otr_checked_page_float\v!empty \emptyhbox \page_otr_fill_and_eject_page % why not dummy_page \else - \page_floats_flush_page_floats_indeed\m_page_otf_checked_page_float + \page_floats_flush_page_floats_indeed\m_page_otr_checked_page_float \fi\fi} % temp hack, needed to prevent floatbox being forgotten during diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv index c08f9856fa7..838ad742188 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-imp.mkiv @@ -26,7 +26,7 @@ \newtoks\t_page_text_data \unexpanded\def\starttextdata#1\stoptextdata - {\global\let\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed + {\glet\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed \globaladdtotoks\t_page_text_data{#1}} \let\stoptextdata\relax @@ -34,7 +34,7 @@ \def\page_shipouts_flush_text_data_indeed {\vsmashed{\the\t_page_text_data}% \global\t_page_text_data\emptytoks - \global\let\page_shipouts_flush_text_data\relax} + \glet\page_shipouts_flush_text_data\relax} \let\page_shipouts_flush_text_data\relax @@ -63,9 +63,21 @@ \newbox \shipoutscratchbox -\setnewconstant\shipoutfinalizemethod\plusone % this will be default (we will have two finalizers) +\setnewconstant\shipoutfinalizemethod\plusone -\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed +\unexpanded\def\shipoutrange#1#2% + {\begingroup + \scratchtoks\emptytoks + \dostepwiserecurse{#1}{\numexpr#2-\plusone\relax}\plusone{\etoksapp\scratchtoks{##1,}}% + \xdef\pagestoshipout{\the\scratchtoks,\number#2}% + \doglobal\appendtoks + \ifnum\realpageno>\numexpr#2+\plusone\relax + \global\everypar{\normalend}% + \fi + \to\everyaftershipout + \endgroup} + +\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed {\setgvalue{\??shipoutmethod#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package) \let\installpagehandler\installshipoutmethod % will go @@ -73,13 +85,6 @@ \unexpanded\def\invokepagehandler#1% {\expandnamespacevalue\??shipoutmethod{#1}\v!normal} -% \def\page_shipouts_handle -% {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname -% \v_page_target_method -% \else -% \v!none -% \fi\endcsname} - \def\page_shipouts_handle {\ifcsname\??shipoutmethod\v_page_target_method\endcsname \expandafter\lastnamedcs @@ -112,12 +117,14 @@ \page_boxes_flush_before \fi \the\everybeforeshipout - \ifcase\shipoutfinalizemethod + \ifcase\shipoutfinalizemethod % not nice ... needs thinking \page_shipouts_handle{#1}% \else - \setbox\shipoutscratchbox\hpack{#1}% just in case there are objects there, hook for testing (will go away) - \finalizeshipoutbox\shipoutscratchbox - \page_shipouts_handle{\box\shipoutscratchbox}% + \setbox\shipoutscratchbox\hpack + {#1}% just in case there are objects there, hook for testing (will go away) + \page_shipouts_handle + {\finalizeshipoutbox\shipoutscratchbox + \box\shipoutscratchbox}% \fi \setnextrealpageno % so this comes before \everyaftershipout so in fact: \the\everyaftershipout % at this point we're already on the next realpage @@ -127,11 +134,12 @@ \def\page_shipouts_ignore#1% {\begingroup - \message - {[\ifarrangingpages arranged \fi page + \writestatus\m!system + {\ifarrangingpages arranged \fi page \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace - not flushed]}% - \setbox\scratchbox\hpack{#1}% + not flushed}% + % \setbox\scratchbox\hpack + % {#1}% no finalize \deadcycles\zerocount \endgroup} @@ -154,7 +162,11 @@ \box\scratchbox \endgroup} -\newdimen\d_page_shipouts_offset \d_page_shipouts_offset=-1in +\ifdefined \page_shipout_box \else + + \def\page_shipout_box#1{\normalshipout\box#1\relax} % takes a number + +\fi \def\page_shipouts_normal#1% {\global\advance\shippedoutpages\plusone @@ -173,30 +185,36 @@ \normalexpanded{\doifelseinset{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse \fi \ifdone - \setbox\shipoutscratchbox\hpack{#1}% + \setbox\shipoutscratchbox\hpack + {#1}% finalizes \ifcase\shipoutfinalizemethod \finalizeshipoutbox\shipoutscratchbox \fi - \normalshipout\vpack - {\offinterlineskip - \vskip\d_page_shipouts_offset - \hskip\d_page_shipouts_offset + \setbox\shipoutscratchbox\vpack + {\scratchdimen\clf_shipoutoffset\relax + \ifdim\scratchdimen=\zeropoint\else + \offinterlineskip + \vkern\scratchdimen + \hkern\scratchdimen + \fi \hpack {\page_otr_flush_every_stuff \page_otr_flush_special_content \box\shipoutscratchbox}}% + \page_shipout_box\shipoutscratchbox % takes a box number! \else \page_shipouts_ignore{#1}% \fi} \def\page_shipouts_arrange#1% - {% \global\advance\shippedoutpages\plusone - \begingroup - \setbox\scratchbox\hpack + {\begingroup + \setbox\shipoutscratchbox\hpack + {#1}% finalizes + \setbox\shipoutscratchbox\hpack {\page_otr_flush_every_stuff \page_otr_flush_special_content \box\shipoutscratchbox}% - \pusharrangedpage\scratchbox + \pusharrangedpage\shipoutscratchbox \deadcycles\zerocount \endgroup} @@ -310,14 +328,14 @@ \let\pusharrangedpage\relax \def\dosetuparrangement#1#2#3#4#5#6#7#8% - {\global\arrangedpageX #1% - \global\arrangedpageY #2% - \global\arrangedpageT #3% - \global\c_page_marks_nx #4% - \global\c_page_marks_ny #5% - \global\let\pusharrangedpage #6% - \global\let\poparrangedpages #7% - \global\let\handlearrangedpage#8} + {\global\arrangedpageX #1% + \global\arrangedpageY #2% + \global\arrangedpageT #3% + \global\c_page_marks_nx #4% + \global\c_page_marks_ny #5% + \glet \pusharrangedpage #6% + \glet \poparrangedpages #7% + \glet \handlearrangedpage#8} \installpagearrangement {\v!normal} {\global\arrangingpagesfalse} diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv index 2064f9f25be..4519083bf19 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-inf.mkiv @@ -112,14 +112,16 @@ {\vfill \settexthoffset \hsize\dimexpr\scratchdimen-2\texthoffset\relax - \hskip\texthoffset % brrrr + \hkern\texthoffset % brrrr \vbox to \zeropoint{\vss\page_info_place_info}% - \vskip\bodyfontsize}% + \vkern\bodyfontsize}% \dp\b_page_versions\zeropoint \wd\b_page_versions\scratchdimen - \setbox#1\hpack{\box#1\hskip-\scratchdimen\box\b_page_versions}} + \setbox#1\hpack{\box#1\hkern-\scratchdimen\box\b_page_versions}} \setupversion % resets [\v!final] +\let\page_info_add_to_box\gobbleoneargument + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/page-ini.lua index 5b73c972903..3d553412815 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/page-ini.lua @@ -41,23 +41,39 @@ function pages.mark(name,list) local page = list[i] local sign = false if type(page) == "string" then - local s, p = match(page,"([%+%-])(%d+)") - if s then - sign, page = s, p + local f, t = match(page,"(%d+)[:%-](%d+)") + if f and t then + f, t = tonumber(f), tonumber(t) + if f and t and f <= t then + if trace then + report("marking page %i upto %i as %a",f,t,name) + end + for page=f,t do + data[page][name] = true + end + end + page = false + else + local s, p = match(page,"([%+%-])(%d+)") + if s then + sign, page = s, p + end end end - page = tonumber(page) if page then - if sign == "+" then - page = realpage + page - end - if sign == "-" then - report("negative page numbers are not supported") - else - if trace then - report("marking page %i as %a",page,name) + page = tonumber(page) + if page then + if sign == "+" then + page = realpage + page + end + if sign == "-" then + report("negative page numbers are not supported") + else + if trace then + report("marking page %i as %a",page,name) + end + data[page][name] = true end - data[page][name] = true end end end @@ -75,7 +91,6 @@ local function marked(name) rawset(data,i,nil) end local pagedata = rawget(data,realpage) - print(pagedata and pagedata[name] and true or false) return pagedata and pagedata[name] and true or false end diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv index dc94edf7638..38477dc2747 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-ini.mkiv @@ -80,7 +80,7 @@ \fi} \def\page_otr_flush_pending_content - {\vskip\zeropoint\relax + {\vkern\zeropoint\relax \ifvoid\normalpagebox \else \unvbox\normalpagebox \penalty\outputpenalty @@ -256,7 +256,10 @@ \box\pagebox \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi} -\appendtoks \restoreglobalbodyfont \to \everybeforepagebody +\appendtoks + \restoreglobalbodyfont + \pickupattributes +\to \everybeforepagebody \ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed? diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi index cabd07bac14..5f48ffd13dd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-inj.mkvi @@ -124,7 +124,7 @@ \ifx\currentpageinjectionalternative\v!none \else % increment counter but don’t generate output \forgetparindent \dontcomplain - \setconstant\shipoutfinalizemethod\zerocount + \setconstant\shipoutfinalizemethod\zerocount % this is messy \page_injections_flush_indeed \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv index 7b80dadb98b..02cc5aa17f2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-lay.mkiv @@ -13,19 +13,16 @@ \writestatus{loading}{ConTeXt Page Macros / Layout Specification} -%D Before you start wondering why some of the page related -%D modules skip upward or left in order to place elements, you -%D must realize that the reference point is the top left -%D corner of the main typesetting area. One reason for this -%D choice is that it suited some viewers that displayed page -%D areas. Another reason is that margins, edges and top and -%D bottom areas are kind of virtual, while the header, text -%D and footer areas normally determine the text flow. +%D Before you start wondering why some of the page related modules skip upward or +%D left in order to place elements, you must realize that the reference point is the +%D top left corner of the main typesetting area. One reason for this choice is that +%D it suited some viewers that displayed page areas. Another reason is that margins, +%D edges and top and bottom areas are kind of virtual, while the header, text and +%D footer areas normally determine the text flow. \unprotect -%D The dimensions related to layout areas are represented by -%D real dimensions. +%D The dimensions related to layout areas are represented by real dimensions. \newdimen\paperheight \paperheight = 297mm \newdimen\paperwidth \paperwidth = 210mm @@ -69,17 +66,15 @@ \newdimen\totaltextwidth -%D The next series of dimensions are complemented by left -%D and rights ones. +%D The next series of dimensions are complemented by left and rights ones. \newdimen\margindistance \newdimen\edgedistance \newdimen\marginwidth \newdimen\edgewidth -%D Because a distance does not really makes sense when there -%D is no area, we use a zero distance in case there is no -%D area. +%D Because a distance does not really makes sense when there is no area, we use a +%D zero distance in case there is no area. %D The horizontal distances are: @@ -149,12 +144,12 @@ \let\currentlayout\empty \fi \letlayoutparameter\c!state\v!normal % global ? still needed ? - \global\let\currentlayout\currentlayout % global + \glet\currentlayout\currentlayout % global \page_layouts_synchronize \page_layouts_check_next \or % \setuplayout (reverts to main layout) \letlayoutparameter\c!state\v!normal % global ? still needed ? - \global\let\currentlayout\empty % global + \glet\currentlayout\empty % global \page_layouts_synchronize \page_layouts_check_next \fi @@ -244,16 +239,15 @@ \swapmacros\innersidetotal \outersidetotal \to \everyswapmargins -%D The papersize macros have a long history and we don't want -%D to change the commands so they keep looking a bit complex. +%D The papersize macros have a long history and we don't want to change the commands +%D so they keep looking a bit complex. %D \macros %D {definepapersize} %D -%D Before we start calculating layout dimensions, we will -%D first take care of paper sizes. The first argument can be -%D either an assignment (for defaults) or an identifier, in -%D which case the second argument is an assignment. +%D Before we start calculating layout dimensions, we will first take care of paper +%D sizes. The first argument can be either an assignment (for defaults) or an +%D identifier, in which case the second argument is an assignment. %D %D \showsetup{definepapersize} %D @@ -281,8 +275,8 @@ %D \macros %D {setuppaper,setuppapersize} %D -%D When setting up the papersize on which to typeset and -%D print, we can also determine some more characteristics. +%D When setting up the papersize on which to typeset and print, we can also +%D determine some more characteristics. %D %D \showsetup{setuppapersize} %D @@ -335,9 +329,8 @@ \def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax} -% Normally we will not use this command directly but for now it -% works out okay. In the future we might use more of the related -% commands. +%D Normally we will not use this command directly but for now it works out okay. In +%D the future we might use more of the related commands. \setuplayouttarget [% these are rather special @@ -462,7 +455,7 @@ \appendtoks \page_paper_reinstate - \global\let\page_paper_reinstate\relax + \glet\page_paper_reinstate\relax \to \everyaftershipout \unexpanded\def\page_paper_set_restore#1#2% @@ -538,7 +531,7 @@ \ifx\currentlayouttarget\empty \let\currentlayouttarget\currentpage \fi - \global\let\papersize\currentlayouttarget + \glet\papersize\currentlayouttarget \page_paper_reset_paper \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option \global\paperwidth \layouttargetparameter\c!width \relax @@ -561,7 +554,7 @@ % locate paper target \page_paper_reset_print \processcommacommand[\m_page_asked_print]\page_paper_identify_target - \global\let\printpapersize\currentlayouttarget + \glet\printpapersize\currentlayouttarget \page_paper_reset_print \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option \global\printpaperwidth \layouttargetparameter\c!width \relax @@ -814,18 +807,18 @@ {\edef\m_page_check{#1} \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}% \ifx\m_page_state\v!start - \global\let\v_page_layouts_pre_check\currentlayout - \global\let\currentlayout\m_page_check + \glet\v_page_layouts_pre_check\currentlayout + \glet\currentlayout\m_page_check \page_layouts_synchronize \else\ifx\m_page_state\v!repeat - \global\let\v_page_layouts_pre_check\relax - \global\let\currentlayout\m_page_check + \glet\v_page_layouts_pre_check\relax + \glet\currentlayout\m_page_check \page_layouts_synchronize \fi\fi} \def\page_layouts_check_revert - {\global\let\currentlayout\v_page_layouts_pre_check - \global\let\v_page_layouts_pre_check\relax + {\glet\currentlayout\v_page_layouts_pre_check + \glet\v_page_layouts_pre_check\relax \page_layouts_synchronize} \def\page_layouts_check_default @@ -996,6 +989,7 @@ \newdimen\d_page_adepts_pushed_text_height \newdimen\d_page_adepts_pushed_footer_height \newdimen\d_page_adepts_height +\newdimen\d_page_adapts_delta \unexpanded\def\adaptlayout {\dodoubleempty\page_adapts_layout} @@ -1040,8 +1034,8 @@ \page_otr_command_set_vsize % \page_backgrounds_recalculate - \global\let\page_adepts_push\relax - \global\let\page_adepts_pop\page_adepts_pop_indeed} + \glet\page_adepts_push\relax + \glet\page_adepts_pop\page_adepts_pop_indeed} % \def\page_adapts_check % {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname} @@ -1067,8 +1061,8 @@ {\global\textheight \d_page_adepts_pushed_text_height \global\footerheight\d_page_adepts_pushed_footer_height \page_layouts_synchronize - \global\let\page_adepts_push\page_adepts_push_indeed - \global\let\page_adepts_pop\relax} + \glet\page_adepts_push\page_adepts_push_indeed + \glet\page_adepts_pop\relax} \appendtoks \page_adapts_check \to \everystarttext \appendtoks \page_adapts_reset \to \everyshipout @@ -1153,8 +1147,8 @@ \def\compensatedinnermakeupmargin {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax} -\unexpanded\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth - {\textwidth\makeupwidth % which is a tricky but valid value +\unexpanded\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth + {\textwidth\makeupwidth % which is a tricky but valid value \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }% \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}% \ifx\m_currentlayout_text_width\empty \else @@ -1174,15 +1168,9 @@ {\freezetextwidth \page_otr_command_set_hsize} -% The next few are better off in page-ini.mkiv - -%D When we start at an even page, we need to swap the layout -%D differently. We cannot adapt the real page number, since -%D it is used in cross referencing. The next switch is set -%D when we start at an even page. - -% We could use nested if here plus some \@EAEAEA's but but the -% next variant has less expansion which is nicer in tracing. +%D When we start at an even page, we need to swap the layout differently. We cannot +%D adapt the real page number, since it is used in cross referencing. The next +%D switch is set when we start at an even page. % #single #left #right @@ -1262,7 +1250,7 @@ % \to \everybeforeshipout \def\goleftonpage % name will change (we could cache) - {\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax} + {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax} \def\doifelsemarginswap#1#2% {\doifbothsides{#1}{#1}{#2}} @@ -1327,12 +1315,9 @@ %D \macros %D {startlocallayout} %D -%D These macros should be used with care. They permit local -%D layouts (as used in fitting pages, see \type {page-app.tex}). - -%D This is kind of obsolete now that we have \type -%D {\definelayout}, so this hack will disappear in future -%D versions. +%D These macros should be used with care. They permit local layouts (as used in +%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we +%D have \type {\definelayout}, so this hack will disappear in future versions. \unexpanded\def\startlocallayout {\globalpushmacro\page_paper_restore @@ -1367,19 +1352,16 @@ \glet\page_grids_add_to_one\gobbleoneargument \glet\page_grids_add_to_mix\gobbleoneargument -%D The default dimensions are quite old and will not change. -%D The funny fractions were introduced when we went from fixed -%D dimensions to relative ones. Since \CONTEXT\ is a dutch -%D package, the dimensions are based on the metric system. The -%D asymmetrical layout is kind of handy for short -%D quick||and||dirty stapled documents. +%D The default dimensions are quite old and will not change. The funny fractions +%D were introduced when we went from fixed dimensions to relative ones. Since +%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The +%D asymmetrical layout is kind of handy for short quick||and||dirty stapled +%D documents. %D -%D Although valid, it is not a real good idea to use -%D dimensions based on the \type {em} unit. First of all, -%D since there are no fonts loaded yet, this dimension makes -%D no sense, and second, you would loose track of values, -%D since they could change while going to a new page, -%D depending on the current font setting. +%D Although valid, it is not a real good idea to use dimensions based on the \type +%D {em} unit. First of all, since there are no fonts loaded yet, this dimension +%D makes no sense, and second, you would loose track of values, since they could +%D change while going to a new page, depending on the current font setting. \setuplayout [ \c!topspace=.08417508418\paperheight, % 2.5cm @@ -1435,8 +1417,8 @@ \c!columns=\plusone, \c!columndistance=\zeropoint] -%D First we define a whole range of (DIN) papersizes, -%D of which the A-series makes most sense. We enable checking. +%D First we define a whole range of (DIN) papersizes, of which the A-series makes +%D most sense. We enable checking. \definepapersize [A0] [\c!width=841mm,\c!height=1189mm] \definepapersize [A1] [\c!width=594mm,\c!height=841mm] @@ -1477,18 +1459,17 @@ \definepapersize [C9] [\c!width=40mm,\c!height=57mm] \definepapersize [C10] [\c!width=28mm,\c!height=40mm] -%D Per August 2004 the rounding of some (seldom used) sizes -%D were corrected top the latest DIN specifications. Peter -%D Rolf came up with these and a few more missing sizes. -%D Watch out: spaces and slashes! +%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the +%D latest DIN specifications. Peter Rolf came up with these and a few more missing +%D sizes. Watch out: spaces and slashes! \definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm] \definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm] \definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm] -%D Because there are no standardized screen sizes, we define -%D a bunch of sizes with $4:3$ ratios. The \type {S6} size is -%D nearly as wide as a sheet of \type {A4} paper. +%D Because there are no standardized screen sizes, we define a bunch of sizes with +%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4} +%D paper. \definepapersize [S3] [\c!width=300pt,\c!height=225pt] \definepapersize [S4] [\c!width=400pt,\c!height=300pt] @@ -1509,15 +1490,13 @@ \definepapersize [S55] [\c!width=500pt,\c!height=500pt] \definepapersize [S66] [\c!width=600pt,\c!height=600pt] -%D One may wonder if \TEX\ should be used for typesetting -%D \CDROM\ covers, but it does not hurt to have the paper size -%D ready. +%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it +%D does not hurt to have the paper size ready. \definepapersize [CD] [\c!width=120mm,\c!height=120mm] -%D The next series is for our English speaking friends who -%D decided to stick to non metric values. Thanks to Nelson -%D Beebe for completing the inch based list. +%D The next series is for our English speaking friends who decided to stick to non +%D metric values. Thanks to Nelson Beebe for completing the inch based list. \definepapersize [letter] [\c!width=8.5in,\c!height=11in] \definepapersize [ledger] [\c!width=11in,\c!height=17in] @@ -1573,9 +1552,9 @@ \definepapersize [business] [\c!width=85mm,\c!height=55mm] \definepapersize [businessUS] [\c!width=3.5in,\c!height=2in] -%D We can now default to a reasonable size. We match the print -%D paper size with the typeset paper size. This setting should -%D come after the first layout specification (already done). +%D We can now default to a reasonable size. We match the print paper size with the +%D typeset paper size. This setting should come after the first layout specification +%D (already done). % \definepapersize % [\v!default] diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua b/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua index a6b6a12c400..3689c7f8d1d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/page-lin.lua @@ -43,15 +43,14 @@ local v_no = variables.no local properties = nodes.properties local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes -local whatcodes = nodes.whatcodes local listcodes = nodes.listcodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local whatsit_code = nodecodes.whatsit local glyph_code = nodecodes.glyph -local line_code = listcodes.line + +local linelist_code = listcodes.line local a_displaymath = attributes.private('displaymath') local a_linenumber = attributes.private('linenumber') @@ -71,7 +70,7 @@ local getattr = nuts.getattr local setattr = nuts.setattr local getlist = nuts.getlist local getbox = nuts.getbox ------ getdir = nuts.getdir +----- getdirection = nuts.getdirection ----- getwidth = nuts.getwidth local getheight = nuts.getheight local getdepth = nuts.getdepth @@ -79,8 +78,9 @@ local getdepth = nuts.getdepth local setprop = nuts.setprop local getprop = nuts.getprop -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse +local nexthlist = nuts.traversers.hlist +local nextvlist = nuts.traversers.vlist + local copy_node = nuts.copy ----- hpack_nodes = nuts.hpack local is_display_math = nuts.is_display_math @@ -224,7 +224,9 @@ implement { local function check_number(n,a,skip,sameline) local d = data[a] if d then - local tag, skipflag, s = d.tag or "", 0, d.start or 1 + local tag = d.tag or "" + local skipflag = 0 + local s = d.start or 1 current_list[#current_list+1] = { n, s } if sameline then skipflag = 0 @@ -244,7 +246,7 @@ local function check_number(n,a,skip,sameline) end local p = checkline(n) if p then - ctx_makelinenumber(tag,skipflag,s,p.hsize,p.reverse and "TRT" or "TLT") + ctx_makelinenumber(tag,skipflag,s,p.hsize,p.reverse and 1 or 0) else report_lines("needs checking") end @@ -283,8 +285,8 @@ end local function listisnumbered(list) if list then - for n in traverse_id(hlist_code,list) do - if getsubtype(n) == line_code then + for n, subtype in nexthlist, list do + if subtype == linelist_code then local a = getattr(n,a_linenumber) if a then -- a quick test for lines (only valid when \par before \stoplinenumbering) @@ -306,7 +308,7 @@ local function findnumberedlist(list) while n do local id = getid(n) if id == hlist_code then - if getsubtype(n) == line_code then + if getsubtype(n) == linelist_code then local a = getattr(n,a_linenumber) if a then return a > 0 and list @@ -383,9 +385,8 @@ function boxed.stage_one(n,nested) local skip = false local function check() - for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found - local subtype = getsubtype(n) - if subtype ~= line_code then + for n, subtype in nexthlist, list do + if subtype ~= linelist_code then -- go on elseif getheight(n) == 0 and getdepth(n) == 0 then -- skip funny hlists -- todo: check line subtype @@ -450,7 +451,7 @@ function boxed.stage_one(n,nested) if not list then return end - for n in traverse_id(vlist_code,list) do + for n in nextvlist, list do local p = properties[n] if p and p.columngap then if trace_numbers then @@ -472,18 +473,21 @@ end function boxed.stage_two(n,m) if #current_list > 0 then m = m or lines.scratchbox - local t, tn = { }, 0 - for l in traverse_id(hlist_code,getlist(getbox(m))) do + local t = { } + local tn = 0 + for l in nexthlist, getlist(getbox(m)) do tn = tn + 1 t[tn] = copy_node(l) -- use take_box instead end for i=1,#current_list do local li = current_list[i] - local n, m, ti = li[1], li[2], t[i] + local n = li[1] + local m = li[2] + local ti = t[i] if ti then - -- local d = getdir(n) + -- local d = getdirection(n) -- local l = getlist(n) - -- if d == "TRT" then + -- if d == 1 then -- local w = getwidth(n) -- ti = hpack_nodes(linked_nodes(new_kern(-w),ti,new_kern(w))) -- end diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi index 4348d677065..a27ba5736c5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-lin.mkvi @@ -46,6 +46,10 @@ \attribute\linenumberattribute\attributeunsetvalue \to \everyforgetall +\appendtoks + \attribute\linenumberattribute \attributeunsetvalue +\to \everyinsidefloat + \newcount \linenumber % not used \newbox \b_page_lines_scratch \newcount \c_page_lines_reference @@ -275,8 +279,8 @@ \fi\fi\fi \fi \the\beforeeverylinenumbering - \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page - \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column + \glet\page_postprocessors_page \page_postprocessors_linenumbers_page + \glet\page_postprocessors_column\page_postprocessors_linenumbers_column \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv \ifcase\c_page_lines_mode\relax \page_lines_start_update % continue @@ -349,7 +353,7 @@ \d_page_lines_distance\linenumberingparameter\c!distance\relax \edef\p_align{\linenumberingparameter\c!align}% \edef\p_location{\linenumberingparameter\c!location}% - \ifcase\istltdir#dir\relax + \ifcase#dir\relax \settrue \c_page_lines_dir_left_to_right \else \setfalse\c_page_lines_dir_left_to_right diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua b/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua index 107ac14102c..192b8a30aa6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/page-mix.lua @@ -69,8 +69,6 @@ local getpenalty = nuts.getpenalty local getwidth = nuts.getwidth local getheight = nuts.getheight local getdepth = nuts.getdepth -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse local theprop = nuts.theprop @@ -829,23 +827,6 @@ local function report_deltas(result,str) report_state("%s, cycles %s, deltas % | t",str,result.cycle or 1,t) end --- local function xxcollectinserts(h) --- local skips, total, order = 0, 0, 0 --- print(h) --- if h then --- h = getlist(h) --- for n in traverse(h) do --- print(tonode(n)) --- end --- for n in traverse_id(insert_code,h) do --- order = order + 1 --- total = total + getheight(n) --- skips = skips + structures.notes.check_spacing(getsubtype(n),order) --- end --- end --- return skips, total --- end - local function setsplit(specification) splitruns = splitruns + 1 if trace_state then diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv index 684ebc5854a..436c4a1dcf6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-mix.mkiv @@ -371,6 +371,9 @@ \let\currentmixedcolumnsmethod\empty +\installmacrostack\currentmixedcolumns +\installmacrostack\currentmixedcolumnsmethod + \unexpanded\def\startmixedcolumns {\dodoubleempty\page_mix_start_columns} @@ -385,8 +388,8 @@ \fi\fi} \unexpanded\def\page_mix_start_columns - {\pushmacro\currentmixedcolumns - \pushmacro\currentmixedcolumnsmethod + {\push_macro_currentmixedcolumns + \push_macro_currentmixedcolumnsmethod \ifsecondargument \singleexpandafter\page_mix_start_columns_a \else\iffirstargument @@ -462,8 +465,8 @@ \let\stopmixedcolumns\page_mix_columns_stop_nop} \unexpanded\def\page_mix_fast_columns_start#1% - {\pushmacro\currentmixedcolumns - \pushmacro\currentmixedcolumnsmethod + {\push_macro_currentmixedcolumns + \push_macro_currentmixedcolumnsmethod \edef\currentmixedcolumns{#1}% \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}% \mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings ! @@ -492,15 +495,15 @@ \endgroup \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax \mixedcolumnsparameter\c!after\relax - \popmacro\currentmixedcolumnsmethod - \popmacro\currentmixedcolumns + \pop_macro_currentmixedcolumnsmethod + \pop_macro_currentmixedcolumns \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} \unexpanded\def\page_mix_columns_stop_nop {\page_mix_finalize_columns \endgroup - \popmacro\currentmixedcolumnsmethod - \popmacro\currentmixedcolumns + \pop_macro_currentmixedcolumnsmethod + \pop_macro_currentmixedcolumns \the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks} % \unexpanded\def\page_mix_columns_stop_yes @@ -509,12 +512,12 @@ % \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax % \mixedcolumnsparameter\c!after\relax % \ifx\currentmixedcolumnsmethod\s!otr -% \popmacro\currentmixedcolumnsmethod -% \popmacro\currentmixedcolumns +% \pop_macro_currentmixedcolumnsmethod +% \pop_macro_currentmixedcolumns % \synchronizeoutput % brrr, otherwise sometimes issues in itemize % \else -% \popmacro\currentmixedcolumnsmethod -% \popmacro\currentmixedcolumns +% \pop_macro_currentmixedcolumnsmethod +% \pop_macro_currentmixedcolumns % \fi % } diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv index 51af24b6a86..957981703e4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-mul.mkiv @@ -471,7 +471,7 @@ \page_mul_postprocess_lines \page_mul_postprocess_columns \dohandleallcolumns - {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width + {\global\setbox\currentcolumnbox\hpack to \d_page_mul_used_width {\box\currentcolumnbox}% \wd\currentcolumnbox\d_page_mul_used_width \ifheightencolumns @@ -479,12 +479,12 @@ \fi}% \page_mul_calculate_column_result_dimensions \overlaycolumnfootnotes - \setbox\columnpagebox\vbox - {\hbox \ifconditional\c_page_mul_reverse dir TRT \fi to \makeupwidth + \setbox\columnpagebox\vpack % \vbox + {\ifconditional\c_page_mul_reverse\reversehpack\else\naturalhpack\fi to \makeupwidth {\hskip\ifconditional\c_page_mul_reverse\d_page_mul_rightskip\else\d_page_mul_leftskip\fi\relax \dohandleallcolumns {\finishcolumnbox - {\setbox\scratchbox\hbox + {\setbox\scratchbox\hpack {\ifx\finishcolumnbox\relax\else\strut\fi \box\currentcolumnbox}% hm, why strut \anch_mark_column_box\scratchbox @@ -499,13 +499,13 @@ \fi \global\setbox\currenttopcolumnbox\emptybox}% \advance\scratchdimen \ht\columnpagebox - \setbox\scratchbox\hbox to \makeupwidth + \setbox\scratchbox\hbox to \makeupwidth % between can be something so no \hpack {\vrule \s!width \zeropoint \s!height\scratchdimen \s!depth \dp\columnpagebox \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}% - \setbox\columnpagebox\hbox + \setbox\columnpagebox\hpack {\box\columnpagebox \hskip-\makeupwidth \box\scratchbox}% @@ -761,7 +761,7 @@ \page_mul_set_n_of_lines \advance\c_page_mul_n_of_lines \minustwo \scratchdimen\dimexpr\c_page_mul_n_of_lines\lineheight+\topskip\relax - \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% + \setbox\b_page_mul_notes\hpack{\lower\scratchdimen\box\b_page_mul_notes}% \ht\b_page_mul_notes\openstrutheight \dp\b_page_mul_notes\openstrutdepth \wd\b_page_mul_notes\zeropoint @@ -784,7 +784,7 @@ \getnoflines\scratchdimen \advance\noflines \minustwo \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax - \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}% + \setbox\b_page_mul_notes\hpack{\lower\scratchdimen\box\b_page_mul_notes}% \ht\b_page_mul_notes\openstrutheight \dp\b_page_mul_notes\openstrutdepth \wd\b_page_mul_notes\zeropoint @@ -890,6 +890,7 @@ \def\page_mul_routine_balance {\bgroup + % why no \forgetall here \page_mul_initialize_variables \widowpenalty\zerocount \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}% @@ -1135,7 +1136,7 @@ % \global\savednoffloats\zerocount % \global\setfalse\c_page_floats_some_waiting % \else -% \global\let\page_floats_column_pop_saved\relax +% \glet\page_floats_column_pop_saved\relax % \fi} % % \let\page_floats_column_pop_saved\relax @@ -1249,7 +1250,7 @@ \xdef\insertionheight{\the\dimen0}% \egroup \else - \global\let\insertionheight\zeropoint + \glet\insertionheight\zeropoint \fi} \def\docolumnroomfloat @@ -1364,7 +1365,7 @@ \global\setbox\currenttopcolumnbox\vbox {\snaptogrid\vbox {\copy\currenttopcolumnbox - \hbox{\vphantom{\vskip\floatheight}}}% known from previous + \hpack{\vphantom{\vskip\floatheight}}}% known from previous \whitespace % nodig ? \blank[\rootfloatparameter\c!spaceafter]}% \else @@ -1848,4 +1849,17 @@ \s!page_otr_command_test_column =\page_mul_command_test_column ] +\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here +\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force +\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top +\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom + +\appendtoks + \flushingcolumnfloatsfalse +\to \everybeforesectionheadhandle + +\appendtoks + \flushingcolumnfloatstrue +\to \everyaftersectionheadhandle + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv index 348c301fc2c..64c4a713498 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-one.mkiv @@ -73,6 +73,7 @@ \else \global\vsize\textheight \fi + \global\advance\vsize\d_page_adapts_delta % alternatively we could set it in builders.buildpage_filter % \ifdim\pagegoal<\maxdimen .. \fi \global\pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax} @@ -141,16 +142,17 @@ {\page_otr_command_flush_top_insertions % this is messy ... we will provide a more tight area (no big deal as we can % do that at the lua end) +% \parfillskip\zeropoint \page_one_registered_text_area_a#1#2% \unvbox % \ifgridsnapping - \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax \prevdepth\openstrutdepth \page_otr_command_flush_bottom_insertions \vfil \else\ifcase\bottomraggednessmode % ragged (default) - \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax + \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax \prevdepth\openstrutdepth \page_otr_command_flush_bottom_insertions \vfil @@ -159,7 +161,7 @@ \page_otr_command_flush_bottom_insertions \or % baseline - \kern\dimexpr\maxdepth-\d_page_one_natural_depth\relax + \vkern\dimexpr\maxdepth-\d_page_one_natural_depth\relax \page_otr_command_flush_bottom_insertions \fi\fi \fakepagenotes}% @@ -228,6 +230,9 @@ \vskip\s_page_one_between_top_insert \egroup} +\let\totaltopinserted\!!zeropoint +\let\totalbotinserted\!!zeropoint + \unexpanded\def\page_one_command_set_top_insertions {\bgroup \ifconditional\c_page_floats_some_waiting @@ -312,38 +317,44 @@ \unexpanded\def\page_one_command_flush_top_insertions {\ifvoid\namedinsertionnumber\s!topfloat\else - \ifgridsnapping - \box\namedinsertionnumber\s!topfloat - \vskip-\topskip - \vskip\strutheight % [xx] new: see icare topbleed - \else - \ifcase\c_page_floats_insertions_topskip_mode - % 0: default, do nothing - \or - % 1: no topskip (crossed fingers) - \vskip-\topskip - \vskip\strutheight - \fi - \unvbox\namedinsertionnumber\s!topfloat - \fi + \page_one_command_flush_top_insertions_indeed % less tracing \fi \global\d_page_floats_inserted_top\zeropoint} +\def\page_one_command_flush_top_insertions_indeed + {\ifgridsnapping + \box\namedinsertionnumber\s!topfloat + \vkern-\topskip + \vkern\strutheight % [xx] new: see icare topbleed + \else + \ifcase\c_page_floats_insertions_topskip_mode + % 0: default, do nothing + \or + % 1: no topskip (crossed fingers) + \vskip-\topskip % skip ! + \vkern\strutheight + \fi + \unvbox\namedinsertionnumber\s!topfloat + \fi} + \unexpanded\def\page_one_command_flush_bottom_insertions {\ifvoid\namedinsertionnumber\s!bottomfloat\else - \ifgridsnapping - % \floatparameter\c!bottombefore - \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% - % \floatparameter\c!bottomafter - \else - \floatparameter\c!bottombefore - \unvbox\namedinsertionnumber\s!bottomfloat - \floatparameter\c!bottomafter - \fi + \page_one_command_flush_bottom_insertions_indeed \fi \global\d_page_floats_inserted_bottom\zeropoint \global\setfalse\c_page_floats_not_permitted} +\def\page_one_command_flush_bottom_insertions_indeed + {\ifgridsnapping + % \floatparameter\c!bottombefore + \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% + % \floatparameter\c!bottomafter + \else + \floatparameter\c!bottombefore + \unvbox\namedinsertionnumber\s!bottomfloat + \floatparameter\c!bottomafter + \fi} + \unexpanded\def\page_one_command_flush_floats {\global\settrue\c_page_floats_flushing \ifconditional\c_page_floats_some_waiting diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi index ebaf17ebc6d..909f5cd4d1e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-otr.mkvi @@ -97,7 +97,7 @@ \newconstant\c_page_otr_eject_penalty \c_page_otr_eject_penalty -\plustenthousand \newconstant\c_page_otr_super_penalty \c_page_otr_super_penalty -\plustwentythousand -\newcount \c_page_otf_trigger_penalty \c_page_otf_trigger_penalty -100010 +\newcount \c_page_otr_trigger_penalty \c_page_otr_trigger_penalty -100010 \newif \ifinotr % we keep this (name) for old times sake @@ -127,9 +127,9 @@ \endgroup} \unexpanded\def\installoutputroutine#invoke#action% \invoke \action - {\global\advance\c_page_otf_trigger_penalty\minusone - \edef#invoke{\page_otr_trigger{\number\c_page_otf_trigger_penalty}}% - \setvalue{\??otrtriggers\number\c_page_otf_trigger_penalty}{#action}} + {\global\advance\c_page_otr_trigger_penalty\minusone + \edef#invoke{\page_otr_trigger{\number\c_page_otr_trigger_penalty}}% + \setvalue{\??otrtriggers\number\c_page_otr_trigger_penalty}{#action}} \unexpanded\def\page_otr_triggered_output_routine_traced {\ifcsname\??otrtriggers\the\outputpenalty\endcsname @@ -160,7 +160,7 @@ \ifdefined\everybeforeoutput \else \newtoks\everybeforeoutput \fi \ifdefined\everyafteroutput \else \newtoks\everyafteroutput \fi -\def\page_otf_set_engine_output_routine#content% +\def\page_otr_set_engine_output_routine#content% {\global\output {\inotrtrue \the\everybeforeoutput @@ -172,7 +172,7 @@ % \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi % \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi % -% \def\page_otf_set_engine_output_routine#content% +% \def\page_otr_set_engine_output_routine#content% % {\the\everybeforeoutputgroup % \global\output % {\inotrtrue @@ -187,7 +187,7 @@ % \fi % \to \everyafteroutputgroup -\page_otf_set_engine_output_routine\page_otr_triggered_output_routine +\page_otr_set_engine_output_routine\page_otr_triggered_output_routine \installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead {\ifvoid\normalpagebox\else diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-pcl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-pcl.mkiv index 53d9f781dbf..140444fc27b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-pcl.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-pcl.mkiv @@ -30,19 +30,18 @@ \definemeasure[threecolumns][\dimexpr\plusthree\columnwidth+\plustwo \columndistance\relax] \definemeasure[fourcolumns] [\dimexpr\plusfour \columnwidth+\plusthree\columndistance\relax] -\newcount\c_page_col_n_of_columns \c_page_col_n_of_columns\plusone -\newcount\c_page_col_current \c_page_col_current \plusone -\newdimen\d_page_col_distance -\newdimen\d_page_col_max_height -\newdimen\d_page_col_max_width -%newdimen\d_page_col_balance_step -\newdimen\d_page_col_column_width - -\newdimen\d_page_col_top_height -\newdimen\d_page_col_top_width - -\newdimen\d_page_col_available -\newdimen\d_page_col_sofar +\newcount \c_page_col_n_of_columns \c_page_col_n_of_columns\plusone +\newcount \c_page_col_current \c_page_col_current \plusone +\newdimen \d_page_col_distance +\newdimen \d_page_col_max_height +\newdimen \d_page_col_max_width +%newdimen \d_page_col_balance_step +\newdimen \d_page_col_column_width +\newdimen \d_page_col_top_height +\newdimen \d_page_col_top_width +\newdimen \d_page_col_available +\newdimen \d_page_col_sofar +\newconditional\c_page_col_page %D We need to step over empty columns. @@ -700,6 +699,7 @@ \setuppagecolumns [\c!distance=1.5\bodyfontsize, \c!n=\plustwo, + \c!page=\v!yes, %\c!align=, % inherit (also replaces tolerance) %\c!before=, %\c!after=, @@ -727,9 +727,39 @@ \ifdefined \columnwidth \else \newdimen\columnwidth \fi \ifdefined \columndistance \else \newdimen\columndistance \fi +\def\page_col_pickup_preceding + {\begingroup + \setupoutputroutine[\s!mixedcolumn]% + \c_page_mix_routine\c_page_mix_routine_intercept + \page_otr_trigger_output_routine + \ifvoid\b_page_mix_preceding \else + % moved here, before the packaging + \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding + % we need to avoid unvboxing with successive balanced on one page + \global\setbox\b_page_mix_preceding\vbox\bgroup + % yes or no: \forcestrutdepth + \unvbox\b_page_mix_preceding + \forcestrutdepth + \egroup + \wd\b_page_mix_preceding\makeupwidth + \global\d_page_mix_preceding_height\ht\b_page_mix_preceding + \fi + \endgroup} + +\def\page_col_flush_preceding + {\ifvoid\b_page_mix_preceding \else + % this is just one method but ok for now + \begingroup + % we might need more but for now this is ok + \setupfloat[\c!spacebefore=,\c!spaceafter=]% + \startplacefigure[\c!location={\v!top,\v!none}]% + \box\b_page_mix_preceding + \stopplacefigure + \endgroup + \fi} + \unexpanded\def\startpagecolumns - {\page - \begingroup + {\begingroup \begingroup \dosingleempty\page_col_start} @@ -738,6 +768,15 @@ {\let\currentpagecolumns\empty \setuppagecolumns[#1]}% {\edef\currentpagecolumns{#1}}% + \edef\p_page{\pagecolumnsparameter\c!page}% + \ifx\p_page\empty + \setfalse\c_page_col_page + \else\ifx\p_page\v!no + \setfalse\c_page_col_page + \else + \settrue\c_page_col_page + \page[\p_page]% + \fi\fi \c_page_col_n_of_columns\pagecolumnsparameter\c!n\relax \ifnum\c_page_col_n_of_columns>\plusone \expandafter\page_col_start_yes @@ -769,13 +808,21 @@ \useblankparameter \pagecolumnsparameter % \useprofileparameter\pagecolumnsparameter % - \usemixedcolumnscolorparameter\c!color + \usepagecolumnscolorparameter\c!color % \setupnotes[\c!width=\textwidth]% % \usesetupsparameter\pagecolumnsparameter % + % This will become a method but for now it's good enough + % + \ifconditional\c_page_col_page\else + \page_col_pickup_preceding + \fi \setupoutputroutine[\s!pagecolumn]% + \ifconditional\c_page_col_page\else + \page_col_flush_preceding + \fi % \setupfloats[\c!ntop=\plusthousand]% % \setupfloats[\c!nbottom=\plusthousand]% diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv index 19adfaa9c17..85da8d9e5fb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-run.mkiv @@ -153,6 +153,7 @@ \v!right=>\c_page_grids_lineno_mode \plusone, \v!left=>\c_page_grids_lineno_mode \plustwo, \v!outer=>\c_page_grids_lineno_mode \plusthree, + \v!inner=>\c_page_grids_lineno_mode \plusfour, \v!columns=>\c_page_grids_columns_mode\plusone]% new option \ifcase\c_page_grids_location \let\page_grids_add_to_box\gobbleoneargument @@ -179,13 +180,13 @@ \gridboxlinemode \c_page_grids_line_mode \gridboxlinenomode\c_page_grids_lineno_mode \setgridbox\scratchbox\makeupwidth\textheight % todo: check color - \global\setbox#1\hbox % global ? + \global\setbox#1\hpack % global ? {\ifcase\c_page_grids_location\or\or\box#1\hskip-\makeupwidth\fi \begingroup % color \ifcase\layoutcolumns\else \gray \setlayoutcomponentattribute{\v!grid:\v!columns}% - \hbox \layoutcomponentboxattribute to \makeupwidth + \hpack \layoutcomponentboxattribute to \makeupwidth {\dorecurse\layoutcolumns {\hskip\layoutcolumnwidth \ifnum\recurselevel<\layoutcolumns @@ -197,7 +198,7 @@ \hskip-\makeupwidth \fi \setlayoutcomponentattribute{\v!grid:\v!lines}% - \hbox \layoutcomponentboxattribute{\box\scratchbox}% + \hpack \layoutcomponentboxattribute{\box\scratchbox}% \endgroup \ifcase\c_page_grids_location\or\hskip-\makeupwidth\box#1\fi}% \stopcolor} diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi index 335d0118734..e11a50f5b33 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-sel.mkvi @@ -342,7 +342,7 @@ \def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]% {\bgroup \dontcomplain - \global\let\slicedpagenumber\!!zerocount + \glet\slicedpagenumber\!!zerocount \getfiguredimensions[#filename]% \setupcurrentwithpages [\c!offset=\zeropoint,% @@ -366,7 +366,7 @@ \c!header=\zeropoint,\c!footer=\zeropoint]% \fi \dorecurse\noffigurepages - {\global\let\slicedpagenumber\recurselevel + {\glet\slicedpagenumber\recurselevel \ifnum\c_page_selectors_n>\plusone \dorecurse\c_page_selectors_n {\let\slicedpagestepx\recurselevel diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv index 3579e3b4849..dd145b3228c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-set.mkiv @@ -248,8 +248,8 @@ \!!counta#1\relax \fi \fi - \relax % needed ! ! ! ! else lookahead over \fi and \@EA - \@EA\egroup\@EA\scratchcounter\the\!!counta\relax} + \relax % needed ! ! ! ! else lookahead over \fi and \expandafter + \expandafter\egroup\expandafter\scratchcounter\the\!!counta\relax} \def\OTRSETsetcorrectcellht {\bgroup @@ -260,8 +260,8 @@ \restoreglobalbodyfont \fi \advance\!!dimena\strutht - \relax % needed ! ! ! ! else lookahead over \fi and \@EA - \@EA\egroup\@EA\scratchdimen\the\!!dimena\relax} + \relax % needed ! ! ! ! else lookahead over \fi and \expandafter + \expandafter\egroup\expandafter\scratchdimen\the\!!dimena\relax} \def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data} {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone @@ -487,7 +487,7 @@ \let\OTRSETbalht\zeropoint \def\OTRSETreducegridbox % for the moment no difference between methods - {\globallet\OTRSETbalht\zeropoint + {\glet\OTRSETbalht\zeropoint \ifcase\OTRSETbalancemethod % no balancing \else @@ -578,7 +578,7 @@ \else \page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments \fi \fi - \globallet\OTRSETbalht\zeropoint + \glet\OTRSETbalht\zeropoint \egroup \fi} @@ -642,7 +642,7 @@ {\page_set_command_set_vsize} \def\doOTRSETcolumnseparator - {\hbox to \zeropoint{\hss\red\vl\hss}} + {\hpack to \zeropoint{\hss\red\vl\hss}} \let\OTRSETcolumnseparator\relax @@ -754,7 +754,7 @@ \fi}% \ifdim\lastskipinotr>\zeropoint \scratchskip\ht\scratchbox - \setbox\scratchbox\hbox + \setbox\scratchbox\hpack {\lower\strutdepth\box\scratchbox}% \dp\scratchbox\scratchdimen \ht\scratchbox\scratchskip @@ -942,7 +942,7 @@ \fi \ifenoughcolumncells \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells - {\hbox{\copy#1}}% + {\hpack{\copy#1}}% \page_set_command_set_vsize \else \OTRSETsavebox{#1}% @@ -1155,7 +1155,7 @@ %OTRSETprepareforcolumnslot3{#1}% %ruledvskip\columnslotspacing\lineheight \blank[\number\columnslotspacing*\v!line]% - \snaptogrid\hbox to \hsize{\hss\box#1\hss}% strange, why the centering + \snaptogrid\hpack to \hsize{\hss\box#1\hss}% strange, why the centering \blank[\number\columnslotspacing*\v!line]% \else \OTRSETstoreincolumnslotSOMEWHERE2{#1}% @@ -1336,7 +1336,7 @@ % a quick hack ... will be redone % \ifdim\wd\floatbox<\floatwidth \ifhbox\floatbox - \global\setbox\floatbox\hbox{\unhbox\floatbox}% + \global\setbox\floatbox\hpack{\unhbox\floatbox}% \fi \fi % \dp\floatbox\zeropoint @@ -1417,7 +1417,7 @@ {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}% \ifdim\totalcolumnspace>\wd\scratchbox - \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}% + \setbox\scratchbox\hpack to \totalcolumnspace{\hss\box\scratchbox\hss}% \fi \page_set_cell_set\currenthcell\currentvcell\box\scratchbox \egroup @@ -1619,17 +1619,17 @@ \def\dostartcolumnset[#1][#2]% {\increment\columnsetlevel\relax - \global\let\localcolumnmaxcells\!!zerocount + \glet\localcolumnmaxcells\!!zerocount \global\setfalse\OTRSETfinish \ifnum\columnsetlevel=\plusone \bgroup \saveinterlinespace - \globallet\columnsetpage\!!plusone + \glet\columnsetpage\!!plusone \def\currentcolumnset{#2}% \insidecolumnstrue % will be different flag in addition \setupoutputroutine[\s!columnset]% \doifelsenothing{#1} - {\globallet\OTRSETlist\s!default} + {\glet\OTRSETlist\s!default} {\xdef\OTRSETlist{#1}}% \OTRSETstartnextpage \OTRSETassignwidths @@ -1659,7 +1659,7 @@ \global\setbox\OTRfinalpagebox\OTRSETmakegridbox \ht\OTRfinalpagebox\textheight % signals output that there is content \OTRSETdofinaloutput - \globallet\OTRSETbalht\zeropoint + \glet\OTRSETbalht\zeropoint \egroup} {}} @@ -1678,7 +1678,7 @@ \ifvoid\OTRfinalpagebox\else % probably balanced \ifdim\ht\OTRfinalpagebox<\textheight - \snaptogrid[\v!page]\hbox{\box\OTRfinalpagebox}% + \snaptogrid[\v!page]\hpack{\box\OTRfinalpagebox}% \else \box\OTRfinalpagebox \fi @@ -1765,7 +1765,7 @@ \def\OTRSETstartnextpage {\doifsomething\OTRSETlist {\getfromcommacommand[\OTRSETlist][1]% - \global\let\OTRSETidentifier\commalistelement + \glet\OTRSETidentifier\commalistelement \xdef\currentcolumnset{\commalistelement}% \checkcolumnsetparent \let\newcommalistelement\empty @@ -1848,7 +1848,7 @@ {\unvbox\normalpagebox \global\lastskipinotr\lastskip}% \ifdim\lastskipinotr>\zeropoint - \global\setbox\b_page_set_preceding\hbox + \global\setbox\b_page_set_preceding\hpack {\lower\strutdepth\box\b_page_set_preceding}% \fi \dp\b_page_set_preceding\strutdepth @@ -1970,7 +1970,7 @@ \def\columnplaceholder#1#2% {\hbox - {\setbox\scratchbox\hbox to \hsize + {\setbox\scratchbox\hpack to \hsize {\iftracecolumnset \hskip-.5ex% \startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor @@ -2032,7 +2032,7 @@ \def\page_set_place_float_slot {\setbox\floatbox\vbox{\page_otr_command_flush_float_box}% \dp\floatbox\strutdp - \@EA\uppercasestring\floatmethod\to\floatmethod + \expandafter\uppercasestring\floatmethod\to\floatmethod \OTRSETstoreincolumnslot\floatmethod\floatbox \page_floats_report_total} @@ -2337,11 +2337,11 @@ \advance\!!countb \minusone % new (*) \doif{\columntextareaparameter\c!location}\v!depth - {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}% + {\setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}% \dp\scratchbox\zeropoint \ht\scratchbox\!!heighta}% % - \setbox0\hbox + \setbox0\hpack {\ifcase\!!countc \copy\scratchbox % \box \else @@ -2360,7 +2360,7 @@ \advance\!!counta \columntextareaparameter\c!nx \advance\!!counta -\!!countc \advance\!!widtha -\!!widthb - \setbox0\hbox + \setbox0\hpack % {\hskip-\namedlayoutparameter\v!odd\c!backspace {\hskip-\layoutparameter\c!backspace \clip @@ -2560,7 +2560,7 @@ % todo: nboven/onder %\OTRSETstoreincolumnslotHERE\scratchbox \edef\floatmethod{\namedframedtextparameter{\??columnsetspan#1}\c!default}% - \@EA\uppercasestring\floatmethod\to\floatmethod + \expandafter\uppercasestring\floatmethod\to\floatmethod % todo : \v!here -> here enzovoorts \OTRSETstoreincolumnslot\floatmethod\scratchbox \checknextindentation[\namedframedtextparameter{\??columnsetspan#1}\c!indentnext]% @@ -2626,6 +2626,23 @@ % \s!page_otr_command_flush_margin_blocks =\page_set_command_flush_margin_blocks, % not used ] +\installfloatmethod \s!columnset \v!here \page_set_place_float_here +\installfloatmethod \s!columnset \v!force \page_set_place_float_force +\installfloatmethod \s!columnset \v!top \page_set_place_float_top +\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom +\installfloatmethod \s!columnset \v!page \page_set_place_float_page +\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot +\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot +\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot +\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot +\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot +\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot +\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot +\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot +\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot +\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot +\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force + \protect \endinput % extreme examples (1) diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv index 6f5d9f3571f..8033812447b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-sid.mkiv @@ -41,6 +41,9 @@ \newdimen \d_page_sides_progress \newdimen \d_page_sides_page_total +\newdimen \d_page_sides_leftoffset +\newdimen \d_page_sides_rightoffset + %newbox \b_page_sides_bottom \newcount \c_page_sides_lines_done @@ -48,6 +51,7 @@ \newcount \c_page_sides_n_of_lines \newcount \c_page_sides_n_of_hang \newconstant \c_page_sides_float_type +\newcount \c_page_sides_hangafter \newconditional \c_page_sides_short \newconditional \c_page_sides_flag @@ -77,6 +81,9 @@ \newdimen \d_page_sides_progression +\newcount \c_page_sides_m_of_lines +\newconditional \c_page_sides_delayed + \newif \iftracesidefloats % public (might change) %D Defaults: @@ -216,6 +223,8 @@ +\compensatedinnermakeupmargin \relax \fi + \global\d_page_sides_leftoffset \d_page_sides_rightskip + \global\d_page_sides_rightoffset\d_page_sides_leftskip \ifdim\d_page_sides_rightskip>\zeropoint \global\advance\d_page_sides_rightskip\rightskip \fi @@ -394,7 +403,8 @@ \endgroup \else \forcestrutdepth - \fi} + \fi + \page_otr_command_set_vsize} % new \def\page_sides_flush_floats {\par @@ -541,30 +551,43 @@ \def\page_sides_inject_dummy_lines {\par \nointerlineskip + % \ifnum\lastpenalty>\zerocount + % \penalty\plustenthousand + % \fi \dontleavehmode \iftracesidefloats \page_sides_inject_dummy_line_traced \else \page_sides_inject_dummy_line_normal \fi - \vskip-\dimexpr\lineheight+\strutdp\relax + \par + % on an empty page we have topskip, say 12pt + \ignoreparskip + % this can be 18.5pt + \kern-\dimexpr\lineheight+\strutdp\relax + % so we can actually have a -2.5pt skip on top \ignoreparskip \blank[\v!samepage] - \blank[\v!disable]} + \blank[\v!disable] + % now say we are negative now + \ifdim\pagetotal<\zeropoint + % then we're at the top of the page ... quite messy .. i really need to + % make the page builder a bit more flexible .. should we do something now? + \fi} %D Checkers: \def\page_sides_check_floats_after_par {\page_sides_check_floats_indeed \ifdim\d_page_sides_pagetotal=\pagetotal \else - \global\let\page_sides_check_floats\page_sides_check_floats_indeed + \glet\page_sides_check_floats\page_sides_check_floats_indeed \page_sides_flush_floats \global\c_page_sides_n_of_lines\zerocount % here ! \fi} \unexpanded\def\page_sides_flush_floats_after_par {\global\d_page_sides_pagetotal\pagetotal - \global\let\page_sides_check_floats\page_sides_check_floats_after_par} + \glet\page_sides_check_floats\page_sides_check_floats_after_par} \unexpanded\def\page_sides_forget_floats {\global\d_page_sides_vsize\d_page_sides_vsize_reset @@ -651,18 +674,49 @@ \fi \endgroup} +% \def\page_sides_analyse_progress +% {\d_page_sides_progress\d_page_sides_vsize +% \ifconditional\c_page_sides_flag +% \advance\d_page_sides_progress-\d_page_sides_page_total +% \global\setfalse\c_page_sides_flag +% \else +% \advance\d_page_sides_progress-\pagetotal +% \fi} + +% test case +% +% \usemodule[art-01] +% \starttext +% \dorecurse{40}{\line{#1}} +% \placefigure[left]{}{} +% \input ward +% \startitemize +% \item word \item word \item word \item word +% \stopitemize +% \input ward +% \page +% \stoptext + \def\page_sides_analyse_progress - {\d_page_sides_progress\d_page_sides_vsize + {%\page_otr_command_set_vsize % this is new, otherwise topfloats are not taken into account + \d_page_sides_progress\d_page_sides_vsize \ifconditional\c_page_sides_flag \advance\d_page_sides_progress-\d_page_sides_page_total \global\setfalse\c_page_sides_flag \else + \ifdim\dimexpr\d_page_sides_progress+\d_page_sides_bottomtotal\relax>\pagegoal + % we adapt pagegoal because we can already have placed something with + % everypar and we hope that it triggers a flush, see test above + \pagegoal\dimexpr\pagegoal-\d_page_sides_bottomtotal\relax + \fi \advance\d_page_sides_progress-\pagetotal \fi} \def\page_sides_analyse_space {\global\settrue\c_page_sides_flag - \page_sides_force_depth +% \ifdim\pagegoal=\maxdimen +% \pagegoal\textheight % maybe +% \fi \global\d_page_sides_page_total \pagetotal % global \ifnum\c_page_sides_float_type<\plusfour \global\d_page_sides_width \zeropoint @@ -716,8 +770,18 @@ %D As we have no clear end of one or more paragraphs we only have pre float %D skips. -\def\page_sides_handle_float#1% grid (4) is rather experimental - {\page_sides_check_horizontal_skips +\newconstant\c_page_sides_page_method % will be: \c_page_sides_page_method\plusone + +\def\page_otr_force_new_page_one + {\vskip\d_page_sides_height + \penalty\outputpenalty + \vskip-\dimexpr\d_page_sides_height-\strutdp\relax + \prevdepth\strutdp} + %\ignoreparskip} + +\def\page_sides_handle_float#1% + {\page_sides_initialize_checker + \page_sides_check_horizontal_skips \page_sides_check_vertical_skips \page_sides_apply_horizontal_shift \page_sides_check_previous_float @@ -726,13 +790,26 @@ \page_sides_relocate_float{#1}% \page_sides_apply_vertical_shift \page_sides_analyse_space - \ifconditional\c_page_floats_room \else - \page_otr_fill_and_eject_page + \ifconditional\c_page_floats_room + \global\setfalse\c_page_sides_delayed + % we're ok + \else + \global\settrue\c_page_sides_delayed + \global\c_page_sides_m_of_lines\c_page_sides_n_of_lines + \ifcase\c_page_sides_page_method + \page_otr_fill_and_eject_page + \or + \page_otr_force_new_page_one + \else + \page_otr_fill_and_eject_page + \fi + \global\c_page_sides_n_of_lines\c_page_sides_m_of_lines \page_sides_analyse_space %\page_sides_inject_before \page_sides_inject_dummy_lines \fi \page_sides_place_float + \global\setfalse\c_page_sides_delayed \page_sides_check_floats_reset \page_sides_wrapup} @@ -740,8 +817,7 @@ {% we need to do this aftergroup \aftergroup\par \aftergroup\ignoreparskip - \aftergroup\ignorespaces - } + \aftergroup\ignorespaces} \def\page_sides_check_floats_indeed {\page_sides_analyse_progress @@ -752,7 +828,16 @@ \fi \parskip\s_spac_whitespace_parskip} % not needed -\let\page_sides_check_floats\page_sides_check_floats_indeed +% \let\page_sides_check_floats\page_sides_check_floats_indeed + +\let\page_sides_check_floats\relax + +\def\page_sides_initialize_checker + {\ifx\page_sides_check_floats\relax + \glet\page_sides_check_floats\page_sides_check_floats_indeed + \clf_enablesidefloatchecker + \glet\page_sides_initialize_checker\relax + \fi} \unexpanded\def\page_sides_check_floats_tracer {\begingroup @@ -771,8 +856,30 @@ \fi \endgroup} +% tricky test: + +% \starttext +% \dorecurse{33}{\line{#1}} +% \placefigure[left]{}{} +% \input ward +% \startitemize +% \item word \item word \item word \item word +% \stopitemize +% \input ward +% \page +% \placefigure[left]{}{} +% \dontleavehmode \begingroup \input ward \par \endgroup +% \dontleavehmode \begingroup \input ward \par \endgroup +% \dontleavehmode \begingroup \input ward \par \endgroup +% \input ward +% \stoptext + \unexpanded\def\page_sides_check_floats_set {\edef\p_sidethreshold{\floatparameter\c!sidethreshold}% + \ifconditional\c_page_sides_delayed + % For Alan's hanging right float that moved to the next page. + \d_page_sides_progress\zeropoint + \fi \ifx\p_sidethreshold\v!old \d_page_sides_progression\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax \c_page_sides_n_of_hang\d_page_sides_progression @@ -785,8 +892,14 @@ \dimexpr\d_page_sides_progress-\p_sidethreshold\relax \fi \getnoflines\d_page_sides_progression + % this can be an option + \ifdim\dimexpr\noflines\lineheight>\dimexpr\pagegoal-\pagetotal\relax + \getrawnoflines\d_page_sides_progression + \fi + % \c_page_sides_n_of_hang\noflines \fi + \global\c_page_sides_hangafter\zerocount \ifnum\c_page_sides_n_of_hang>\zerocount \ifcase\c_page_sides_n_of_lines \else @@ -822,6 +935,7 @@ \else \hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width \hangafter-\c_page_sides_n_of_hang + \global\c_page_sides_hangafter\hangafter \fi \fi \global\advance\c_page_sides_checks_done \plusone @@ -830,7 +944,16 @@ \fi} \unexpanded\def\page_sides_check_floats_reset - {\global\c_page_sides_checks_done\zerocount} + {\ifcase\c_page_sides_checks_done\else + \ifcase\c_page_sides_hangafter\else + % we need to deal with par's ending in a group which would restore + % hang parameters + \global\c_page_sides_hangafter\zerocount + \hangindent\zeropoint + \fi + % \global % no, otherwise a next hangindent won't work + \c_page_sides_checks_done\zerocount + \fi} \unexpanded\def\page_sides_synchronize_floats {\ifinner \else diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-smp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-smp.mkiv new file mode 100644 index 00000000000..2711c9944f7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/page-smp.mkiv @@ -0,0 +1,59 @@ +%D \module +%D [ file=page-smp, % was: core-mul, page-mul +%D version=1998.03.15, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Simple Multi Column Output, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +%D The old one: + +\definemixedcolumns + [\v!columns] + % compatible with columns default : + [\c!balance=\v!yes, + \c!blank={\v!line,\v!fixed}] + +\unexpanded\def\setupcolumns + {\setupmixedcolumns[\v!columns]} + +%D This will be replaced by mixed box. + +\unexpanded\def\startsimplecolumns + {\dosingleempty\page_simple_start} + +\def\page_simple_start[#1]% + {\bgroup + \setsimplecolumnshsize[#1]% + \nopenalties + \setbox\scratchbox\vbox\bgroup + \forgetall} % \blank[\v!disable] + +\unexpanded\def\stopsimplecolumns + {\removebottomthings + \egroup + \rigidcolumnbalance\scratchbox + \egroup} + +\unexpanded\def\setsimplecolumnshsize[#1]% + {\getdummyparameters + [\c!width=\hsize, + \c!distance=1.5\bodyfontsize, + \c!n=2, + \c!lines=0, + #1]% + \edef\rigidcolumnlines + {\directdummyparameter\c!lines}% + \setrigidcolumnhsize + {\directdummyparameter\c!width}% + {\directdummyparameter\c!distance}% + {\directdummyparameter\c!n}} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv index dc1e013d50d..bb95ee467b1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-spr.mkiv @@ -23,15 +23,32 @@ % beware, ugly overload, to be redone +% \def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear +% {\setbox#1\hbox +% {\setlayoutcomponentattribute{\v!page:\v!text}% +% \vbox \layoutcomponentboxattribute to \textheight +% {\offinterlineskip +% \freezetextwidth +% \hsize\textwidth % local variant of \sethsize +% \boxmaxdepth\maxdepth +% \noindent % content can be < \hsize +% \page_otr_command_package_contents#2#3}}% +% \dp#1\zeropoint +% \ifconditional\c_page_spread_busy +% \normalsettextpagecontent_spread{#1}% +% \else +% \normalsettextpagecontent_normal{#1}% +% \fi} + \def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear - {\setbox#1\hbox + {\setbox#1\hpack {\setlayoutcomponentattribute{\v!page:\v!text}% - \vbox \layoutcomponentboxattribute to \textheight + \vpack \layoutcomponentboxattribute to \textheight {\offinterlineskip \freezetextwidth \hsize\textwidth % local variant of \sethsize \boxmaxdepth\maxdepth - \noindent % content can be < \hsize + \noindent % content can be < \hsize \page_otr_command_package_contents#2#3}}% \dp#1\zeropoint \ifconditional\c_page_spread_busy @@ -40,12 +57,18 @@ \normalsettextpagecontent_normal{#1}% \fi} +% \def\normalsettextpagecontent_normal#1% +% {\setbox#1\hbox to \makeupwidth +% {\hss\box#1\hss}} % never change the \hss's + \def\normalsettextpagecontent_normal#1% - {\setbox#1\hbox to \makeupwidth - {\hss\box#1\hss}} % never change the \hss's + {\ifdim\wd#1=\makeupwidth\else + \setbox#1\hpack to \makeupwidth + {\hss\box#1\hss}% never change the \hss's + \fi} \def\normalsettextpagecontent_spread#1% - {\setbox#1\hbox to \makeupwidth + {\setbox#1\hpack to \makeupwidth {\ifvoid\b_page_spread_content \ifconditional\c_page_spread_once \box#1% diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-str.lua b/Master/texmf-dist/tex/context/base/mkiv/page-str.lua index 4aeffffd80d..ebb49a918c2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-str.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/page-str.lua @@ -20,18 +20,27 @@ local implement = interfaces.implement local nodecodes = nodes.nodecodes -local slide_node_list = nodes.slide -local write_node = nodes.write -local flush_node = nodes.flush -local copy_node_list = nodes.copy_list -local vpack_node_list = nodes.vpack +local nuts = nodes.nuts +local tonut = nodes.tonut +local slide_node_list = nuts.slide +local write_node = nuts.write +local flush_node = nuts.flush +local copy_node_list = nuts.copy_list +local vpack_node_list = nuts.vpack + +local getbox = nuts.getbox +local setlink = nuts.setlink +local getlist = nuts.getlist +local setlist = nuts.setlist +local getwhd = nuts.getwhd +local setwhd = nuts.setwhd local settings_to_array = utilities.parsers.settings_to_array local enableaction = nodes.tasks.enableaction local texgetdimen = tex.getdimen -local texgetbox = tex.getbox +----- texgetbox = tex.getbox local trace_collecting = false trackers.register("streams.collecting", function(v) trace_collecting = v end) local trace_flushing = false trackers.register("streams.flushing", function(v) trace_flushing = v end) @@ -41,7 +50,11 @@ local report_streams = logs.reporter("streams") streams = streams or { } -- might move to the builders namespace local streams = streams -local data, name, stack = { }, nil, { } +-- maybe store head and tail ... first we need usage + +local data = { } +local name = nil +local stack = { } function streams.enable(newname) if newname == "default" then @@ -66,7 +79,7 @@ end function streams.collect(head,where) if name and head and name ~= "default" then - local tail = node.slide(head) + local head = tonut(head) local dana = data[name] if not dana then dana = { } @@ -75,7 +88,7 @@ function streams.collect(head,where) local last = dana[#dana] if last then local tail = slide_node_list(last) - tail.next, head.prev = head, tail + setlink(tail,head) elseif last == false then dana[#dana] = head else @@ -84,9 +97,9 @@ function streams.collect(head,where) if trace_collecting then report_streams("appending snippet %a to slot %s",name,#dana) end - return nil, true + return nil else - return head, false + return head end end @@ -118,7 +131,7 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards for i=1,dn do local di = dana[i] if di then - write_node(copy_node_list(di.list)) -- list, will be option + write_node(copy_node_list(getlist(di))) -- list, will be option end end if copy then @@ -131,8 +144,8 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards for i=1,dn do local di = dana[i] if di then - write_node(di.list) -- list, will be option - di.list = nil + write_node(getlist(di)) -- list, will be option + setlist(di) flush_node(di) end end @@ -167,7 +180,7 @@ function streams.synchronize(list) -- this is an experiment ! local slot = dana[m] if slot then local vbox = vpack_node_list(slot) - local ht, dp = vbox.height, vbox.depth + local wd, ht, dp = getwhd(vbox) if ht > height then height = ht end @@ -191,32 +204,36 @@ function streams.synchronize(list) -- this is an experiment ! local dana = data[name] local vbox = dana[m] if vbox then - local delta_height = height - vbox.height - local delta_depth = depth - vbox.depth + local wd, ht, dp = getwhd(vbox) + local delta_height = height - ht + local delta_depth = depth - dp if delta_height > 0 or delta_depth > 0 then if false then -- actually we need to add glue and repack - vbox.height, vbox.depth = height, depth + setwhd(vbox,false,height,depth) if trace_flushing then report_streams("slot %s of %a with delta (%p,%p) is compensated",m,i,delta_height,delta_depth) end else -- this is not yet ok as we also need to keep an eye on vertical spacing -- so we might need to do some splitting or whatever - local tail = vbox.list and slide_node_list(vbox.list) - local n, delta = 0, delta_height -- for tracing + local list = getlist(vbox) + local tail = list and slide_node_list(list) + local n = 0 + local delta = delta_height -- for tracing while delta > 0 do -- we need to add some interline penalties - local line = copy_node_list(texgetbox("strutbox")) - line.height, line.depth = strutht, strutdp + local line = copy_node_list(getbox("strutbox")) + setwhd(line,false,strutht,strutdp) if tail then - tail.next, line.prev = line, tail + setlink(tail,line) end - tail = line - n, delta = n +1, delta - struthtdp + tail = line + n = n + 1 + delta = delta - struthtdp end - dana[m] = vpack_node_list(vbox.list) - vbox.list = nil + dana[m] = vpack_node_list(getlist(vbox)) + setlist(vbox) flush_node(vbox) if trace_flushing then report_streams("slot %s:%s with delta (%p,%p) is compensated by %s lines",m,i,delta_height,delta_depth,n) @@ -230,6 +247,8 @@ function streams.synchronize(list) -- this is an experiment ! end end +-- hm, nut or node + tasks.appendaction("mvlbuilders", "normalizers", "streams.collect") tasks.disableaction("mvlbuilders", "streams.collect") diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv b/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv index 57a465603b5..354c1f3c3ee 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/page-str.mkiv @@ -56,7 +56,7 @@ \unexpanded\def\disableoutputstream {\inoutputstreamfalse - \global\let\currentoutputstream\s!default + \glet\currentoutputstream\s!default \clf_disablestream} \unexpanded\def\startoutputstream[#1]% diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi index b043b60c7ba..97668c14377 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/page-txt.mkvi @@ -98,8 +98,8 @@ {\expandafter\normalgdef\csname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}} \def\page_layouts_set_element_status_normal#vertical% - {\global\expandafter\let\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal - \global\expandafter\let\csname\??layouttextsreset#vertical\endcsname\relax + {\expandafter\glet\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal + \expandafter\glet\csname\??layouttextsreset#vertical\endcsname\relax \page_layouts_synchronize_element{#vertical}} \def\page_layouts_synchronize_element#vertical% @@ -527,10 +527,10 @@ \page_layouts_place_text_line_right \page_layouts_place_text_line_left \namedlayoutelementparameter\currentlayouttextline\c!after - \kern\zeropoint}% keep the \dp, beware of \vtops, never change this! + \vkern\zeropoint}% keep the \dp, beware of \vtops, never change this! \dp\b_page_layouts_element\zeropoint \box\b_page_layouts_element - \vskip-#height\relax} + \vkern-#height\relax} \let\page_layouts_extra_at_margin_left \plusone \let\page_layouts_extra_at_margin_right\plustwo @@ -831,21 +831,21 @@ \calculatereducedvsizes \swapmargins \offinterlineskip - \vskip\dimexpr-\topheight-\topdistance\relax + \vkern\dimexpr-\topheight-\topdistance\relax \the\toptextcontent - \vskip\dimexpr\topheight+\topdistance\relax + \vkern\dimexpr\topheight+\topdistance\relax \the\headertextcontent - \vskip\dimexpr\headerheight+\headerdistance+\textdistance\relax + \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax \anch_positions_place_anchors - \vskip\dimexpr-\textdistance-\textheight\relax + \vkern\dimexpr-\textdistance-\textheight\relax \the\texttextcontent - \vskip\textheight + \vkern\textheight \the\everyendoftextbody - \vskip\footerdistance + \vkern\footerdistance \the\footertextcontent - \vskip\dimexpr\footerheight+\bottomdistance\relax + \vkern\dimexpr\footerheight+\bottomdistance\relax \the\bottomtextcontent - \vskip\bottomheight + \vkern\bottomheight \vfilll}% \smashbox\b_page_layouts_element \box\b_page_layouts_element} @@ -854,16 +854,20 @@ % \let\page_prepare_backgrounds\gobbleoneargument % \fi +% only for very special controlled cases or experiments: + +\let\page_scale_text_box\gobbleoneargument + \def\page_insert_body#1#2% {\setbox\b_page_layouts_element\vpack {\offinterlineskip \calculatereducedvsizes \calculatehsizes \swapmargins - \vskip\dimexpr\headerheight+\headerdistance+\textdistance\relax + \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax \dontleavehmode %\page_prepare_backgrounds{#2}% - \hbox to \makeupwidth + \hpack to \makeupwidth {\begingroup \swapmargins \goleftonpage @@ -880,6 +884,7 @@ \settextpagecontent\b_page_layouts_element{#1}{#2}% \page_backgrounds_add_to_text\b_page_layouts_element \page_grids_add_to_box\b_page_layouts_element + \page_scale_text_box\b_page_layouts_element \box\b_page_layouts_element \begingroup \ifdim\rightmarginwidth>\zeropoint diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua index be0c771a3e4..e74c7ee18b5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-aut.lua @@ -16,6 +16,7 @@ local lpeg = lpeg local type, next, tostring, tonumber = type, next, tostring, tonumber local concat, sortedhash = table.concat, table.sortedhash local utfsub = utf.sub +local find = string.find local formatters = string.formatters local P, S, C, V, Cs, Ct, Cg, Cf, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Cc @@ -38,6 +39,8 @@ local chardata = characters.data local trace_hashing = false trackers.register("publications.authorhash", function(v) trace_hashing = v end) +local expand_authors = false directives.register("publications.prerollauthor", function(v) expand_authors = v end) + local report = logs.reporter("publications","authors") local report_cite = logs.reporter("publications","cite") @@ -61,8 +64,8 @@ local v_last = interfaces.variables.last local space = lpegpatterns.whitespace local comma = P(",") -local period = P(".") -local dash = P("-") +local period = P(".") + P("{.}") +local dash = P("-") + P("{-}") local firstcharacter = lpegpatterns.utf8byte local utf8character = lpegpatterns.utf8character local p_and = space^1 * (P("and") + P("&&") + P("++")) * space^1 @@ -123,6 +126,8 @@ end local authormap = allocate() publications.authormap = authormap +local prerollcmdstring = publications.prerollcmdstring + local function splitauthor(author,justsplit) local detail, remapped if not justsplit then @@ -142,6 +147,9 @@ local function splitauthor(author,justsplit) end local author = remapped or author local firstnames, vons, surnames, initials, juniors, options + if expand_authors and find(author,"\\btxcmd") then + author = prerollcmdstring(author) + end local split = lpegmatch(commasplitter,author) local n = #split detail = { @@ -151,8 +159,11 @@ local function splitauthor(author,justsplit) if n == 1 then -- {First Middle von Last} local words = lpegmatch(spacesplitter,author) - firstnames, vons, surnames = { }, { }, { } - local i, n = 1, #words + local i = 1 + local n = #words + firstnames = { } + vons = { } + surnames = { } while i <= n do local w = words[i] if is_upper(w) then @@ -190,9 +201,12 @@ local function splitauthor(author,justsplit) elseif n == 2 then -- {Last, First} -- {von Last, First} - firstnames, vons, surnames = { }, { }, { } local words = lpegmatch(spacesplitter,split[1]) - local i, n = 1, #words + local i = 1 + local n = #words + firstnames = { } + vons = { } + surnames = { } while i <= n do local w = words[i] if is_upper(w) then @@ -202,21 +216,25 @@ local function splitauthor(author,justsplit) end end while i <= n do - surnames[#surnames+1], i = words[i], i + 1 + surnames[#surnames+1] = words[i] + i = i + 1 end -- local words = lpegmatch(spacesplitter,split[2]) - local i, n = 1, #words + local i = 1 + local n = #words while i <= n do local w = words[i] if is_upper(w) then - firstnames[#firstnames+1], i = w, i + 1 + firstnames[#firstnames+1] = w + i = i + 1 else break end end while i <= n do - vons[#vons+1], i = words[i], i + 1 + vons[#vons+1] = words[i] + i = i + 1 end if surnames and firstnames and #surnames == 0 then -- safeguard @@ -308,12 +326,14 @@ local function the_initials(initials,symbol,connector) if not connector then connector = "-" end - local result, r = { }, 0 + local result = { } + local r = 0 for i=1,#initials do local initial = initials[i] if type(initial) == "table" then -- J.-J. - local set, s = { }, 0 + local set = { } + local s = 0 for i=1,#initial do if i > 1 then s = s + 1 ; set[s] = connector @@ -825,8 +845,10 @@ local p_clean = Cs ( ( + lpeg.patterns.utf8character )^1) +-- Probabbly more robust is a two pass approach. + authorhashers.short = function(authors) - -- a short is a real dumb hardcodes kind of tag and we only support + -- a short is a real dumb hardcoded kind of tag and we only support -- this one because some users might expect it, not because it makes -- sense if type(authors) == "table" then diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua index 310df82f38a..f09e97a8d9f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-dat.lua @@ -22,6 +22,10 @@ if not characters then dofile(resolvers.findfile("char-tex.lua")) end +if not utilities.sequencers then + dofile(resolvers.findfile("util-seq.lua")) +end + local lower, find, sub = string.lower, string.find, string.sub local concat, copy, tohash = table.concat, table.copy, table.tohash local next, type, rawget, tonumber = next, type, rawget, tonumber @@ -30,7 +34,7 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns local textoutf = characters and characters.tex.toutf local settings_to_hash, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.settings_to_array local formatters = string.formatters -local sortedkeys, sortedhash, keys = table.sortedkeys, table.sortedhash, table.keys +local sortedkeys, sortedhash, keys, sort = table.sortedkeys, table.sortedhash, table.keys, table.sort local xmlcollected, xmltext, xmlconvert = xml.collected, xml.text, xml.convert local setmetatableindex = table.setmetatableindex @@ -439,7 +443,7 @@ do ----- command = P("\\") * (Carg(1) * C(R("az","AZ")^1) * space^0 / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end) local command = P("\\") * (Carg(1) * C(csletter^1) * space^0 / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end) local whatever = P("\\") * P(" ")^1 / " " - + P("\\") * ( P("hbox") + P("raise") ) -- bah + ----- + P("\\") * ( P("hbox") + P("raise") ) -- bah -- no longer local somemath = P("$") * ((1-P("$"))^1) * P("$") -- let's not assume nested math ----- character = lpegpatterns.utf8character local any = P(1) @@ -482,6 +486,8 @@ do local tags = table.setmetatableindex("table") + local indirectcrossrefs = true + local function do_definition(category,tag,tab,dataset) publicationsstats.nofdefinitions = publicationsstats.nofdefinitions + 1 if tag == "" then @@ -529,11 +535,23 @@ do value = lpegmatch(filter_2,value,1,dataset.commands) -- we need to start at 1 for { } end if normalized == "crossref" then - local parent = luadata[value] - if parent then - setmetatableindex(entries,parent) + if indirectcrossrefs then + setmetatableindex(entries,function(t,k) + local parent = rawget(luadata,value) + if parent == entries then + report_duplicates("bad parent %a for %a in dataset %s",value,hashtag,dataset.name) + setmetatableindex(entries,nil) + return entries + elseif parent then + setmetatableindex(entries,parent) + return entries[k] + else + report_duplicates("no valid parent %a for %a in dataset %s",value,hashtag,dataset.name) + setmetatableindex(entries,nil) + end + end) else - -- warning + dataset.nofcrossrefs = dataset.nofcrossrefs +1 end end entries[normalized] = value @@ -640,16 +658,17 @@ do local somevalue = d_value + b_value + s_value + r_value + n_value + e_value local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0)) - local stripper = lpegpatterns.stripper - value = value / function(s) return lpegmatch(stripper,s) end + local stripper = lpegpatterns.collapser + local stripped = value / function(s) return lpegmatch(stripper,s) end local forget = percent^1 * (1-lineending)^0 local spacing = spacing * forget^0 * spacing - local assignment = spacing * key * spacing * equal * spacing * value * spacing + local replacement= spacing * key * spacing * equal * spacing * value * spacing + local assignment = spacing * key * spacing * equal * spacing * stripped * spacing local definition = category * spacing * left * spacing * tag * spacing * comma * Ct((assignment * comma^0)^0) * spacing * right * Carg(1) / do_definition local crapword = C((1-space-left)^1) - local shortcut = Cmt(crapword,function(_,p,s) return lower(s) == "string" and p end) * spacing * left * ((assignment * Carg(1))/do_shortcut * comma^0)^0 * spacing * right + local shortcut = Cmt(crapword,function(_,p,s) return lower(s) == "string" and p end) * spacing * left * ((replacement * Carg(1))/do_shortcut * comma^0)^0 * spacing * right local comment = Cmt(crapword,function(_,p,s) return lower(s) == "comment" and p end) * spacing * lpegpatterns.argument * Carg(1) / do_comment local casecrap = #S("sScC") * (shortcut + comment) @@ -682,12 +701,37 @@ do statistics.starttiming(publications) publicationsstats.nofbytes = publicationsstats.nofbytes + size current.nofbytes = current.nofbytes + size + current.nofcrossrefs = 0 if source then table.insert(current.sources, { filename = source, checksum = md5.HEX(content) }) current.loaded[source] = kind or true end - current.newtags = #current.luadata > 0 and { } or current.newtags + local luadata = current.luadata + current.newtags = #luadata > 0 and { } or current.newtags lpegmatch(bibtotable,content or "",1,current) + if current.nofcrossrefs > 0 then + for tag, entries in next, luadata do + local value = entries.crossref + if value then + local parent = luadata[value] + if parent == entries then + report_duplicates("bad parent %a for %a in dataset %s",value,hashtag,dataset.name) + elseif parent then + local t = { } + for k, v in next, parent do + if not entries[k] then + entries[k] = v + t[#t+1] = k + end + end + sort(t) + entries.inherited = concat(t,",") + else + report_duplicates("no valid parent %a for %a in dataset %s",value,hashtag,dataset.name) + end + end + end + end statistics.stoptiming(publications) end @@ -708,22 +752,27 @@ do local compact = false -- can be a directive but then we also need to deal with newlines ... not now - function publications.converttoxml(dataset,nice,dontstore,usedonly,subset) -- we have fields ! + function publications.converttoxml(dataset,nice,dontstore,usedonly,subset,noversion,rawtoo) -- we have fields ! local current = datasets[dataset] local luadata = subset or (current and current.luadata) if luadata then statistics.starttiming(publications) -- local result, r, n = { }, 0, 0 - local usedonly = usedonly and publications.usedentries() + if usedonly then + usedonly = publications.usedentries() + usedonly = usedonly[current.name] + end -- r = r + 1 ; result[r] = "" - r = r + 1 ; result[r] = "" + r = r + 1 ; result[r] = formatters[""](current.name) -- if nice then -- will be default local f_entry_start = formatters[" "] local s_entry_stop = " " local f_field = formatters[" %s"] + local f_cdata = formatters[" "] + for tag, entry in sortedhash(luadata) do if not usedonly or usedonly[tag] then r = r + 1 ; result[r] = f_entry_start(tag,entry.category,entry.index) @@ -737,6 +786,11 @@ do end end end + if rawtoo then + local s = publications.savers.bib(current,false,{ [tag] = entry }) + s = utilities.strings.striplines(s,"prune and collapse") + r = r + 1 ; result[r] = f_cdata(s) + end r = r + 1 ; result[r] = s_entry_stop n = n + 1 end @@ -766,7 +820,7 @@ do -- r = r + 1 ; result[r] = "" -- - result = concat(result,nice and "\n" or nil) + result = concat(result,nice and "\n" or nil,noversion and 2 or 1,#result) -- if dontstore then -- indeed @@ -1084,7 +1138,7 @@ do \ifdefined\btxcmd % we're probably in context \else - \def\btxcmd#1{\csname#1\endcsname} + \def\btxcmd#1{\begincsname#1\endcsname} \fi } @@ -1094,8 +1148,8 @@ do local f_start = formatters["@%s{%s,\n"] local f_field = formatters[" %s = {%s},\n"] local s_stop = "}\n\n" - local result = { s_preamble } - local n, r = 0, 1 + local result = { } + local n, r = 0, 0 for tag, data in sortedhash(tobesaved) do r = r + 1 ; result[r] = f_start(data.category or "article",tag) for key, value in sortedhash(data) do @@ -1106,8 +1160,16 @@ do r = r + 1 ; result[r] = s_stop n = n + 1 end - report("%s entries from dataset %a saved in %a",n,dataset,filename) - io.savedata(filename,concat(result)) + result = concat(result) + if find(result,"\\btxcmd") then + result = s_preamble .. result + end + if filename then + report("%s entries from dataset %a saved in %a",n,dataset,filename) + io.savedata(filename,result) + else + return result + end end function savers.lua(dataset,filename,tobesaved) @@ -1127,8 +1189,8 @@ do table.save(filename,list) end - function savers.xml(dataset,filename,tobesaved) - local result, n = publications.converttoxml(dataset,true,true,false,tobesaved) + function savers.xml(dataset,filename,tobesaved,rawtoo) + local result, n = publications.converttoxml(dataset,true,true,false,tobesaved,false,rawtoo) report("%s entries from dataset %a saved in %a",n,dataset,filename) io.savedata(filename,result) end @@ -1175,6 +1237,8 @@ do return dataset end + publications.savers = savers + if implement then implement { @@ -1248,3 +1312,18 @@ do writers.pagenumber = writers.range end + +if implement then + + implement { + name = "btxshortcut", + arguments = "2 strings", + actions = function(instance,key) + local d = publications.datasets[instance] + context(d and d.shortcuts[key] or "?") + end, + } + +end + +-- inspect(publications.load { filename = "e:/tmp/oeps.bib" }) diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi index cd78a879959..160cc452209 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-apa.mkvi @@ -432,8 +432,44 @@ \c!style=\v!italic] \definebtx + [apa:\s!cite:subtitle] + [apa:\s!cite:title] + +\definebtx + [apa:\s!cite:booktitle] + [apa:\s!cite:title] + +\definebtx + [apa:\s!cite:subbooktitle] [apa:\s!cite:booktitle] + +% Will these get used? + +\definebtx + [apa:\s!cite:title:inbook] [apa:\s!cite:title] + [\c!style=] % not italic + +\definebtx + [apa:\s!cite:title:incollection] + [apa:\s!cite:title:inbook] + +\definebtx + [apa:\s!cite:title:inproceedings] + [apa:\s!cite:title:inbook] + +\definebtx + [apa:\s!cite:subtitle:inbook] + [apa:\s!cite:title:inbook] + +\definebtx + [apa:\s!cite:subtitle:incollection] + [apa:\s!cite:title:incollection] + +\definebtx + [apa:\s!cite:subtitle:inproceedings] + [apa:\s!cite:title:inproceedings] + \definebtx [apa:\s!cite:tag] @@ -441,7 +477,6 @@ [\c!left={[}, \c!right={]}] - \definebtx [apa:\s!cite:index] [apa:\s!cite] @@ -679,6 +714,50 @@ \fastsetup{\s!btx:\s!cite:author:years} \stopsetups +% these setups need to be explicitly defined in order to get cite rendering + +\startsetups \s!btx:apa:\s!cite:organization + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:subtitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:booktitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:subbooktitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +% are these needed? + +\startsetups \s!btx:apa:\s!cite:title:inbook + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:title:incollection + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:title:inproceedings + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:subtitle:inbook + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:subtitle:incollection + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:apa:\s!cite:subtitle:inproceedings + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + % used in publ-imp-page.mkvi \startsetups btx:apa:list:page-or-pages @@ -797,7 +876,7 @@ % A book might have an editor AND an author \doif {\currentbtxcategory} {book} { \doifnot {\btxfoundname{author}} {editor} { - \btxdoif {ineditor} { % ineditor authorconversion + \btxdoif {ineditor} { % ineditor specific authorconversion \btxleftparenthesis \btxflush{ineditor} \btxcomma @@ -973,11 +1052,11 @@ \starttexdefinition unexpanded btx:apa:editor-in \btxdoif {booktitle} { \btxlabeltext{In} + \btxspace \doifnot {\btxfoundname{author}} {editor} { - \btxspace \texdefinition{btx:apa:author-or-editor} {ineditor} + \btxcomma } - \btxspace \texdefinition{btx:apa:composed-title}{booktitle} \btxperiod } diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi index 8fe96429d1b..56af83a1b15 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-imp-cite.mkvi @@ -232,9 +232,6 @@ \startsetups \s!btx:\s!cite:pages \fastsetup{\s!btx:\s!cite:range} \stopsetups -\startsetups \s!btx:\s!cite:organization - \fastsetup{\s!btx:\s!cite:range} -\stopsetups % is the next one used? % Yes, bibtex is a mess and one can have pages or sometimes page diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-inc.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-inc.lua new file mode 100644 index 00000000000..9231be3c192 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-inc.lua @@ -0,0 +1,26 @@ +if not modules then modules = { } end modules ['publ-inc'] = { + version = 1.001, + comment = "this module part of publication support", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local fullstrip = string.fullstrip +local datasets, savers = publications.datasets, publications.savers +local assignbuffer = buffers.assign + +interfaces.implement { + name = "btxentrytobuffer", + arguments = "3 strings", + actions = function(dataset,tag,target) + local d = datasets[dataset] + if d then + d = d.luadata[tag] + end + if d then + d = fullstrip(savers.bib(dataset,false,{ [tag] = d })) + end + assignbuffer(target,d or "") + end +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-inc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-inc.mkiv new file mode 100644 index 00000000000..c1728f44a4f --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-inc.mkiv @@ -0,0 +1,63 @@ +%D \module +%D [ file=publ-inc, +%D version=2018.06.23, +%D title=\CONTEXT\ Publication Macros, +%D subtitle=XML inclusion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Publication Macros / XML inclusion} + +\registerctxluafile{publ-inc}{} + +%D A teaser for Alan. + +\unprotect + +\definesymbol[btxattachment][{\infofont\darkred btx}] +\definesymbol[btxcomment] [{\infofont\darkblue btx}] + +\unexpanded\def\btx_add_blob#1#2% + {\relax + \clf_btxentrytobuffer{\currentbtxdataset}{\currentbtxtag}{temp-btx-export}% + #2% + [\c!symbol=#1,% + \c!space=\v!yes, + \c!buffer=temp-btx-export,% + \c!name={\currentbtxtag.bib}]% + \relax} + +\unexpanded\def\btxattach + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \btx_add_blob{btxattachment}\attachment + \dostoptagged + \fi \fi \fi} + +\unexpanded\def\btxcomment + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \btx_add_blob{btxcomment}\comment + \dostoptagged + \fi \fi \fi} + +%D This kind of feature creep is not yet configurable, nor documented. + +\unexpanded\def\btxaddsource + {\iftrialtypesetting \else \ifexporting \iflocation + \dostarttagged\t!ignore\empty + \llap{% + \btx_add_blob{btxattachment}\attachment + \quad + \btx_add_blob{btxcomment}\comment + \hskip\leftmargindistance + }% + \dostoptagged + \fi \fi \fi} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua index 9dfeda168cc..f62352f07f0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.lua @@ -32,7 +32,7 @@ local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash local setmetatableindex = table.setmetatableindex local lpegmatch = lpeg.match local P, S, C, Ct, Cs, R, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.R, lpeg.Carg -local upper = utf.upper +local upper = characters.upper local report = logs.reporter("publications") local report_cite = logs.reporter("publications","cite") @@ -229,9 +229,9 @@ logs.registerfinalactions(function() logs.startfilelogging(report,"used btx commands") done = true end - if isdefined[command] then + if isdefined(command) then report("%-20s %-20s % 5i %s",name,command,n,"known") - elseif isdefined[upper(command)] then + elseif isdefined(upper(command)) then report("%-20s %-20s % 5i %s",name,command,n,"KNOWN") else report("%-20s %-20s % 5i %s",name,command,n,"unknown") @@ -246,7 +246,7 @@ logs.registerfinalactions(function() logs.starterrorlogging(report,"unknown btx commands") for name, dataset in sortedhash(datasets) do for command, n in sortedhash(dataset.commands) do - if not isdefined[command] and not isdefined[upper(command)] then + if not isdefined(command) and not isdefined(upper(command)) then report("%-20s %-20s % 5i %s",name,command,n,"unknown") end end @@ -1065,14 +1065,17 @@ do -- maybe not redo when already done local function shortsorter(a,b) - local ay, by = a[2], b[2] -- year + local ay = a[2] -- year + local by = b[2] -- year if ay ~= by then return ay < by end - local ay, by = a[3], b[3] -- suffix + local ay = a[3] -- suffix + local by = b[3] -- suffix if ay ~= by then -- bah, bah, bah - local an, bn = tonumber(ay), tonumber(by) + local an = tonumber(ay) + local bn = tonumber(by) if an and bn then return an < bn else @@ -2023,7 +2026,8 @@ do for i=1,nofranges do local r = ranges[i] ctx_btxsetconcat(concatstate(i,nofranges)) - local first, last = r[1], r[2] + local first = r[1] + local last = r[2] ctx_btxsetfirstinternal(first[2].internal) ctx_btxsetfirstpage(first[1]) if last then @@ -2044,7 +2048,8 @@ do } local function identical(a,b) - local na, nb = #a, #b + local na = #a + local nb = #b if na ~= nb then return false end @@ -2056,7 +2061,8 @@ do end return true end - local ha, hb = a.hash, b.hash + local ha = a.hash + local hb = b.hash if ha then return ha == hb end @@ -3456,3 +3462,20 @@ do } end + +do + + local btxstring = "" + + implement { + name = "btxcmdstring", + actions = function() if btxstring ~= "" then context(btxstring) end end, + } + + function publications.prerollcmdstring(str) + btxstring = str or "" + tex.runtoks("t_btx_cmd") + return nodes.toutf(tex.getbox("b_btx_cmd").list) or str + end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv index 9f970547d33..ead46929d44 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/publ-ini.mkiv @@ -107,23 +107,27 @@ %D to split between cite and list here as it only complicates matters (timing) and is %D not clear either. -\let\currentbtxspecification\empty +\let\currentbtxspecification \empty +\let\currentbtxspecificationfallback\empty + +\installmacrostack\currentbtxspecification +\installmacrostack\currentbtxspecificationfallback \unexpanded\def\startbtxrenderingdefinitions[#1]% {\unprotect - \pushmacro\currentbtxspecification + \push_macro_currentbtxspecification \edef\currentbtxspecification{#1}} \unexpanded\def\stopbtxrenderingdefinitions - {\popmacro\currentbtxspecification + {\pop_macro_currentbtxspecification \protect} \unexpanded\def\loadbtxdefinitionfile [#1]{\clf_btxloaddefinitionfile {#1}} \unexpanded\def\loadbtxreplacementfile[#1]{\clf_btxloadreplacementfile{#1}} \unexpanded\def\publ_specification_push#1% - {\pushmacro\currentbtxspecification - \pushmacro\currentbtxspecificationfallback + {\push_macro_currentbtxspecification + \push_macro_currentbtxspecificationfallback \edef\currentbtxspecification{#1}% \edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}% \ifx\currentbtxspecificationfallback\currentbtxspecification @@ -132,8 +136,8 @@ \clf_btxsetspecification{\currentbtxspecification}} \unexpanded\def\publ_specification_pop - {\popmacro\currentbtxspecificationfallback - \popmacro\currentbtxspecification + {\pop_macro_currentbtxspecificationfallback + \pop_macro_currentbtxspecification \clf_btxsetspecification{\currentbtxspecification}} \unexpanded\def\publ_specification_set#1% beware: is global @@ -223,9 +227,6 @@ \installcommandhandler \??btxregister {btxregister} \??btxregister \installcommandhandler \??btxrendering {btxrendering} \??btxrendering -\let\currentbtxcitealternative \empty -\let\currentbtxspecificationfallback\empty - \unexpanded\def\setbtxparameterset#1#2% {\edef\currentbtx {\ifcsname\??btx\currentbtxspecification:#1:#2:\s!parent\endcsname @@ -333,6 +334,11 @@ \expandafter\publ_command_nop \fi{#1}} +\newtoks\t_btx_cmd +\newbox \b_btx_cmd + +\t_btx_cmd{\global\setbox\b_btx_cmd\hpack{\clf_btxcmdstring}} + \let\btxcmd\btxcommand \def\publ_command_yes#1% @@ -341,10 +347,10 @@ \def\publ_command_nop#1% {\ifcsname#1\endcsname \showmessage\m!publications{10}{#1,#1}% - \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname + \expandafter\glet\csname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname \else\ifcsname\utfupper{#1}\endcsname \showmessage\m!publications{10}{#1}{\utfupper{#1}}% - \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname + \expandafter\glet\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname \else \showmessage\m!publications{11}{#1}% \setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}% @@ -385,6 +391,12 @@ \let\btxsetup\fastsetup +\def\btxfield #1{\dostarttagged\t!pubfld{#1}\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\def\btxdetail #1{\dostarttagged\t!pubfld{#1}\clf_btxdetail{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\def\btxflush #1{\dostarttagged\t!pubfld{#1}\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +\def\btxdirect #1{\dostarttagged\t!pubfld{#1}\clf_btxdirect{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged} +%def\btxauthorfield#1{\dostarttagged\t!pubfld{#1}\clf_btxauthorfield \currentbtxauthorindex{#1}\dostoptagged} + %D How complex will we go? Can we assume that e.g. an apa style will not be mixed %D with another one? I think this assumption is okay. For manuals we might want to %D mix but we can work around it. @@ -629,11 +641,13 @@ \unexpanded\def\btxnumberingsetup#1% {\begingroup + \dostarttagged\t!listtag\empty \setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering % brrrr \setbtxlist \btxparameter\c!left % \btxparameter\c!command{\publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}}% \publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}% \btxparameter\c!right + \dostoptagged \endgroup \btx_reset_numbering} % probably not needed @@ -655,21 +669,34 @@ \def\btx_entry_inject_list_text {\publ_fast_setup\plusfour\s!list\s!text} +\ifdefined\dotagpublication \else \let\dotagpublication \gobbletwoarguments \fi + \unexpanded\def\btx_entry_inject {\begingroup + \dostarttagged\t!publication\empty + \dotagpublication\currentbtxdataset\currentbtxtag \redoconvertfont % see (**) in strc-lst, this will become an configuration option \edef\currentbtxcategory{\btxfield{category}}% \ignorespaces \ifconditional\c_btx_list_texts + \dostarttagged\t!listtext\s!left \currentbtxbefore + \dostoptagged \fi + %\dostarttagged\t!listcontent\empty \btx_entry_inject_list_text + %\dostoptagged \ifconditional\c_btx_list_pages + \dostarttagged\t!listpage\empty \btx_entry_inject_pages + \dostoptagged \fi \ifconditional\c_btx_list_texts + \dostarttagged\t!listtext\s!right \currentbtxafter + \dostoptagged \fi + \dostoptagged \endgroup} \unexpanded\def\btxshowentryinline @@ -843,6 +870,8 @@ \expandafter\p_command\expandafter{\number\nofbtxlistentries}\relax \fi \else + \dostarttagged\t!publications\currentbtxrendering + \dostarttagged\t!list{btx}% \startpacked[\v!blank]% % sorting and so \clf_btxpreparelistentries{\currentbtxdataset}% could be put in collect @@ -865,6 +894,8 @@ {\let\currentbtxlistentry\recurselevel \clf_btxflushlistentry{\currentbtxdataset}\currentbtxlistentry\relax}% \stoppacked + \dostoptagged + \dostoptagged \fi \btxrenderingparameter\c!after \fi @@ -978,8 +1009,10 @@ \strc_lists_apply_renderingsetup} \def\btx_entry_indeed - {\btx_list_reference_inject - \btx_entry_inject} + {\dostarttagged\t!listcontent\empty + \btx_list_reference_inject + \btx_entry_inject + \dostoptagged} \def\btx_page_indeed {} @@ -1113,7 +1146,8 @@ \let\btxcitereference\btx_cite_reference_inject -\let\currentbtxnumbering\empty +\let\currentbtxnumbering \empty +\let\currentbtxcitealternative \empty \appendtoks \edef\currentbtxnumbering{\btxrenderingparameter\c!numbering}% @@ -1995,4 +2029,15 @@ \fetchruntimecommand \showbtxfields \f!publ_tra \fetchruntimecommand \showbtxtables \f!publ_tra +%D Some potential crap: +%D +%D Because I consider this bad data management and a weird mix of languages only one +%D accessor is provided. + +\unexpanded\def\btxshortcut + {\dosingleempty\publ_shortcut} + +\def\publ_shortcut[#1]#2% + {\clf_btxshortcut{\iffirstargument#1\else\s!default\fi}{#2}} + \protect diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi index 7634398f8db..0c320cd03bf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-bar.mkvi @@ -138,7 +138,7 @@ \setbox2\hbox{\inheritedinteractionbarframed{\symbol[\interactionparameter\c!symbolset][\v!previouspage]}}% \scratchheight\ht2 % needed because we default to nothing \letinteractionbarparameter\c!strut\v!no - \letinteractionparameter\c!width\zeropoint + % \letinteractionparameter\c!width\zeropoint \scratchcounterone\zerocount % new, was 1 \processallactionsinset [#list] diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi index 8bbd6eeda90..87af29cfb9d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-but.mkvi @@ -11,20 +11,16 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% \restorestandardblank -% better namespace for pos - \writestatus{loading}{ConTeXt Screen Macros / Buttons} \registerctxluafile{scrn-but}{} \unprotect -%D Buttons are just what their names says: things that can be -%D clicked (pushed) on. They are similar to \type{\goto}, -%D except that the text argument is not interpreted. -%D Furthermore one can apply anything to them that can be done -%D with \type{\framed}. +%D Buttons are just what their names says: things that can be clicked (pushed) on. +%D They are similar to \type{\goto}, except that the text argument is not +%D interpreted. Furthermore one can apply anything to them that can be done with +%D \type {\framed}. %D %D \startbuffer %D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer] @@ -119,8 +115,8 @@ %D \overlaybutton[reference] %D \stoptyping %D -%D This command can be used to define overlays an/or can be -%D used in the whatevertext areas, like: +%D This command can be used to define overlays an/or can be used in the whatevertext +%D areas, like: %D %D \starttyping %D \defineoverlay[PrevPage][\overlaybutton{PrevPage}] @@ -128,8 +124,7 @@ %D \setuptexttexts[\overlaybutton{NextPage}] %D \stoptyping %D -%D For practical reasons, this macro accepts square brackets -%D as well as braces. +%D For practical reasons, this macro accepts square brackets as well as braces. \unexpanded\def\overlaybutton {\dosingleempty\scrn_button_overlay} diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi index dec334209db..7710a32dcb5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-fld.mkvi @@ -480,7 +480,7 @@ \let\resetfields\relax -\def\scrn_field_load_scripts{\useJSscripts[fld]\globallet\scrn_field_load_scripts\relax} +\def\scrn_field_load_scripts{\useJSscripts[fld]\glet\scrn_field_load_scripts\relax} \newconditional\fieldlabelshown \newconditional\fieldframeshown @@ -627,11 +627,13 @@ %D Common stuff (obsolete) + \newcount\c_scrn_field_system_n -\def\nextsystemfield - {\global\advance\c_scrn_field_system_n\plusone - \def\currentsystemfield{sys::\number\c_scrn_field_system_n}} +\def\currentsystemfield{sys::\number\c_scrn_field_system_n} + +\unexpanded\def\nextsystemfield + {\global\advance\c_scrn_field_system_n\plusone} %D \CONTEXT\ had tooltips right from the moment that it %D supported fields. Due to the at that moment somewhat @@ -754,7 +756,8 @@ {\ifcsname\??fieldstack#tag\endcsname % already done \else - \setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}% + %setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}% + \setxvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][\normalunexpanded{#settings}]}% \fi} \unexpanded\def\fieldstack @@ -768,26 +771,28 @@ \newbox\b_scrn_fieldstack_box +\definesymbol[\s!empty][] + \def\scrn_fieldstack_add#tag#settings#symbol% {\advance\scratchcounter\plusone \edef\currentfieldstackname{#tag:\number\scratchcounter}% \ifnum\scratchcounter=\fieldcategoryparameter\c!start\relax - \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default={#symbol}]% + \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default={#symbol}]% \else - \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default=]% + \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default=\s!empty]% \fi \setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}% \setcollector [fieldstack] {\fieldbody [\currentfieldstackname] - [\c!option=\v!readonly, + [\c!option={\v!readonly}, \c!width=\wd\b_scrn_fieldstack_box, \c!height=\ht\b_scrn_fieldstack_box, \c!depth=\dp\b_scrn_fieldstack_box, #settings]}} -\def\scrn_fieldstack_construct[#tag][#symbols][#settings]% start=n, 0 == leeg +\unexpanded\def\scrn_fieldstack_construct[#tag][#symbols][#settings]% start=n, 0 == leeg {\iflocation \dontleavehmode \begingroup @@ -822,21 +827,56 @@ \unexpanded\def\overlayrollbutton {\dodoubleargument\scrn_rollbutton_overlay} -\def\scrn_rollbutton_overlay[#regionin][#regionout]% +\unexpanded\def\scrn_rollbutton_overlay[#regionin][#regionout]% + {\iffirstargument + \scrn_rollbutton_overlay_indeed[#regionin][#regionout]% + \else + \expandafter\scrn_rollbutton_overlay_indeed + \fi} + +% \def\scrn_rollbutton_overlay_indeed#regionin#regionout% +% {\iflocation +% \bgroup +% \global\advance\c_scrn_rollbutton_n\plusone +% \definesymbol +% [rollbutton:\number\c_scrn_rollbutton_n] +% [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]% +% \definefieldbody +% [rollbutton:\number\c_scrn_rollbutton_n] +% [\c!type=push, +% \c!regionin={#regionin}, +% \c!regionout={#regionout}, +% \c!values=\currentsystemfield, +% \c!default=\currentsystemfield]% +% \fitfield[\currentsystemfield]% +% \egroup +% \fi} + +\def\scrn_rollbutton_overlay_indeed#regionin#regionout% {\iflocation \bgroup - \global\advance\c_scrn_rollbutton_n\plusone + \global\advance\c_scrn_rollbutton_n_button\plusone + \global\advance\c_scrn_rollbutton_n_symbol\plusone \definesymbol - [rollbutton:\number\c_scrn_rollbutton_n] + [rollsymbol:\number\c_scrn_rollbutton_n_symbol] [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]% - \definefieldbody - [rollbutton:\number\c_scrn_rollbutton_n] - [\c!type=push, - \c!regionin={#regionin}, - \c!regionout={#regionout}, - \c!values=\currentsystemfield, - \c!default=\currentsystemfield]% - \fitfield[\currentsystemfield]% + % \definefieldbody + % [rollbutton:\number\c_scrn_rollbutton_n_button] + % [\c!type=push, + % \c!values=rollsymbol:\number\c_scrn_rollbutton_n_symbol, + % \c!default=rollsymbol:\number\c_scrn_rollbutton_n_symbol]% + % \fitfield + % [rollbutton:\number\c_scrn_rollbutton_n_button]% + % [\c!regionin={#regionin}, + % \c!regionout={#regionout}]% + % + \definefield + [rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton] + [rollsymbol:\number\c_scrn_rollbutton_n_symbol]% + \fitfield + [rollbutton:\number\c_scrn_rollbutton_n_button]% + [\c!regionin={#regionin},\c!regionout={#regionout}]% + % \egroup \fi} @@ -914,7 +954,7 @@ %D We plug into the menu system \unexpanded\def\scrn_menu_psh_start[#reference]#text\stoppsh - {\starttxt\pushbutton[\currentmenu][#reference]\stoptxt} + {\starttxt\pushbutton[\currentinteractionmenu][#reference]\stoptxt} \unexpanded\def\scrn_menu_psh_direct[#reference]#text\\ {\scrn_menu_psh_start[#reference]\stoprob} @@ -956,6 +996,8 @@ \newcount\c_scrn_rollbutton_n_button \newcount\c_scrn_rollbutton_n_symbol +\def\lastrollbuttonindex{\the\c_scrn_rollbutton_n_button} + \unexpanded\def\rollbutton {\dodoubleempty\scrn_rollbutton} @@ -973,11 +1015,16 @@ \setbuttonparameter \usebuttonstyleandcolor} +\setupfield + [rollbutton] + [\c!frame=\v!off, + \c!offset=\v!overlay] + \def\scrn_rollbutton[#tag][#settings]#text[#reference]% {\dontleavehmode \bgroup - \advance\c_scrn_rollbutton_n_button\plusone - \advance\c_scrn_rollbutton_n_symbol\plusone + \global\advance\c_scrn_rollbutton_n_button\plusone + \global\advance\c_scrn_rollbutton_n_symbol\plusone \iffirstargument \ifsecondargument \edef\currentinteractionmenu{#tag}% @@ -994,21 +1041,18 @@ \else \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b \fi - % todo: share symbols, tricky since different dimensions + % todo: share symbols, tricky since different dimensions (maybe \unique...) \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}{#text}]% \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}{#text}]% \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}{#text}]% - \setupfield - [rollbutton] - [\c!frame=\v!off, - \c!offset=\v!overlay, - \c!clickout={#reference}]% \definefield [rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton] [rollsymbol:\number\c_scrn_rollbutton_n_symbol:n,% rollsymbol:\number\c_scrn_rollbutton_n_symbol:r,% rollsymbol:\number\c_scrn_rollbutton_n_symbol:d]% - \fitfield[rollbutton:\number\c_scrn_rollbutton_n_button]% + \fitfield + [rollbutton:\number\c_scrn_rollbutton_n_button]% + [\c!clickout={#reference}]% \egroup} \unexpanded\def\scrn_rollbutton_symbol_indeed#getparameter#inheritedframed#setparameter#usestyleandcolor#what#text% @@ -1023,7 +1067,7 @@ %D We plug into the menu system \unexpanded\def\scrn_menu_rob_start[#reference]#text\stoprob - {\starttxt\rollbutton[\currentmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt} + {\starttxt\rollbutton[\currentinteractionmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt} \unexpanded\def\scrn_menu_rob_direct[#reference]#text\\ {\scrn_menu_rob_start[#reference]#text\stoprob} diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi index e1be43f3782..557ceb5631a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ini.mkvi @@ -61,7 +61,7 @@ \to \everyjob % it makes no sense to create an environment as we will seldom have structured -% interactionso a general start-stop will do +% interactions so a general start-stop will do % % \appendtoks % \setuevalue \currentinteraction {\scrn_interaction_direct{\currentinteraction}}% diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi index 7695443adb2..a3b0a78c61c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-pag.mkvi @@ -188,13 +188,13 @@ \let\scrn_canvas_synchronize_complex\relax \appendtoks - \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed \to \everysetuplayout \appendtoks - \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed \to \everysetuplayouttarget \def\scrn_canvas_synchronize_only @@ -213,8 +213,8 @@ \def\scrn_canvas_synchronize_simple_indeed {\scrn_canvas_synchronize_only - %\global\let\scrn_canvas_synchronize_simple \relax - \global\let\scrn_canvas_synchronize_complex\relax} + %\glet\scrn_canvas_synchronize_simple \relax + \glet\scrn_canvas_synchronize_complex\relax} \def\scrn_canvas_synchronize_complex_indeed {\scrn_canvas_calculate % otherwise we need to hook it into setuppage etc @@ -235,8 +235,8 @@ copies \numexpr\interactionscreenparameter\c!copies\relax print {\interactionscreenparameter\c!print}% \relax - %\global\let\scrn_canvas_synchronize_simple \relax - \global\let\scrn_canvas_synchronize_complex\relax} + %\glet\scrn_canvas_synchronize_simple \relax + \glet\scrn_canvas_synchronize_complex\relax} \appendtoks \begingroup @@ -262,8 +262,8 @@ \c!option=\v!auto] \appendtoks - \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed - \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed + \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed + \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed \to \everysetupinteractionscreen %D Conditional page breaks: diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi index bace1331288..df395e5505b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-ref.mkvi @@ -83,15 +83,15 @@ %D delayed ... -\def\scrn_reference_enable_references - {\ifproductionrun - \clf_enableinteraction % only once anyway - \glet\scrn_reference_enable_references\relax - \fi} - -\appendtoks - \scrn_reference_enable_references -\to \everysetupinteraction +% \def\scrn_reference_enable_references +% {\ifproductionrun +% \clf_enableinteraction % only once anyway +% \glet\scrn_reference_enable_references\relax +% \fi} +% +% \appendtoks +% \scrn_reference_enable_references +% \to \everysetupinteraction \setupinteraction % start fit page and reset form [\c!openaction=, diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi index c74125c72b6..d1571ca656d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/scrn-wid.mkvi @@ -212,11 +212,10 @@ name {\attachmentparameter\c!name}% buffer {\attachmentparameter\c!buffer}% \relax - \setbox\b_scrn_attachment_link\hbox{\scrn_attachment_place}% \wd\b_scrn_attachment_link\currentattachmentwidth \ht\b_scrn_attachment_link\currentattachmentheight \dp\b_scrn_attachment_link\currentattachmentdepth - \box\b_scrn_attachment_link} + \expandnamespaceparameter\??attachmentlocation\attachmentparameter\c!location\s!unknown} \setvalue{\??attachmentmethod\v!hidden}% {\clf_insertattachment @@ -231,29 +230,48 @@ buffer {\attachmentparameter\c!buffer}% \relax} -\def\scrn_attachment_place - {\executeifdefined - {\??attachmentlocation\attachmentparameter\c!location}\hbox - {\box\b_scrn_attachment_link}} - -\setvalue{\??attachmentlocation\v!inmargin }{\inmargin } -\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge } -\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge } -\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin } -\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin} -\setvalue{\??attachmentlocation\v!high }{\high} -\setvalue{\??attachmentlocation\v!none }{\scrn_attachment_collect} -%setvalue{\??attachmentlocation\v!text }{\gobblenextargument} % gobbles the box - -\def\scrn_attachment_collect#content% +\unexpanded\def\scrn_attachment_flush_traced + {\hpack\bgroup + \blackrule % can be a fast one + [ \c!color=trace:r, + \c!width=\wd\b_scrn_attachment_link, + \c!height=\ht\b_scrn_attachment_link, + \c!depth=\dp\b_scrn_attachment_link]% + \kern-\wd\b_scrn_attachment_link + \box\b_scrn_attachment_link + \egroup} + +\unexpanded\def\scrn_attachment_flush_normal + {\box\b_scrn_attachment_link} + +\installtextracker + {attachments.anchors} + {\let\scrn_attachment_flush\scrn_attachment_flush_traced} + {\let\scrn_attachment_flush\scrn_attachment_flush_normal} + +\let\scrn_attachment_flush\scrn_attachment_flush_normal + +\setvalue{\??attachmentlocation\v!inmargin }{\inmargin {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin {\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin{\scrn_attachment_flush}} +\setvalue{\??attachmentlocation\v!high }{\high {\scrn_attachment_flush}} + +\setvalue{\??attachmentlocation\v!none}% {\global\setbox\b_scrn_attachment_collect\hbox\bgroup \ifvoid\b_scrn_attachment_collect\else \box\b_scrn_attachment_collect \hskip\attachmentparameter\c!distance\relax \fi - #content% + \scrn_attachment_flush \egroup} +\setvalue{\??attachmentlocation\s!unknown}% + {\ifvoid\b_scrn_attachment_collect\else + \box\b_scrn_attachment_collect + \fi} + \unexpanded\def\placeattachments {\ifvoid\b_scrn_attachment_collect\else \box\b_scrn_attachment_collect @@ -317,7 +335,7 @@ % % test % -% \startcomment[symbol=Balloon] +% \startcomment[symbol=Help] % Do we want this kind of rubish? % \stopcomment % @@ -360,6 +378,9 @@ % % test +%D The implementation is mostly the same as for attachments but sharing code +%D will not make it cleaner. + \installcorenamespace{comment} \installcorenamespace{commentlocation} @@ -489,17 +510,37 @@ \dp\b_scrn_comment_link\currentcommentdepth \expandnamespaceparameter\??commentlocation\commentparameter\c!location\s!unknown} -\setvalue{\??commentmethods\v!hidden}% - {} +\letvalue{\??commentmethods\v!hidden}\donothing + +\unexpanded\def\scrn_comment_flush_traced + {\hpack\bgroup + \blackrule % can be a fast one + [ \c!color=trace:y, + \c!width=\wd\b_scrn_comment_link, + \c!height=\ht\b_scrn_comment_link, + \c!depth=\dp\b_scrn_comment_link]% + \kern-\wd\b_scrn_comment_link + \box\b_scrn_comment_link + \egroup} + +\unexpanded\def\scrn_comment_flush_normal + {\box\b_scrn_comment_link} + +\installtextracker + {comments.anchors} + {\let\scrn_comment_flush\scrn_comment_flush_traced} + {\let\scrn_comment_flush\scrn_comment_flush_normal} + +\let\scrn_comment_flush\scrn_comment_flush_normal % todo: dedicated margin classes -\setvalue{\??commentlocation\v!inmargin }{\inmargin {\box\b_scrn_comment_link}} -\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\box\b_scrn_comment_link}} -\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\box\b_scrn_comment_link}} -\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\box\b_scrn_comment_link}} -\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\box\b_scrn_comment_link}} -\setvalue{\??commentlocation\v!high }{\high {\box\b_scrn_comment_link}} +\setvalue{\??commentlocation\v!inmargin }{\inmargin {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\scrn_comment_flush}} +\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\scrn_comment_flush}} +\setvalue{\??commentlocation\v!high }{\high {\scrn_comment_flush}} \setvalue{\??commentlocation\v!none}% {\global\setbox\b_scrn_comment_collect\hbox\bgroup @@ -507,7 +548,7 @@ \box\b_scrn_comment_collect \hskip\commentparameter\c!distance\relax \fi - \box\b_scrn_comment_link + \scrn_comment_flush \egroup} \setvalue{\??commentlocation\s!unknown}% diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua index b31dc335a4a..83eecf6a3b3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-cjk.lua @@ -6,23 +6,24 @@ if not modules then modules = { } end modules ['scrp-cjk'] = { license = "see context related readme files" } --- We can speed this up by preallocating nodes and copying them but the --- gain is not that large. - --- The input line endings: there is no way to distinguish between --- inline spaces and endofline turned into spaces (would not make --- sense either because otherwise a wanted space at the end of a --- line would have to be a hard coded ones. +-- We can speed this up by preallocating nodes and copying them but the gain is not +-- that large. +-- +-- If needed we can speed this up (traversers and prev next and such) but cjk +-- documents don't have that many glyphs and certainly not much font processing so +-- there not much gain in it. +-- +-- The input line endings: there is no way to distinguish between inline spaces and +-- endofline turned into spaces (would not make sense either because otherwise a +-- wanted space at the end of a line would have to be a hard coded ones. local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local copy_node = nuts.copy local remove_node = nuts.remove -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph local getnext = nuts.getnext local getprev = nuts.getprev @@ -41,12 +42,14 @@ local new_kern = nodepool.kern local new_penalty = nodepool.penalty local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes + local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue -local userskip_code = skipcodes.userskip -local spaceskip_code = skipcodes.spaceskip -local xspaceskip_code = skipcodes.xspaceskip + +local userskip_code = gluecodes.userskip +local spaceskip_code = gluecodes.spaceskip +local xspaceskip_code = gluecodes.xspaceskip local a_scriptstatus = attributes.private('scriptstatus') local a_scriptinjection = attributes.private('scriptinjection') @@ -439,13 +442,16 @@ local injectors = { -- [previous] [current] local function process(head,first,last) if first ~= last then - local lastfont, previous, last = nil, "start", nil + local lastfont = nil + local previous = "start" + local last = nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming = getnext(first) + local id = getid(first) if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = getattr(first,a_scriptstatus) local current = numbertocategory[a] - local action = injectors[previous] + local action = injectors[previous] if action then action = action[current] if action then @@ -459,12 +465,16 @@ local function process(head,first,last) end previous = current else -- glue - local p, n = getprev(first), upcoming + local p = getprev(first) + local n = upcoming if p and n then - local pid, nid = getid(p), getid(n) + local pid = getid(p) + local nid = getid(n) if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) - local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] + local pa = getattr(p,a_scriptstatus) + local na = getattr(n,a_scriptstatus) + local pcjk = pa and numbertocategory[pa] + local ncjk = na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" or pcjk == "other" or ncjk == "other" @@ -509,10 +519,9 @@ scripts.installmethod { } function scripts.decomposehangul(head) - local head = tonut(head) local done = false - for current in traverse_id(glyph_code,head) do - local lead_consonant, medial_vowel, tail_consonant = decomposed(getchar(current)) + for current, char in nextglyph, head do + local lead_consonant, medial_vowel, tail_consonant = decomposed(char) if lead_consonant then setchar(current,lead_consonant) local m = copy_node(current) @@ -526,7 +535,7 @@ function scripts.decomposehangul(head) done = true end end - return tonode(head), done + return head, done end -- nodes.tasks.prependaction("processors","normalizers","scripts.decomposehangul") @@ -695,13 +704,16 @@ local injectors = { -- [previous] [current] local function process(head,first,last) if first ~= last then - local lastfont, previous, last = nil, "start", nil + local lastfont = nil + local previous = "start" + local last = nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming = getnext(first) + local id = getid(first) if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = getattr(first,a_scriptstatus) local current = numbertocategory[a] - local action = injectors[previous] + local action = injectors[previous] if action then action = action[current] if action then @@ -715,12 +727,16 @@ local function process(head,first,last) end previous = current else -- glue - local p, n = getprev(first), upcoming + local p = getprev(first) + local n = upcoming if p and n then - local pid, nid = getid(p), getid(n) + local pid = getid(p) + local nid = getid(n) if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) - local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] + local pa = getattr(p,a_scriptstatus) + local na = getattr(n,a_scriptstatus) + local pcjk = pa and numbertocategory[pa] + local ncjk = na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" or pcjk == "other" or ncjk == "other" @@ -917,13 +933,16 @@ local injectors = { -- [previous] [current] local function process(head,first,last) if first ~= last then - local lastfont, previous, last = nil, "start", nil + local lastfont = nil + local previous = "start" + local last = nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming = getnext(first) + local id = getid(first) if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = getattr(first,a_scriptstatus) local current = numbertocategory[a] - local action = injectors[previous] + local action = injectors[previous] if action then action = action[current] if action then @@ -940,12 +959,16 @@ local function process(head,first,last) -- upcoming = getnext(end_of_math(current)) -- previous = "start" else -- glue - local p, n = getprev(first), upcoming -- we should remember prev + local p = getprev(first) + local n = upcoming if p and n then - local pid, nid = getid(p), getid(n) + local pid = getid(p) + local nid = getid(n) if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) - local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] + local pa = getattr(p,a_scriptstatus) + local na = getattr(n,a_scriptstatus) + local pcjk = pa and numbertocategory[pa] + local ncjk = na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" or pcjk == "other" or ncjk == "other" diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua index 43cb2ff6a4e..f6a994b884b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-eth.lua @@ -12,71 +12,16 @@ if not modules then modules = { } end modules ['scrp-eth'] = { local nuts = nodes.nuts local getnext = nuts.getnext -local getfont = nuts.getfont -local getid = nuts.getid +local ischar = nuts.ischar local getattr = nuts.getattr -local insert_node_before = nuts.insert_before - -local nodepool = nuts.pool - -local new_glue = nodepool.glue -local new_penalty = nodepool.penalty - local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local a_scriptstatus = attributes.private('scriptstatus') -local a_scriptinjection = attributes.private('scriptinjection') -local categorytonumber = scripts.categorytonumber local numbertocategory = scripts.numbertocategory -local hash = scripts.hash -local numbertodataset = scripts.numbertodataset - -local fonthashes = fonts.hashes -local parameters = fonthashes.parameters - -local space, stretch, shrink, lastfont - -local inter_character_space_factor = 1 -local inter_character_stretch_factor = 1 -local inter_character_shrink_factor = 1 - -local function space_glue(current) - local data = numbertodataset[getattr(current,a_scriptinjection)] - if data then - inter_character_space_factor = data.inter_character_space_factor or 1 - inter_character_stretch_factor = data.inter_character_stretch_factor or 1 - inter_character_shrink_factor = data.inter_character_shrink_factor or 1 - end - local font = getfont(current) - if lastfont ~= font then - local pf = parameters[font] - space = pf.space - stretch = pf.space_stretch - shrink = pf.space_shrink - lastfont = font - end - return new_glue( - inter_character_space_factor * space, - inter_character_stretch_factor * stretch, - inter_character_shrink_factor * shrink - ) -end - -local function insert_space(head,current) - insert_node_before(head,current,space_glue(current)) -end - -local function insert_zerowidthspace(head,current) - insert_node_before(head,current,new_glue(0)) -end - -local function insert_nobreakspace(head,current) - insert_node_before(head,current,new_penalty(10000)) - insert_node_before(head,current,space_glue(current)) -end +local inserters = scripts.inserters -- syllable [zerowidthspace] syllable -- syllable [zerowidthspace] word @@ -88,21 +33,22 @@ end -- sentence [space] word -- sentence [space] sentence + local injectors = { -- [previous] [current] ethiopic_syllable = { - ethiopic_syllable = insert_zerowidthspace, - ethiopic_word = insert_nobreakspace, - ethiopic_sentence = insert_nobreakspace, + ethiopic_syllable = inserters.zerowidthspace_before, + ethiopic_word = inserters.nobreakspace_before, + ethiopic_sentence = inserters.nobreakspace_before, }, ethiopic_word = { - ethiopic_syllable = insert_space, - ethiopic_word = insert_space, - ethiopic_sentence = insert_space, + ethiopic_syllable = inserters.space_before, + ethiopic_word = inserters.space_before, + ethiopic_sentence = inserters.space_before, }, ethiopic_sentence = { - ethiopic_syllable = insert_space, - ethiopic_word = insert_space, - ethiopic_sentence = insert_space, + ethiopic_syllable = inserters.space_before, + ethiopic_word = inserters.space_before, + ethiopic_sentence = inserters.space_before, }, } @@ -111,10 +57,10 @@ local function process(head,first,last) local injector = false local current = first while current do - local id = getid(current) - if id == glyph_code then + local char, id = ischar(current) + if char then local scriptstatus = getattr(current,a_scriptstatus) - local category = numbertocategory[scriptstatus] + local category = numbertocategory[scriptstatus] if injector then local action = injector[category] if action then @@ -122,8 +68,6 @@ local function process(head,first,last) end end injector = injectors[category] - else - -- nothing yet end if current == last then break diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua index 9bd70e30af1..e6aa5f0720c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.lua @@ -22,72 +22,75 @@ local report_splitting = logs.reporter("scripts","splitting") local utfbyte, utfsplit = utf.byte, utf.split local gmatch = string.gmatch -local attributes = attributes -local nodes = nodes -local context = context +local attributes = attributes +local nodes = nodes +local context = context -local texsetattribute = tex.setattribute +local texsetattribute = tex.setattribute -local nodecodes = nodes.nodecodes -local unsetvalue = attributes.unsetvalue +local nodecodes = nodes.nodecodes +local unsetvalue = attributes.unsetvalue -local implement = interfaces.implement +local implement = interfaces.implement -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue +local glyph_code = nodecodes.glyph +local glue_code = nodecodes.glue -local emwidths = fonts.hashes.emwidths -local exheights = fonts.hashes.exheights +local emwidths = fonts.hashes.emwidths +local exheights = fonts.hashes.exheights -local a_scriptinjection = attributes.private('scriptinjection') -local a_scriptsplitting = attributes.private('scriptsplitting') -local a_scriptstatus = attributes.private('scriptstatus') +local a_scriptinjection = attributes.private('scriptinjection') +local a_scriptsplitting = attributes.private('scriptsplitting') +local a_scriptstatus = attributes.private('scriptstatus') -local fontdata = fonts.hashes.identifiers -local allocate = utilities.storage.allocate -local setnodecolor = nodes.tracers.colors.set -local setmetatableindex = table.setmetatableindex +local fontdata = fonts.hashes.identifiers +local allocate = utilities.storage.allocate +local setnodecolor = nodes.tracers.colors.set +local setmetatableindex = table.setmetatableindex -local enableaction = nodes.tasks.enableaction -local disableaction = nodes.tasks.disableaction +local enableaction = nodes.tasks.enableaction +local disableaction = nodes.tasks.disableaction -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode +local nuts = nodes.nuts -local getnext = nuts.getnext -local getchar = nuts.getchar -local getfont = nuts.getfont -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local isglyph = nuts.isglyph +local getnext = nuts.getnext +local getchar = nuts.getchar +local getfont = nuts.getfont +local getid = nuts.getid +local getattr = nuts.getattr +local setattr = nuts.setattr +local isglyph = nuts.isglyph -local insert_node_after = nuts.insert_after -local first_glyph = nuts.first_glyph -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +local insert_node_after = nuts.insert_after +local insert_node_before = nuts.insert_before -local nodepool = nuts.pool +local first_glyph = nuts.first_glyph -local new_glue = nodepool.glue -local new_rule = nodepool.rule -local new_penalty = nodepool.penalty +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextglyph = nuts.traversers.glyph +local nextchar = nuts.traversers.char -scripts = scripts or { } -local scripts = scripts +local nodepool = nuts.pool -scripts.hash = scripts.hash or { } -local hash = scripts.hash +local new_glue = nodepool.glue +local new_rule = nodepool.rule +local new_penalty = nodepool.penalty -local handlers = allocate() -scripts.handlers = handlers +scripts = scripts or { } +local scripts = scripts -local injectors = allocate() -scripts.injectors = handlers +scripts.hash = scripts.hash or { } +local hash = scripts.hash -local splitters = allocate() -scripts.splitters = splitters +local handlers = allocate() +scripts.handlers = handlers + +local injectors = allocate() +scripts.injectors = handlers + +local splitters = allocate() +scripts.splitters = splitters local hash = { -- we could put these presets in char-def.lua -- @@ -206,6 +209,11 @@ local hash = { -- we could put these presets in char-def.lua [0x1361] = "ethiopic_word", [0x1362] = "ethiopic_sentence", -- + -- tibetan: + -- + [0x0F0B] = "breaking_tsheg", + [0x0F0C] = "nonbreaking_tsheg", + } local function provide(t,k) @@ -225,6 +233,7 @@ local function provide(t,k) elseif (k >= 0x01160 and k <= 0x011A7) then v = "jamo_medial" elseif (k >= 0x011A8 and k <= 0x011FF) then v = "jamo_final" elseif (k >= 0x01200 and k <= 0x0139F) then v = "ethiopic_syllable" + elseif (k >= 0x00F00 and k <= 0x00FFF) then v = "tibetan" else v = false end t[k] = v @@ -267,6 +276,7 @@ function scripts.installmethod(handler) report_preprocessing("missing (default) dataset in script %a",name) datasets.default = { } -- slower but an error anyway end + for k, v in next, datasets do setmetatableindex(v,defaults) end @@ -387,6 +397,8 @@ local scriptcolors = allocate { -- todo: just named colors ethiopic_syllable = "trace:1", ethiopic_word = "trace:2", ethiopic_sentence = "trace:3", + breaking_tsheg = "trace:1", + nonbreaking_tsheg = "trace:2", } scripts.colors = scriptcolors @@ -409,6 +421,8 @@ local numbertocategory = allocate { -- rather bound to cjk ... will be generaliz "ethiopic_syllable", "ethiopic_word", "ethiopic_sentence", + "breaking_tsheg", + "nonbreaking_tsheg", } local categorytonumber = allocate(table.swapped(numbertocategory)) -- could be one table @@ -417,7 +431,7 @@ scripts.categorytonumber = categorytonumber scripts.numbertocategory = numbertocategory local function colorize(start,stop) - for n in traverse_id(glyph_code,start) do + for n in nextglyph, start do local kind = numbertocategory[getattr(n,a_scriptstatus)] if kind then local ac = scriptcolors[kind] @@ -450,13 +464,12 @@ end -- we can have a fonts.hashes.originals function scripts.injectors.handler(head) - head = tonut(head) local start = first_glyph(head) -- we already have glyphs here (subtype 1) if not start then - return tonode(head), false + return head else - local last_a, normal_process, lastfont, originals = nil, nil, nil, nil - local done, first, last, ok = false, nil, nil, false + local last_a, normal_process, lastfont, originals, first, last + local ok = false while start do local char, id = isglyph(start) if char then @@ -473,7 +486,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -482,16 +495,15 @@ function scripts.injectors.handler(head) normal_process = handler.injector end if normal_process then - -- wrong: originals are indices ! - local font = getfont(start) - if font ~= lastfont then - originals = fontdata[font].resources + -- id == font + if id ~= lastfont then + originals = fontdata[id].resources if resources then originals = resources.originals else originals = nil -- can't happen end - lastfont = font + lastfont = id end if originals and type(originals) == "number" then char = originals[char] or char @@ -517,7 +529,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -532,7 +544,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -554,7 +566,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - first, last, ok, done = nil, nil, false, true + first, last, ok = nil, nil, false elseif first then first, last = nil, nil end @@ -570,16 +582,15 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - done = true end - return tonode(head), done + return head end end -- kind of experimental .. might move to it's own module -- function scripts.splitters.handler(head) --- return head, false +-- return head -- end local function addwords(tree,data) @@ -701,32 +712,6 @@ end) local categories = characters.categories or { } --- local function hit(root,head) --- local current = getnext(head) --- local lastrun = false --- local lastfinal = false --- while current and getid(current) == glyph_code do --- local char = getchar(current) --- local newroot = root[char] --- if newroot then --- local final = newroot.final --- if final then --- lastrun = current --- lastfinal = final --- end --- root = newroot --- elseif categories[char] == "mn" then --- -- continue --- else --- return lastrun, lastfinal --- end --- current = getnext(current) --- end --- if lastrun then --- return lastrun, lastfinal --- end --- end - local function hit(root,head) local current = getnext(head) local lastrun = false @@ -759,9 +744,7 @@ end local tree, attr, proc function splitters.handler(head) -- todo: also first_glyph test - head = tonut(head) local current = head - local done = false while current do if getid(current) == glyph_code then local a = getattr(current,a_scriptsplitting) @@ -792,7 +775,6 @@ function splitters.handler(head) -- todo: also first_glyph test end end head, current = proc(handler,head,current,last,1) - done = true else if trace_splitdetail then -- could be punctuation @@ -803,7 +785,6 @@ function splitters.handler(head) -- todo: also first_glyph test end end head, current = proc(handler,head,current,last,2) - done = true end end end @@ -813,7 +794,7 @@ function splitters.handler(head) -- todo: also first_glyph test end current = getnext(current) end - return tonode(head), done + return head end local function marker(head,current,font,color) -- could become: nodes.tracers.marker @@ -907,15 +888,13 @@ setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end) -- playing nice function autofontfeature.handler(head) - for n in traverse_char(tonut(head)) do + for n, char, font in nextchar, head do -- if getattr(n,a_scriptinjection) then -- -- already tagged by script feature, maybe some day adapt -- else - local char = getchar(n) local script = otfscripts[char] if script then local dynamic = getattr(n,0) or 0 - local font = getfont(n) if dynamic > 0 then local slot = cache_yes[font] local attr = slot[script] @@ -980,3 +959,73 @@ implement { name = "resetscript", actions = scripts.reset } + +-- some common helpers + + +do + + local parameters = fonts.hashes.parameters + + local space, stretch, shrink, lastfont + + local inter_character_space_factor = 1 + local inter_character_stretch_factor = 1 + local inter_character_shrink_factor = 1 + + local function space_glue(current) + local data = numbertodataset[getattr(current,a_scriptinjection)] + if data then + inter_character_space_factor = data.inter_character_space_factor or 1 + inter_character_stretch_factor = data.inter_character_stretch_factor or 1 + inter_character_shrink_factor = data.inter_character_shrink_factor or 1 + end + local font = getfont(current) + if lastfont ~= font then + local pf = parameters[font] + space = pf.space + stretch = pf.space_stretch + shrink = pf.space_shrink + lastfont = font + end + return new_glue( + inter_character_space_factor * space, + inter_character_stretch_factor * stretch, + inter_character_shrink_factor * shrink + ) + end + + scripts.inserters = { + + space_before = function(head,current) + return insert_node_before(head,current,space_glue(current)) + end, + space_after = function(head,current) + return insert_node_after(head,current,space_glue(current)) + end, + + zerowidthspace_before = function(head,current) + return insert_node_before(head,current,new_glue(0)) + end, + zerowidthspace_after = function(head,current) + return insert_node_after(head,current,new_glue(0)) + end, + + nobreakspace_before = function(head,current) + local g = space_glue(current) + local p = new_penalty(10000) + head, current = insert_node_before(head,current,p) + return insert_node_before(head,current,g) + end, + nobreakspace_after = function(head,current) + local g = space_glue(current) + local p = new_penalty(10000) + head, current = insert_node_after(head,current,g) + return insert_node_after(head,current,p) + end, + + } + +end + +-- end of helpers diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv index 8f28f505d14..f2d1da62741 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-ini.mkiv @@ -17,10 +17,11 @@ \registerctxluafile{scrp-cjk}{} \registerctxluafile{scrp-eth}{} \registerctxluafile{scrp-tha}{} +\registerctxluafile{scrp-tib}{} -\definesystemattribute[scriptinjection][public] -\definesystemattribute[scriptsplitting][public] -\definesystemattribute[scriptstatus] [public] +\definesystemattribute[scriptinjection][public,pickup] +\definesystemattribute[scriptsplitting][public,pickup] +\definesystemattribute[scriptstatus] [public,pickup] %D Since scripts need specific \LUA\ code we use hard coded attribute %D values, but we might have more tricks at some time, so we use a @@ -43,10 +44,23 @@ \unexpanded\def\scripts_basics_set {\clf_setscript{\currentscript}{\scriptparameter\c!method}{\scriptparameter\c!preset}} -\unexpanded\def\setscript[#1]% +% \unexpanded\def\setscript[#1]% +% {\edef\currentscript{#1}% +% \scripts_basics_set} + +\unexpanded\def\setglobalscript[#1]% + {\edef\currentscript{#1}% + \scripts_basics_set + \pickupscriptinjectionattribute + \pickupscriptsplittingattribute + \pickupscriptstatusattribute} + +\unexpanded\def\setlocalscript[#1]% {\edef\currentscript{#1}% \scripts_basics_set} +\let\setscript\setlocalscript + \unexpanded\def\resetscript {\clf_resetscript} @@ -73,6 +87,7 @@ \definescript [nihongo] [\c!method=nihongo] \definescript [ethiopic] [\c!method=ethiopic] \definescript [thai] [\c!method=thai] +\definescript [tibetan] [\c!method=tibetan] \definescript [latin] [\c!method=] % resets the attribute (also currentscript) diff --git a/Master/texmf-dist/tex/context/base/mkiv/scrp-tib.lua b/Master/texmf-dist/tex/context/base/mkiv/scrp-tib.lua new file mode 100644 index 00000000000..b67f6964800 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/scrp-tib.lua @@ -0,0 +1,81 @@ +if not modules then modules = { } end modules ['scrp-tib'] = { + version = 1.001, + comment = "companion to scrp-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getattr = nuts.getattr +local ischar = nuts.ischar + +local a_scriptstatus = attributes.private('scriptstatus') + +local numbertocategory = scripts.numbertocategory +local inserters = scripts.inserters + +local injectors = { + breaking_tsheg = inserters.space_after, +} + +-- more efficient is to check directly +-- +-- local b_tsheg = 0x0F0B -- breaking +-- local n_tsheg = 0x0F0C -- nonbreaking +-- +-- if char == b_tsheg then +-- head, current = insert_space_after(head,current) +-- end +-- +-- but this is more general + +local function process(head,first,last) + if first ~= last then + local current = first + while current do + local char, id = ischar(current) + if char then + local scriptstatus = getattr(current,a_scriptstatus) + if scriptstatus and scriptstatus > 0 then + local category = numbertocategory[scriptstatus] + if category then + local injector = injectors[category] + if injector then + head, current = injector(head,current) + end + end + end + end + if current == last then + break + else + current = getnext(current) + end + end + end +end + +scripts.installmethod { + name = "tibetan", + injector = process, + datasets = { + default = { + inter_character_space_factor = 1, + inter_character_stretch_factor = 1, + inter_character_shrink_factor = 1, + }, + half = { + inter_character_space_factor = 0.5, + inter_character_stretch_factor = 0.5, + inter_character_shrink_factor = 0.5, + }, + quarter = { + inter_character_space_factor = 0.25, + inter_character_stretch_factor = 0.25, + inter_character_shrink_factor = 0.25, + }, + }, +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua index f90b70be5c9..0916337b197 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/sort-ini.lua @@ -401,8 +401,10 @@ local function basic(a,b) -- trace ea and eb -- hashed (shared) entries return 0 end - local ea, eb = a.split, b.split - local na, nb = #ea, #eb + local ea = a.split + local eb = b.split + local na = #ea + local nb = #eb if na == 0 and nb == 0 then -- simple variant (single word) local result = 0 @@ -414,7 +416,8 @@ local function basic(a,b) -- trace ea and eb end end if result == 0 then - local la, lb = #ea.uc, #eb.uc + local la = #ea.uc + local lb = #eb.uc if la > lb then return 1 elseif lb > la then @@ -429,7 +432,8 @@ local function basic(a,b) -- trace ea and eb -- complex variant, used in register (multiple words) local result = 0 for i=1,nb < na and nb or na do - local eai, ebi = ea[i], eb[i] + local eai = ea[i] + local ebi = eb[i] for j=1,#sequence do local m = sequence[j] result = basicsort(eai[m],ebi[m]) @@ -438,7 +442,8 @@ local function basic(a,b) -- trace ea and eb end end if result == 0 then - local la, lb = #eai.uc, #ebi.uc + local la = #eai.uc + local lb = #ebi.uc if la > lb then return 1 elseif lb > la then @@ -586,8 +591,18 @@ function splitters.utf(str,checked) -- we could append m and u but this is clean -- end -- end end - local m_case, z_case, p_case, m_mapping, z_mapping, p_mapping, char, byte, n = { }, { }, { }, { }, { }, { }, { }, { }, 0 - local nm, nz, np = 0, 0, 0 + local m_case = { } + local z_case = { } + local p_case = { } + local m_mapping = { } + local z_mapping = { } + local p_mapping = { } + local char = { } + local byte = { } + local n = 0 + local nm = 0 + local nz = 0 + local np = 0 for sc in utfcharacters(str) do local b = utfbyte(sc) if b >= digitsoffset then diff --git a/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua b/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua index 1aa173d1b20..b277989664b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/sort-lan.lua @@ -71,16 +71,22 @@ definitions['fr'] = { parent = 'default' } -- DIN 5007-1 -definitions['DIN 5007-1'] = { parent = 'default' } +definitions['DIN 5007-1'] = { + parent = 'default', + replacements = { + { "ß", "ss" }, + }, +} -- DIN 5007-2 definitions['DIN 5007-2'] = { parent = 'default', replacements = { - { "ä", 'ae' }, { "Ä", 'Ae' }, - { "ö", 'oe' }, { "Ö", 'Oe' }, - { "ü", 'ue' }, { "Ü", 'Ue' }, + { "ä", "ae" }, { "Ä", "Ae" }, + { "ö", "oe" }, { "Ö", "Oe" }, + { "ü", "ue" }, { "Ü", "Ue" }, + { "ß", "ss" }, }, } @@ -88,7 +94,9 @@ definitions['DIN 5007-2'] = { definitions['Duden'] = { parent = 'default', - replacements = { { "ß", 's' } }, + replacements = { + { "ß", "s" }, + }, } -- definitions['de'] = { parent = 'default' } -- new german @@ -126,7 +134,7 @@ definitions['de-AT'] = { }, } --- finish (by Wolfgang Schuster) +-- finnish (by Wolfgang Schuster) definitions['fi'] = { entries = { @@ -897,22 +905,24 @@ definitions["hu"] = { }, } ---- Estonian +-- Estonian definitions["et"] = { - entries = { -- w x y are used for foreign words only - ["a"] = "a", ["b"] = "b", ["d"] = "d", ["e"] = "e", ["f"] = "f", - ["g"] = "g", ["h"] = "h", ["i"] = "i", ["j"] = "j", ["k"] = "k", - ["l"] = "l", ["m"] = "m", ["n"] = "n", ["o"] = "o", ["p"] = "p", - ["r"] = "r", ["s"] = "s", ["š"] = "š", ["z"] = "z", ["ž"] = "ž", - ["t"] = "t", ["u"] = "u", ["v"] = "v", ["w"] = "v", ["õ"] = "õ", - ["ä"] = "ä", ["ö"] = "ö", ["ü"] = "ü", ["x"] = "x", ["y"] = "y", + entries = { -- f š z ž are used in estonian words of foreign origin, c č q w x y are used for foreign words only + ["a"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č", ["d"] = "d", + ["e"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h", ["i"] = "i", + ["j"] = "j", ["k"] = "k", ["l"] = "l", ["m"] = "m", ["n"] = "n", + ["o"] = "o", ["p"] = "p", ["q"] = "q", ["r"] = "r", ["s"] = "s", + ["š"] = "š", ["z"] = "z", ["ž"] = "ž", ["t"] = "t", ["u"] = "u", + ["v"] = "v", ["w"] = "w", ["õ"] = "õ", ["ä"] = "ä", ["ö"] = "ö", + ["ü"] = "ü", ["x"] = "x", ["y"] = "y", }, orders = { - "a", "b", "d", "e", "f", "g", "h", "i", "j", "k", - "l", "m", "n", "o", "p", "r", "s", "š", "z", "ž", - "t", "u", "v", "w", "õ", "ä", "ö", "ü", "x", "y", - } + "a", "b", "c", "č", "d", "e", "f", "g", "h", "i", + "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", + "š", "z", "ž", "t", "u", "v", "w", "õ", "ä", "ö", + "ü", "x", "y", + }, } --- Korean diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua deleted file mode 100644 index 3db59881b20..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.lua +++ /dev/null @@ -1,67 +0,0 @@ -if not modules then modules = { } end modules ['spac-adj'] = { - version = 1.001, - comment = "companion to spac-adj.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- sort of obsolete code - -local a_vadjust = attributes.private('graphicvadjust') - -local nodecodes = nodes.nodecodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist - -local remove_node = nodes.remove -local hpack_node = node.hpack - -local enableaction = nodes.tasks.enableaction - -function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionchain for mvl only - if groupcode == "" then -- mvl only - local h, p, done = head, nil, false - while h do - local id = h.id - if id == hlist_code or id == vlist_code then - local a = h[a_vadjust] - if a then - if p then - local n - head, h, n = remove_node(head,h) - local pl = p.list - if n.width ~= 0 then - n = hpack_node(n,0,'exactly') -- todo: dir - end - if pl then - pl.prev = n - n.next = pl - end - p.list = n - done = true - else - -- can't happen - end - else - p = h - h = h.next - end - else - h = h.next - end - end - return head, done - else - return head, false - end -end - -interfaces.implement { - name = "enablegraphicvadjust", - onlyonce = true, - actions = function() - enableaction("finalizers","nodes.handlers.graphicvadjust") - end -} diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv deleted file mode 100644 index d29d15c17cb..00000000000 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-adj.mkiv +++ /dev/null @@ -1,51 +0,0 @@ -%D \module -%D [ file=spac-adj, % moved from spac-par.mkiv -%D version=2009.10.16, % 1997.03.31, was core-spa.tex -%D title=\CONTEXT\ Spacing Macros, -%D subtitle=Paragraphs, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Spacing Macros / Adjustments} - -\unprotect - -% Very nasty but needed for margin stuff inside colored -% paragraphs. Obsolete for while . - -\registerctxluafile{spac-adj}{} - -\definesystemattribute [graphicvadjust] [public] - -\unexpanded\def\enablegraphicvadjust - {\writestatus\m!system{graphicvadjusting is no longer needed!} - \clf_enablegraphicvadjust %once anyway - \glet\enablegraphicvadjust\relax} - -\unexpanded\def\graphicvadjust % currently not enabled ... nasty bidi handling - {\clf_enablegraphicvadjust % and probably no longer needed anyway - \dowithnextboxcontentcs\forgetall\spac_vadjust_graphic_finish\vbox} - -\def\spac_vadjust_graphic_finish - {\vadjust - {\vbox attr \graphicvadjustattribute \plusone - {\unvbox\nextbox - % corrects for one line paragraphs - \nointerlineskip - \kern-\struttotal - \nointerlineskip - \verticalstrut}}} - -\unexpanded\def\fakedvadjust - {\dowithnextboxcs\spac_vadjust_faked_finish\vtop} - -\def\spac_vadjust_faked_finish - {\setbox\nextbox\hpack{\llap{\lower\strutdepth\box\nextbox}}% - \smashedbox\nextbox} - -\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua index 640478d3499..b58040ac72a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.lua @@ -38,7 +38,8 @@ local listcodes = nodes.listcodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local line_code = listcodes.line + +local linelist_code = listcodes.line local new_stretch = nodepool.stretch @@ -63,13 +64,12 @@ local nofrealigned = 0 -- raggedright 0 0 fil -- raggedcenter 0 + 0 + - -local function handler(head,leftpage,realpageno) +local function handler(head,leftpage,realpageno) -- traverse_list local current = head - local done = false while current do local id = getid(current) if id == hlist_code then - if getsubtype(current) == line_code then + if getsubtype(current) == linelist_code then local a = takeattr(current,a_realign) if not a or a == 0 then -- skip @@ -102,7 +102,6 @@ local function handler(head,leftpage,realpageno) elseif trace_realign then report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno) end - done = true nofrealigned = nofrealigned + 1 end end @@ -113,14 +112,11 @@ local function handler(head,leftpage,realpageno) end current = getnext(current) end - return head, done + return head end function alignments.handler(head) - local leftpage = isleftpage() - local realpageno = texgetcount("realpageno") - local head, done = handler(tonut(head),leftpage,realpageno) - return tonode(head), done + return handler(head,isleftpage(),texgetcount("realpageno")) end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv index fbcf45caa2e..4362ff25002 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ali.mkiv @@ -27,7 +27,7 @@ % % but that also means myoption gets frozen due to caching. -\registerctxluafile{spac-ali}{} +\registerctxluafile{spac-ali}{optimize} \definesystemattribute[realign] [public] % might be combined with the next one \definesystemattribute[alignstate][public] % will make a single attributes for several states @@ -61,16 +61,6 @@ \newtoks\everyresetalign % todo -%D We will not use bodydir and pagedir so we disable them. That way we get -%D normal hyperlink support. We back on it (too hard to fake \type {\the}). - -\unexpanded\def\syst_fatal_dir_error#1% - {\writestatus{fatal error}{\string#1\space is forbidden}% - \wait} - -\def\pagedir {\syst_fatal_dir_error\pagedir} \let\normalpagedir\pagedir -\def\bodydir {\syst_fatal_dir_error\bodydir} \let\normalbodydir\bodydir - % This will become a more advanced layout controller soon: \newconditional\layoutlefttoright \settrue\layoutlefttoright @@ -94,63 +84,23 @@ \unexpanded\def\spac_directions_lefttoright_vmode {\settrue\displaylefttoright \settrue\inlinelefttoright - \textdir TLT\relax - \pardir TLT\relax} + \textdirection\directionlefttoright + \pardirection \directionlefttoright} \unexpanded\def\spac_directions_righttoleft_vmode {\setfalse\displaylefttoright \setfalse\inlinelefttoright - \textdir TRT\relax - \pardir TRT\relax} - -% % keep this as reference -% -% \unexpanded\def\spac_directions_lefttoright_hmode -% {\textdir TLT\relax -% \settrue\inlinelefttoright} -% -% \unexpanded\def\spac_directions_righttoleft_hmode -% {\textdir TRT\relax -% \setfalse\inlinelefttoright} -% -% \unexpanded\def\spac_directions_lefttoright_hmode -% {\ifzeropt\lastskip -% \textdir TLT\relax -% \else -% \scratchskip\lastskip -% \unskip -% \textdir TLT\relax -% \hskip\scratchskip -% \fi -% \settrue\inlinelefttoright} -% -% \unexpanded\def\spac_directions_righttoleft_hmode -% {\ifzeropt\lastskip -% \textdir TRT\relax -% \else -% \scratchskip\lastskip -% \unskip -% \textdir TRT\relax -% \hskip\scratchskip -% \fi -% \setfalse\inlinelefttoright} + \textdirection\directionrighttoleft + \pardirection \directionrighttoleft} \unexpanded\def\spac_directions_lefttoright_hmode - {\linedir TLT\relax % linedir keeps subtype of skip + {\linedirection\directionlefttoright % linedir keeps subtype of skip \settrue\inlinelefttoright} \unexpanded\def\spac_directions_righttoleft_hmode - {\linedir TRT\relax % linedir keeps subtype of skip + {\linedirection\directionrighttoleft % linedir keeps subtype of skip \setfalse\inlinelefttoright} -% \def\currentdirectionparameters -% {\ifconditional\inlinelefttoright \else -% idir {r2l}% -% \fi -% \ifconditional\displaylefttoright \else -% ddir {r2l}% -% \fi} - \unexpanded\def\synchronizelayoutdirection {\ifconditional\layoutlefttoright \spac_directions_synchronize_lr @@ -167,16 +117,17 @@ \def\spac_directions_synchronize_lr {\settrue\inlinelefttoright - \textdir TLT\relax - \pardir TLT\relax} + \textdirection\directionlefttoright + \pardirection \directionlefttoright} \def\spac_directions_synchronize_rl {\setfalse\inlinelefttoright - \textdir TRT\relax - \pardir TRT\relax} + \textdirection\directionrighttoleft + \pardirection \directionrighttoleft} \unexpanded\def\synchronizeinlinedirection - {\textdir T\ifconditional\inlinelefttoright L\else R\fi T\relax} + {% why not \linedirection here + \textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi} \unexpanded\def\checkedlefttoright {\ifvmode @@ -210,49 +161,20 @@ \unexpanded\def\usebidiparameter#1% {\begincsname\??bidi#1\c!bidi\endcsname} -% maybe some day: -% -% \newcount\postdirpenalty % \zerocount -% \newcount\predirpenalty % \zerocount -% -% \def\spac_directions_post_break -% {\ifhmode -% \removeunwantedspaces -% \penalty\postdirpenalty -% \fi} -% -% \def\spac_directions_pre_break -% {\ifhmode -% \penalty\predirpenalty -% \ignorespaces -% \fi} -% -% \unexpanded\def\spac_directions_lefttoright_hmode -% {\settrue\inlinelefttoright -% \textdir TLT\relax -% \aftergroup\spac_directions_post_break -% \spac_directions_pre_break} -% -% \unexpanded\def\spac_directions_righttoleft_hmode -% {\textdir TRT\relax -% \setfalse\inlinelefttoright -% \aftergroup\spac_directions_post_break -% \spac_directions_pre_break} - \unexpanded\def\showdirections {\dontleavehmode - \begingroup\infofont\textdir TLT[\space - layout:\ifconditional \layoutlefttoright l2r\else r2l\fi\space - display:\ifconditional\displaylefttoright l2r\else r2l\fi\space - inline:\ifconditional \inlinelefttoright l2r\else r2l\fi\space + \begingroup\infofont\textdirection\directionlefttoright[\space + layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space + display: \ifconditional\displaylefttoright l2r\else r2l\fi\space + inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space ]\endgroup} -\unexpanded\def\righttolefthbox#1#{\normalhbox dir TRT #1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox -\unexpanded\def\lefttorighthbox#1#{\normalhbox dir TLT #1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox -\unexpanded\def\righttoleftvbox#1#{\normalvbox dir TRT #1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox -\unexpanded\def\lefttorightvbox#1#{\normalvbox dir TLT #1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox -\unexpanded\def\righttoleftvtop#1#{\normalvtop dir TRT #1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop -\unexpanded\def\lefttorightvtop#1#{\normalvtop dir TLT #1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop +\unexpanded\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox +\unexpanded\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox +\unexpanded\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox +\unexpanded\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox +\unexpanded\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop +\unexpanded\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop \unexpanded\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next} \unexpanded\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox @@ -355,7 +277,8 @@ \newconstant\c_spac_align_state_par_fill \def\v_spac_align_fill_amount {\plusone fil} -\def\v_spac_align_fill_amount_hard {\plusone fill} +\def\v_spac_align_fill_amount_hard {\plusone fill} +\def\v_spac_align_fill_amount_extreme {\plustenthousand filll} \def\v_spac_align_fill_amount_negative {\minusone fil} \def\v_spac_align_fill_amount_double {\plustwo fil} \def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key @@ -479,7 +402,8 @@ \spaceskip \zeropoint\relax \xspaceskip \zeropoint\relax \parfillskip \zeropoint - \parfillleftskip\zeropoint\s!plus\v_spac_align_fill_amount_hard\relax + \parfillleftskip\zeropoint\s!plus\v_spac_align_fill_amount_extreme\relax + \parfillleftmode\plustwo % \plusone checks for multiple lines \parindent \zeropoint \relax} @@ -643,8 +567,8 @@ }}% kept, nice for tracing \edef\raggedcommand {\the\t_spac_align_collected }% \edef\updateraggedskips{\spac_align_flush_horizontal}% - \global\expandafter\let\csname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand - \global\expandafter\let\csname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips} + \expandafter\glet\csname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand + \expandafter\glet\csname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips} \def\spac_align_collect#1% {\csname\??aligncommand#1\endcsname} diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua index 0fa639f9295..23cf9741b14 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.lua @@ -27,9 +27,6 @@ local nodes, node = nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - local getnext = nuts.getnext local getprev = nuts.getprev local getattr = nuts.getattr @@ -38,7 +35,6 @@ local getlang = nuts.getlang local setchar = nuts.setchar local setattrlist = nuts.setattrlist local getfont = nuts.getfont -local getchar = nuts.getchar local setsubtype = nuts.setsubtype local setdisc = nuts.setdisc local isglyph = nuts.isglyph @@ -48,13 +44,13 @@ local setcolor = nodes.tracers.colors.set local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglyph = nuts.traversers.glyph local copy_node = nuts.copy -local tasks = nodes.tasks - local nodepool = nuts.pool local new_penalty = nodepool.penalty local new_glue = nodepool.glue @@ -63,12 +59,10 @@ local new_rule = nodepool.rule local new_disc = nodepool.disc local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes -local disccodes = nodes.disccodes +local gluecodes = nodes.gluecodes local glyph_code = nodecodes.glyph -local space_skip_code = skipcodes.spaceskip -local explicit_code = disccodes.explicit +local spaceskip_code = gluecodes.spaceskip local chardata = characters.data local is_punctuation = characters.is_punctuation @@ -101,8 +95,7 @@ local function inject_quad_space(unicode,head,current,fraction) setattrlist(glue,current) setattrlist(current) -- why reset all setattr(glue,a_character,unicode) - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function inject_char_space(unicode,head,current,parent) @@ -112,8 +105,7 @@ local function inject_char_space(unicode,head,current,parent) setattrlist(glue,current) setattrlist(current) -- why reset all setattr(glue,a_character,unicode) - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink) @@ -132,18 +124,17 @@ local function inject_nobreak_space(unicode,head,current,space,spacestretch,spac head, current = insert_node_after(head,current,kern) head, current = insert_node_after(head,current,penalty) end - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function nbsp(head,current) local para = fontparameters[getfont(current)] if getattr(current,a_alignstate) == 1 then -- flushright head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0) - setsubtype(current,space_skip_code) + setsubtype(current,spaceskip_code) else head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink) - setsubtype(current,space_skip_code) + setsubtype(current,spaceskip_code) end return head, current end @@ -152,27 +143,13 @@ end function characters.replacenbsp(head,original) local head, current = nbsp(head,original) - head = remove_node(head,original,true) - return head, current + return remove_node(head,original,true) end --- function characters.replacenbspaces(head) --- for current in traverse_id(glyph_code,head) do --- if getchar(current) == 0x00A0 then --- local h = nbsp(head,current) --- if h then --- head = remove_node(h,current,true) --- end --- end --- end --- return head --- end - function characters.replacenbspaces(head) - local head = tonut(head) local wipe = false - for current in traverse_id(glyph_code,head) do -- can be anytiem so no traverse_char - if getchar(current) == 0x00A0 then + for current, char, font in nextglyph, head do -- can be anytime so no traverse_char + if char == 0x00A0 then if wipe then head = remove_node(h,current,true) wipe = false @@ -184,15 +161,16 @@ function characters.replacenbspaces(head) end end if wipe then - head = remove_node(h,current,true) + head = remove_node(head,current,true) end - return tonode(head) + return head end -- This initialization might move someplace else if we need more of it. The problem is that -- this module depends on fonts so we have an order problem. local nbsphash = { } setmetatableindex(nbsphash,function(t,k) + -- this needs checking ! for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end setmetatableindex(nbsphash,nil) @@ -209,11 +187,11 @@ local methods = { [0x001F] = function(head,current) -- kind of special local next = getnext(current) if next then - local char = isglyph(next) + local char, font = isglyph(next) if char then head, current = remove_node(head,current,true) if not is_punctuation[char] then - local p = fontparameters[getfont(next)] + local p = fontparameters[font] head, current = insert_node_before(head,current,new_glue(p.space,p.space_stretch,p.space_shrink)) end end @@ -319,9 +297,7 @@ local methods = { characters.methods = methods -- function characters.handler(head) -- todo: use traverse_id --- head = tonut(head) -- local current = head --- local done = false -- while current do -- local char, id = isglyph(current) -- if char then @@ -335,47 +311,39 @@ characters.methods = methods -- if h then -- head = remove_node(h,current,true) -- end --- done = true -- end -- current = next -- else -- current = getnext(current) -- end -- end --- return tonode(head), done +-- return head -- end --- for current, char, font in traverse_char_data(head) will save 0.015 on a 300 page doc - -- this also works ok in math as we run over glyphs and these stay glyphs ... not sure -- about scripts and such but that is not important anyway ... some day we can consider -- special definitions in math function characters.handler(head) - local head = tonut(head) local wipe = false - for current in traverse_char(head) do - local char = getchar(current) - if char then - local method = methods[char] - if method then - if wipe then - head = remove_node(head,wipe,true) - wipe = false - end - if trace_characters then - report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) - end - local h = method(head,current) - if h then - wipe = current - end - done = true + for current, char in nextchar, head do + local method = methods[char] + if method then + if wipe then + head = remove_node(head,wipe,true) + wipe = false + end + if trace_characters then + report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) + end + local h = method(head,current) + if h then + wipe = current end end end if wipe then head = remove_node(head,wipe,true) end - return tonode(head), done + return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv index ed2cb47f982..23f4ac8dd64 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-chr.mkiv @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{spac-chr}{} +\registerctxluafile{spac-chr}{optimize} \definesystemattribute[characters][public] diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv index 29351a3dd46..bd50bfea68b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-flr.mkiv @@ -60,6 +60,35 @@ \endgroup \ignorespaces} +% \definefiller +% [MyFiller] +% [offset=.25\emwidth, +% rightmargindistance=-\rightskip, +% method=middle] +% +% \startitemize[packed,joinedup][rightmargin=5em] +% \startitem +% \input sapolsky \fillupto[MyFiller]{RS} +% \stopitem +% \stopitemize + +\unexpanded\def\fillupto + {\dosingleempty\spac_fillers_upto} + +\def\spac_fillers_upto[#1]#2% + {\removeunwantedspaces + \begingroup + \edef\currentfiller{#1}% + \scratchdimen\dimexpr\fillerparameter\c!rightmargindistance\relax + \ifdim\scratchdimen=\zeropoint\else + \parfillskip \scratchdimen\s!plus \plusone\s!fil\relax + \fi + \spac_fillers_indeed[#1]% + \doifsomething{#2}{\hbox{#2}}% + \par + \endgroup + \ignorespaces} + \setvalue{\??filleralternative\s!unknown}% {} @@ -87,8 +116,8 @@ \setvalue{\??filleralternative\v!rule}% {\expandnamespaceparameter\??fillerleadermethod\fillerparameter\c!method\v!local \hrule - \!!height\fillerparameter\c!height - \!!depth \fillerparameter\c!depth + \s!height\fillerparameter\c!height + \s!depth \fillerparameter\c!depth \hfill} \letvalue{\??fillerleadermethod\s!local }\normalleaders % overflow ends up inbetween (current box) @@ -106,6 +135,7 @@ \c!depth=\zeropoint, \c!leftmargin=\zeropoint, \c!rightmargin=\zeropoint, + \c!rightmargindistance=\zeropoint, \c!alternative=\v!symbol, \c!method=\s!local] diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv index 73c6e0dd151..72d017836f6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-grd.mkiv @@ -108,8 +108,8 @@ \newbox \b_spac_lines_correction_after \def\spac_lines_initialize_corrections - {\setbox\b_spac_lines_correction_before\hbox{\setstrut\strut}% - \setbox\b_spac_lines_correction_after \hbox{(}% + {\setbox\b_spac_lines_correction_before\hpack{\setstrut\strut}% + \setbox\b_spac_lines_correction_after \hbox {(}% \d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax \d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax \ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv index ce747a2025b..32b7f06fb81 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-hor.mkiv @@ -17,8 +17,9 @@ \registerctxluafile{spac-hor}{} -\let \parfillrightskip \parfillskip -\newskip\parfillleftskip +\let \parfillrightskip \parfillskip +\newskip \parfillleftskip +\newconstant\parfillleftmode \let\v_spac_indentation_current\empty % amount/keyword @@ -205,6 +206,9 @@ \let\checkindentation\relax +\installmacrostack\checkindentation +\installmacrostack\ifindentation + \def\spac_indentation_remove {\ifdim\parindent=\zeropoint \else \begingroup @@ -218,21 +222,21 @@ \def\spac_indentation_do_toggle_indeed {\global\indentationfalse - \global\let\checkindentation\spac_indentation_no_toggle_indeed + \glet\checkindentation\spac_indentation_no_toggle_indeed \spac_indentation_remove} \def\spac_indentation_no_toggle_indeed {\global\indentationtrue - \global\let\checkindentation\spac_indentation_do_toggle_indeed} + \glet\checkindentation\spac_indentation_do_toggle_indeed} \def\spac_indentation_do_indeed {\global\indentationtrue} \def\spac_indentation_do_toggle - {\global\let\checkindentation\spac_indentation_do_toggle_indeed} + {\glet\checkindentation\spac_indentation_do_toggle_indeed} \def\spac_indentation_no_toggle - {\global\let\checkindentation\spac_indentation_no_toggle_indeed} + {\glet\checkindentation\spac_indentation_no_toggle_indeed} \def\spac_indentation_check_toggle {\ifcase\c_spac_indentation_toggle_state @@ -244,22 +248,22 @@ \fi} \def\spac_indentation_variant_yes - {\global\let\checkindentation\spac_indentation_do_indeed} + {\glet\checkindentation\spac_indentation_do_indeed} \def\spac_indentation_no_next_check {\spac_indentation_remove - \global\let\checkindentation\spac_indentation_do_indeed} + \glet\checkindentation\spac_indentation_do_indeed} \def\spac_indentation_variant_no % made global {\ifinpagebody \else \global\indentationfalse - \global\let\checkindentation\spac_indentation_no_next_check + \glet\checkindentation\spac_indentation_no_next_check \fi} \def\nonoindentation % bv bij floats {\ifinpagebody \else \global\indentationtrue - \global\let\checkindentation\spac_indentation_do_indeed + \glet\checkindentation\spac_indentation_do_indeed \fi} \def\spac_indentation_variant_force @@ -271,13 +275,13 @@ \fi \fi} \appendtoks - \pushmacro\checkindentation - \pushmacro\ifindentation + \push_macro_checkindentation + \push_macro_ifindentation \to \everypushsomestate \appendtoks - \popmacro\ifindentation - \popmacro\checkindentation + \pop_macro_ifindentation + \pop_macro_checkindentation \to \everypopsomestate % public: @@ -287,16 +291,16 @@ \let\doindentation\spac_indentation_variant_yes % public \def\dontrechecknextindentation % public (in macros) - {\global\let\dorechecknextindentation\relax} + {\glet\dorechecknextindentation\relax} \let\dorechecknextindentation\relax % public (in macros) \unexpanded\def\spac_indentation_check_next_indentation - {\global\let\dorechecknextindentation\relax + {\glet\dorechecknextindentation\relax \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par \def\spac_indentation_variant_auto - {\global\let\dorechecknextindentation\spac_indentation_check_next_indentation} + {\glet\dorechecknextindentation\spac_indentation_check_next_indentation} %D This one sets up the local indentation behaviour (i.e. either or not %D a next paragraph will be indented). @@ -564,6 +568,13 @@ \fi \fi} +\unexpanded\def\onlynonbreakablespace + {\ifdim\lastskip=\interwordspace + \unskip + \nonbreakablespace + \fi + \ignorespaces} + % \startbuffer % \startlines \tt \fixedspaces % 0~1~~2~~~3~~~~4~~~~~5 @@ -598,12 +609,15 @@ \ifdefined\quad \else - \unexpanded\def\enskip{\hskip.5\emwidth} - \unexpanded\def\quad {\hskip \emwidth} - \unexpanded\def\qquad {\hskip 2\emwidth} + \unexpanded\def\enskip{\hskip.5\emwidth\relax} + \unexpanded\def\quad {\hskip \emwidth\relax} + \unexpanded\def\qquad {\hskip 2\emwidth\relax} \fi +\unexpanded\def\negenspace{\kern-.5\emwidth} +\unexpanded\def\negemspace{\kern- \emwidth} + \let\emspace\quad \unexpanded\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) @@ -1116,6 +1130,8 @@ \unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% \unexpanded\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% +% hm, order matters when we \let in \obeyspaces + \installspacemethod \v!on {\obeyspaces \let\obeyedspace\spac_spaces_checked_control diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv index 6558cb1113f..d862f6d8109 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-lin.mkiv @@ -86,7 +86,7 @@ \let\spac_lines_break\relax \fi \linesparameter\c!before - \pushmacro\checkindentation + \push_macro_checkindentation \whitespace \dostarttaggedchained\t!lines\currentlines\??lines \begingroup @@ -126,7 +126,7 @@ {\dostoptagged \endgroup \dostoptagged - \popmacro\checkindentation + \pop_macro_checkindentation \linesparameter\c!after \egroup} diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv index c7d22f0e0c5..9adc591ed96 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-pag.mkiv @@ -151,6 +151,7 @@ \unexpanded\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs} % use \dontleavehmode if needed \unexpanded\def\doifelserightpage{\doifelserightpagestate\s!paragraph\nofraggedparagraphs} +\unexpanded\def\rightpageorder {\pagestaterealpageorder\s!paragraph\nofraggedparagraphs} \let\doifrightpageelse\doifelserightpage @@ -169,9 +170,9 @@ \fi \ifpagechanged \letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage - \globallet\lastchangedpage\m_spac_pagestates_realpage + \glet\lastchangedpage\m_spac_pagestates_realpage \else - \globallet\lastchangedpage\realfolio + \glet\lastchangedpage\realfolio \fi} \def\changedpagestate#1#2% diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv index 4dd3db24338..0932b735989 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-par.mkiv @@ -79,17 +79,17 @@ \setvalue{\??paragraphintro\v!first}#1% {\global\settrue\c_spac_paragraphs_intro_first - \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}% + \gtoksapp\t_spac_paragraphs_intro_first{#1}% \glet\insertparagraphintro\spac_paragraphs_flush_intro} \setvalue{\??paragraphintro\v!next}#1% {\global\settrue\c_spac_paragraphs_intro_next - \global\t_spac_paragraphs_intro_next\expandafter{\the\t_spac_paragraphs_intro_next#1}% + \gtoksapp\t_spac_paragraphs_intro_next{#1}% \glet\insertparagraphintro\spac_paragraphs_flush_intro} \setvalue{\??paragraphintro\v!each}#1% {\global\settrue\c_spac_paragraphs_intro_each - \global\t_spac_paragraphs_intro_each\expandafter{\the\t_spac_paragraphs_intro_each#1}% + \gtoksapp\t_spac_paragraphs_intro_each{#1}% \glet\insertparagraphintro\spac_paragraphs_flush_intro} %D We can say: @@ -130,7 +130,7 @@ \unexpanded\def\flushatparagraph#1% {\global\c_spac_paragraphs_intro_first\plusone - \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}% + \gtoksapp\t_spac_paragraphs_intro_first{#1}% \glet\insertparagraphintro\spac_paragraphs_flush_intro} %D Here comes the flusher (we misuse the one level expansion of token @@ -221,19 +221,19 @@ \dowithnextboxcs\spac_postponed_data_finish\hbox} \def\spac_postponed_data_finish - {\global\setbox\b_spac_postponed_data\hbox % to\zeropoint + {\global\setbox\b_spac_postponed_data\hpack % to\zeropoint {\box\b_spac_postponed_data\box\nextbox}% \endgroup} \def\spac_postponed_data_flush {%\iftrialtypesetting \else \ifvoid\b_spac_postponed_data\else - \hbox{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data + \hpack{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data \fi \glet\flushpostponednodedata\relax }%\fi} -\unexpanded\def\doflushatpar +\unexpanded\def\doflushatpar % might be renamed {\ifvmode \expandafter\flushatnextpar \else diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua index a28f305932c..32582c56fc5 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-prf.lua @@ -17,6 +17,7 @@ local formatters = string.formatters local nodecodes = nodes.nodecodes local gluecodes = nodes.gluecodes local listcodes = nodes.listcodes +local leadercodes = nodes.leadercodes local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc @@ -30,10 +31,12 @@ local math_code = nodecodes.math local rule_code = nodecodes.rule local marginkern_code = nodecodes.marginkern -local leaders_code = gluecodes.leaders +local leaders_code = leadercodes.leaders + local lineskip_code = gluecodes.lineskip local baselineskip_code = gluecodes.baselineskip -local line_code = listcodes.line + +local linelist_code = listcodes.line local texlists = tex.lists local settexattribute = tex.setattribute @@ -128,6 +131,9 @@ local function getprofile(line,step) local margin = step / 4 local min = 0 local max = ceiling(getwidth(line)/step) + 1 + local wd = 0 + local ht = 0 + local dp = 0 for i=min,max do heights[i] = 0 @@ -136,8 +142,6 @@ local function getprofile(line,step) -- remember p - local wd, ht, dp = 0, 0, 0 - local function progress() position = width width = position + wd @@ -639,7 +643,7 @@ end local function profilelist(line,mvl) - local current = tonut(line) + local current = line local top = nil local bot = nil @@ -668,7 +672,7 @@ local function profilelist(line,mvl) local id = getid(current) if id == hlist_code then local subtype = getsubtype(current) - if subtype == line_code then + if subtype == linelist_code then t_profile = hasprofile(current) if t_profile then top = current @@ -710,7 +714,7 @@ local function profilelist(line,mvl) if id == hlist_code then -- check subtype local subtype = getsubtype(current) - if subtype == line_code then + if subtype == linelist_code then if top == current then -- skip bot = nil -- to be sure @@ -819,7 +823,7 @@ function profiling.profilebox(specification) local id = getid(current) if id == hlist_code then local subtype = getsubtype(current) - if subtype == line_code then + if subtype == linelist_code then if top then bot = current b_profile = setprofile(bot) @@ -899,9 +903,8 @@ end -- -- function profiling.vboxhandler(head,where) -- if head and not ignore[where] then --- local h = tonut(head) --- if getnext(h) then --- profilelist(h) +-- if getnext(head) then +-- profilelist(head) -- end -- end -- return head @@ -911,7 +914,7 @@ function profiling.pagehandler(head) if head then profilelist(head,true) end - return head, true + return head end interfaces.implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua index 969a195e1fe..b55f1ca7cae 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua @@ -116,8 +116,8 @@ local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') local nuts = nodes.nuts -local tonode = nuts.tonode local tonut = nuts.tonut +local tonode = nuts.tonode local getnext = nuts.getnext local setlink = nuts.setlink @@ -147,15 +147,16 @@ local getdepth = nuts.getdepth local find_node_tail = nuts.tail local flush_node = nuts.flush_node -local traverse_nodes = nuts.traverse -local traverse_nodes_id = nuts.traverse_id local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local remove_node = nuts.remove local count_nodes = nuts.countall local hpack_node = nuts.hpack local vpack_node = nuts.vpack ------ writable_spec = nuts.writable_spec + +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist + local nodereference = nuts.reference local theprop = nuts.theprop @@ -170,8 +171,9 @@ local new_kern = nodepool.kern local new_rule = nodepool.rule local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes -local penaltycodes = nodes.penaltycodes +local gluecodes = nodes.gluecodes +----- penaltycodes = nodes.penaltycodes +----- listcodes = nodes.listcodes local penalty_code = nodecodes.penalty local kern_code = nodecodes.kern @@ -179,21 +181,22 @@ local glue_code = nodecodes.glue local insert_code = nodecodes.ins local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local rule_code = nodecodes.rule local localpar_code = nodecodes.localpar -local linebreak_code = penaltycodes.linebreakpenalty +local userskip_code = gluecodes.userskip +local lineskip_code = gluecodes.lineskip +local baselineskip_code = gluecodes.baselineskip +local parskip_code = gluecodes.parskip +local topskip_code = gluecodes.topskip +local splittopskip_code = gluecodes.splittopskip -local userskip_code = skipcodes.userskip -local lineskip_code = skipcodes.lineskip -local baselineskip_code = skipcodes.baselineskip -local parskip_code = skipcodes.parskip -local topskip_code = skipcodes.topskip -local splittopskip_code = skipcodes.splittopskip +local linelist_code = nodes.listcodes.line -local abovedisplayskip_code = skipcodes.abovedisplayskip -local belowdisplayskip_code = skipcodes.belowdisplayskip -local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip -local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip +local abovedisplayskip_code = gluecodes.abovedisplayskip +local belowdisplayskip_code = gluecodes.belowdisplayskip +local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip +local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip local properties = nodes.properties.data @@ -208,90 +211,93 @@ vspacingdata.snapmethods = snapmethods storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") -local default = { - [v_maxheight] = true, - [v_maxdepth] = true, - [v_strut] = true, - [v_hfraction] = 1, - [v_dfraction] = 1, - [v_bfraction] = 0.25, -} +do -local fractions = { - [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, - [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, - [v_box] = v_bfraction, - [v_top] = v_tlines, [v_bottom] = v_blines, -} + local default = { + [v_maxheight] = true, + [v_maxdepth] = true, + [v_strut] = true, + [v_hfraction] = 1, + [v_dfraction] = 1, + [v_bfraction] = 0.25, + } -local values = { - offset = "offset" -} + local fractions = { + [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, + [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, + [v_box] = v_bfraction, + [v_top] = v_tlines, [v_bottom] = v_blines, + } -local colonsplitter = lpeg.splitat(":") + local values = { + offset = "offset" + } -local function listtohash(str) - local t = { } - for s in gmatch(str,"[^, ]+") do - local key, detail = lpegmatch(colonsplitter,s) - local v = variables[key] - if v then - t[v] = true - if detail then - local k = fractions[key] - if k then - detail = tonumber("0" .. detail) - if detail then - t[k] = detail - end - else - k = values[key] + local colonsplitter = lpeg.splitat(":") + + local function listtohash(str) + local t = { } + for s in gmatch(str,"[^, ]+") do + local key, detail = lpegmatch(colonsplitter,s) + local v = variables[key] + if v then + t[v] = true + if detail then + local k = fractions[key] if k then - detail = todimen(detail) + detail = tonumber("0" .. detail) if detail then t[k] = detail end + else + k = values[key] + if k then + detail = todimen(detail) + if detail then + t[k] = detail + end + end end end + else + detail = tonumber("0" .. key) + if detail then + t[v_hfraction] = detail + t[v_dfraction] = detail + end end + end + if next(t) then + t[v_hfraction] = t[v_hfraction] or 1 + t[v_dfraction] = t[v_dfraction] or 1 + return t else - detail = tonumber("0" .. key) - if detail then - t[v_hfraction] = detail - t[v_dfraction] = detail - end + return default end end - if next(t) then - t[v_hfraction] = t[v_hfraction] or 1 - t[v_dfraction] = t[v_dfraction] or 1 - return t - else - return default + + function vspacing.definesnapmethod(name,method) + local n = #snapmethods + 1 + local t = listtohash(method) + snapmethods[n] = t + t.name = name -- not interfaced + t.specification = method -- not interfaced + context(n) end -end -function vspacing.definesnapmethod(name,method) - local n = #snapmethods + 1 - local t = listtohash(method) - snapmethods[n] = t - t.name = name -- not interfaced - t.specification = method -- not interfaced - context(n) end local function validvbox(parentid,list) if parentid == hlist_code then local id = getid(list) - if id == localpar_code then -- check for initial par subtype + if id == localpar_code and getsubtype(list) == 0 then list = getnext(list) if not next then return nil end end local done = nil - for n in traverse_nodes(list) do - local id = getid(n) + for n, id in nextnode, list do if id == vlist_code or id == hlist_code then if done then return nil @@ -320,14 +326,13 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only -- problem: any snapped vbox ends up in a line if list and parentid == hlist_code then local id = getid(list) - if id == localpar_code then -- check for initial par subtype + if id == localpar_code and getsubtype(list) == 0 then list = getnext(list) if not list then return false end end - for n in traverse_nodes(list) do - local id = getid(n) + for n, id in nextnode, list do if id == hlist_code or id == vlist_code then -- local a = getattr(n,a_snapmethod) -- if not a then @@ -536,7 +541,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut] if thebox and id == vlist_code then local list = getlist(thebox) local lw, lh, ld - for n in traverse_nodes_id(hlist_code,list) do + for n in nexthlist, list do lw, lh, ld = getwhd(n) break end @@ -572,7 +577,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut] if thebox and id == vlist_code then local list = getlist(thebox) local lw, lh, ld - for n in traverse_nodes_id(hlist_code,list) do + for n in nexthlist, list do lw, lh, ld = getwhd(n) end if lh then @@ -872,14 +877,15 @@ end local trace_list, tracing_info, before, after = { }, false, "", "" local function nodes_to_string(head) - local current, t = head, { } + local current = head + local t = { } while current do local id = getid(current) local ty = nodecodes[id] if id == penalty_code then t[#t+1] = formatters["%s:%s"](ty,getpenalty(current)) elseif id == glue_code then - t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getwidth(current)) + t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current)) elseif id == kern_code then t[#t+1] = formatters["%s:%p"](ty,getkern(current)) else @@ -1261,17 +1267,26 @@ do if trace then reset_tracing(head) end - local current, oldhead = head, head - local glue_order, glue_data, force_glue = 0, nil, false - local penalty_order, penalty_data, natural_penalty, special_penalty = 0, nil, nil, nil - local parskip, ignore_parskip, ignore_following, ignore_whitespace, keep_together = nil, false, false, false, false - local lastsnap = nil + local current = head + local oldhead = head + local glue_order = 0 + local glue_data + local force_glue = false + local penalty_order = 0 + local penalty_data + local natural_penalty + local special_penalty + local parskip + local ignore_parskip = false + local ignore_following = false + local ignore_whitespace = false + local keep_together = false + local lastsnap + local pagehead + local pagetail -- -- todo: keep_together: between headers -- - local pagehead = nil - local pagetail = nil - local function getpagelist() if not pagehead then pagehead = texlists.page_head @@ -1396,7 +1411,7 @@ do end head = insert_node_before(head,current,glue_data) else - -- report_vspacing("needs checking (%s): %p",skipcodes[getsubtype(glue_data)],w) + -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w) flush_node(glue_data) end end @@ -1814,7 +1829,7 @@ do if snap and trace_vsnapping then local w = getwidth(current) if w ~= 0 then - report_snapper("glue %p of type %a kept",w,skipcodes[subtype]) + report_snapper("glue %p of type %a kept",w,gluecodes[subtype]) end end if trace then @@ -1881,7 +1896,7 @@ do trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) end end - return head, true + return head end -- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display @@ -1909,43 +1924,47 @@ do -- ugly code: we get partial lists (check if this stack is still okay) ... and we run -- into temp nodes (sigh) + local forceflush = false + function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then - newhead = tonut(newhead) local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false stackhack = true -- todo: only when grid snapping once enabled -- todo: fast check if head = tail - for n in traverse_nodes(newhead) do -- we could just look for glue nodes - local id = getid(n) + for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes if id ~= glue_code then flush = true - else - local subtype = getsubtype(n) - if subtype == userskip_code then - if getattr(n,a_skipcategory) then - stackhack = true - else - flush = true - end - elseif subtype == parskip_code then - -- if where == new_graf then ... end - if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then --- texsetcount("c_spac_vspacing_ignore_parskip",0) - setglue(n) - -- maybe removenode - end + elseif subtype == userskip_code then + if getattr(n,a_skipcategory) then + stackhack = true + else + flush = true + end + elseif subtype == parskip_code then + -- if where == new_graf then ... end + if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then + -- texsetcount("c_spac_vspacing_ignore_parskip",0) + setglue(n) + -- maybe removenode end end end texsetcount("c_spac_vspacing_ignore_parskip",0) + + if forceflush then + forceflush = false + flush = true + end + if flush then if stackhead then if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end setlink(stacktail,newhead) - newhead = stackhead - stackhead, stacktail = nil, nil + newhead = stackhead + stackhead = nil + stacktail = nil end if stackhack then stackhack = false @@ -1956,7 +1975,7 @@ do if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end -- texlists.contrib_head = newhead end - return tonode(newhead) + return newhead else if stackhead then if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end @@ -1966,13 +1985,43 @@ do stackhead = newhead end stacktail = newtail - -- texlists.contrib_head = nil - -- newhead = nil end end return nil end + -- function vspacing.flushpagestack() + -- if stackhead then + -- local head = texlists.contrib_head + -- if head then + -- local tail = find_node_tail(head) + -- setlink(tail,stackhead) + -- else + -- texlists.contrib_head = tonode(stackhead) + -- end + -- stackhead, stacktail = nil, nil + -- end + -- + -- end + + function vspacing.pageoverflow() + local h = 0 + if stackhead then + for n, id in nextnode, stackhead do + if id == glue_code then + h = h + getwidth(n) + elseif id == kern_code then + h = h + getkern(n) + end + end + end + return h + end + + function vspacing.forcepageflush() + forceflush = true + end + local ignore = table.tohash { "split_keep", "split_off", @@ -1980,11 +2029,10 @@ do } function vspacing.vboxhandler(head,where) - if head and not ignore[where] then - local h = tonut(head) - if getnext(h) then -- what if a one liner and snapping? - h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return tonode(h) + if head and not ignore[where] and getnext(head) then + if getnext(head) then -- what if a one liner and snapping? + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + return head end end return head @@ -2015,7 +2063,6 @@ do local outer = texnest[0] local enabled = true - local count = true local trace = false local report = logs.reporter("vspacing") @@ -2024,96 +2071,84 @@ do end) directives.register("vspacing.synchronizepage",function(v) - if v == true or v == "count" then - enabled = true - count = true - elseif v == "first" then - enabled = true - count = false - else - enabled = false - count = false - end + enabled = v end) - -- hm, check the old one + local ignoredepth = -65536000 - -- function vspacing.synchronizepage() - -- if enabled then - -- local head = texlists.hold_head - -- local skip = 0 - -- while head and head.id == insert_code do - -- head = head.next - -- skip = skip + 1 - -- end - -- if head then - -- outer.prevdepth = 0 - -- end - -- if trace then - -- report("prevdepth %s at page %i, skipped %i, value %p", - -- head and "reset" or "kept",texgetcount("realpageno"),skip,outer.prevdepth) - -- end - -- end - -- end + -- A previous version analyzed the number of lines moved to the next page in + -- synchronizepage because prevgraf is unreliable in that case. However, we cannot + -- tweak that parameter because it is also used in postlinebreak and hangafter, so + -- there is a danger for interference. Therefore we now do it dynamically. - local ignoredepth = -65536000 + -- We can also support other lists but there prevgraf probably is ok. - function vspacing.synchronizepage() + function vspacing.getnofpreviouslines(head) if enabled then - local newdepth = outer.prevdepth - local olddepth = newdepth - local oldlines = outer.prevgraf - local newlines = 0 - local boxfound = false - local head = texlists.contrib_head + if not thead then + head = texlists.page_head + end + local noflines = 0 if head then local tail = find_node_tail(tonut(head)) while tail do local id = getid(tail) if id == hlist_code then - if not boxfound then - newdepth = getdepth(tail) - boxfound = true - end - newlines = newlines + 1 - if not count then + if getsubtype(tail) == linelist_code then + noflines = noflines + 1 + else break end elseif id == vlist_code then - if not boxfound then - newdepth = getdepth(tail) - boxfound = true - end break elseif id == glue_code then local subtype = getsubtype(tail) - if not (subtype == baselineskip_code or subtype == lineskip_code) then - break - elseif boxfound and not count then - break + if subtype == baselineskip_code or subtype == lineskip_code then + -- we're ok + elseif subtype == parskip_code then + if getwidth(tail) > 0 then + break + else + -- we assume we're ok + end end elseif id == penalty_code then - if boxfound and not count then - break - end - else - -- ins, mark, kern, rule, boundary, whatsit + -- we're probably ok + elseif id == rule_code or id == kern_code then break + else + -- ins, mark, boundary, whatsit end tail = getprev(tail) end end - if boxfound then - -- what if newdepth ... - else - texset("prevdepth",ignoredepth) - outer.prevdepth = ignoredepth - end - texset("prevgraf", newlines) - outer.prevgraf = newlines + return noflines + end + end + + interfaces.implement { + name = "getnofpreviouslines", + public = true, + actions = vspacing.getnofpreviouslines, + } + + function vspacing.synchronizepage() + if enabled then if trace then - report("page %i, prevdepth %p (last depth %p), prevgraf %i (from %i), %sboxes", - texgetcount("realpageno"),olddepth,newdepth,oldlines,newlines,boxfound and "" or "no ") + local newdepth = outer.prevdepth + local olddepth = newdepth + if not texlists.page_head then + newdepth = ignoredepth + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth) + -- report("list %s",nodes.idsandsubtypes(head)) + else + if not texlists.page_head then + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end end end end @@ -2226,7 +2261,7 @@ do -- end -- } - interfaces.implement { + implement { name = "removelastline", actions = function() local head = texlists.page_head @@ -2242,7 +2277,7 @@ do end } - interfaces.implement { + implement { name = "showpagelist", -- will improve actions = function() local head = texlists.page_head @@ -2256,4 +2291,14 @@ do end } + implement { + name = "pageoverflow", + actions = { vspacing.pageoverflow, context } + } + + implement { + name = "forcepageflush", + actions = vspacing.forcepageflush + } + end diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv index b71e28219b7..7b36f9a5b52 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.mkiv @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{spac-ver}{} +\registerctxluafile{spac-ver}{optimize} % todo: use usernodes ? @@ -165,6 +165,8 @@ \installcommandhandler \??interlinespace {interlinespace} \??interlinespace +\installmacrostack\currentinterlinespace + \unexpanded\def\setupinterlinespace {\dodoubleempty\spac_linespacing_setup} @@ -205,7 +207,7 @@ \ifx\p_spac_checked_interlinespace\empty \spac_linespacing_synchronize_local \else\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check - \pushmacro\currentinterlinespace + \push_macro_currentinterlinespace \let\currentinterlinespace\p_spac_checked_interlinespace \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed \iflocalinterlinespace @@ -215,7 +217,7 @@ \the\everysetuplocalinterlinespace \localinterlinespacefalse \fi - \popmacro\currentinterlinespace + \pop_macro_currentinterlinespace \else \normalexpanded{\noexpand\doifelseassignment{\p_spac_checked_interlinespace}% \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}% @@ -230,9 +232,9 @@ \unexpanded\def\setuplocalinterlinespace[#1]% {\localinterlinespacetrue - \pushmacro\currentinterlinespace + \push_macro_currentinterlinespace \setupinterlinespace[#1]% - \popmacro\currentinterlinespace + \pop_macro_currentinterlinespace \localinterlinespacefalse} \let\switchtointerlinespace\setuplocalinterlinespace @@ -282,47 +284,50 @@ \unexpanded\def\smallbreak {\par - \ifdim\lastskip<\smallskipamount + \ifvmode\ifdim\lastskip<\smallskipamount \removelastskip - \penalty-50 + \penalty-\plusfifty \smallskip - \fi} + \fi\fi} \unexpanded\def\medbreak {\par - \ifdim\lastskip<\medskipamount + \ifvmode\ifdim\lastskip<\medskipamount \removelastskip - \penalty-100 + \penalty-\plusonehundred \medskip - \fi} + \fi\fi} \unexpanded\def\bigbreak {\par - \ifdim\lastskip<\bigskipamount + \ifvmode\ifdim\lastskip<\bigskipamount \removelastskip - \penalty-200 + \penalty-\plustwohundred \bigskip - \fi} + \fi\fi} -\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode -\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode -\unexpanded\def\allowbreak{\penalty \zeropoint} % can be hmode or vmode -\unexpanded\def\goodbreak {\par\penalty-500\relax} % forces vmode -\unexpanded\def\filbreak {\par\vfil\penalty-200\vfilneg} % forces vmode +\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode +\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode +\unexpanded\def\allowbreak{\penalty \zerocount} % can be hmode or vmode + +\unexpanded\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode +\unexpanded\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode %D Made slightly more readable: \unexpanded\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=} \unexpanded\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=} -\unexpanded\def\topglue{\nointerlineskip\vglue-\topskip\vglue} +\unexpanded\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi} \def\spac_helpers_vglue_indeed {\par - \d_spac_prevdepth\prevdepth - \hrule\s!height\zeropoint - \nobreak - \vskip\s_spac_lastskip - \prevdepth\d_spac_prevdepth} + \ifvmode + \d_spac_prevdepth\prevdepth + \hrule\s!height\zeropoint + \nobreak + \vskip\s_spac_lastskip + \prevdepth\d_spac_prevdepth + \fi} \def\spac_helpers_hglue_indeed {\dontleavehmode @@ -895,11 +900,14 @@ \dosetstrut} \unexpanded\def\setcharstrut#1% - {\setbox\strutbox\hbox{#1}% hm, maybe hpack i.e. why apply fonts .. conceptual choice + {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps \strutht\ht\strutbox \strutdp\dp\strutbox \dosetstrut} +\unexpanded\def\settightstrut + {\setcharstrut{(}} + \unexpanded\def\setfontstrut {\setcharstrut{(gplQT}} @@ -1307,9 +1315,41 @@ \let\normaloffinterlineskip\offinterlineskip % knuth's original +%D This is tricky. The prevdepth value is still set to the last one even if there is +%D nothing on the page. The same is true for prevgraf, which doesn't resemble the +%D value on the current page. +%D +%D So, here we kick in a checker but it has to happen after the output group and it +%D only has to be done once (output can trigger itself!). +%D +%D However, prevgraf is somehow bound to hangindent so we can get very +%D nasty side effects. So, in tne end we use our own variable! + +\ifdefined\getnofpreviouslines + % defined public at the lua end +\else + \let\getnofpreviouslines\!!zerocount +\fi + +\unexpanded\def\page_otr_synchronize_page_yes + {\aftergroup\page_otr_synchronize_page_indeed + \glet\page_otr_synchronize_page\relax} + +% \unexpanded\def\page_otr_synchronize_page_indeed +% {\clf_synchronizepage +% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} +% +% This has to become an otr method: \s!page_otr_command_synchonize_page + +\unexpanded\def\page_otr_synchronize_page_indeed + {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi + \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} + +\let\page_otr_synchronize_page\page_otr_synchronize_page_yes + \appendtoks - \ifvmode\clf_synchronizepage\fi % a nasty hack (tested for a while now) -\to \everyafteroutput + \page_otr_synchronize_page +\to \everyaftershipout %D My own one: @@ -1361,7 +1401,7 @@ \let\restoreinterlinepenalty\relax \unexpanded\def\spac_penalties_restore - {\global\let\restoreinterlinepenalty\relax + {\glet\restoreinterlinepenalty\relax \global\resetpenalties\interlinepenalties \global\c_spac_keep_lines_together\zerocount} @@ -1369,7 +1409,7 @@ {\ifnum#1>\c_spac_keep_lines_together \global\c_spac_keep_lines_together#1% \global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand - \global\let\restoreinterlinepenalty\spac_penalties_restore + \glet\restoreinterlinepenalty\spac_penalties_restore \fi} \def\defaultdisplaywidowpenalty {50} @@ -1701,7 +1741,7 @@ \fi \doifelsenothing{#1}{\spac_grids_snap_value_set\v!normal}{\spac_grids_snap_value_set{#1}}% \clf_vspacingsnap\nextbox\attribute\snapmethodattribute\relax - \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% *pack ? + \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap \egroup} \def\spac_grids_check_nop @@ -1816,15 +1856,15 @@ \unexpanded\def\gridboxvbox {\ifcase\gridboxlinemode - \vbox + \vpack \or - \ruledvbox + \ruledvpack \or - \vbox + \vpack \or - \ruledvbox + \ruledvpack \else - \ruledvbox + \ruledvpack \fi} \def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} @@ -1836,8 +1876,10 @@ \resetteststrut \offinterlineskip \hsize#2% - \ifnum\gridboxlinenomode=\plusthree - \gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi + \ifcase\gridboxlinenomode\or\or\or + \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer + \or + \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner \fi \topskipcorrection \gridboxvbox % calculated size @@ -2014,7 +2056,7 @@ \expandafter\nostartblankhandling \fi} -\def\nostartblankhandling#1\stopblankhandling +\unexpanded\def\nostartblankhandling#1\stopblankhandling {} \def\dostartblankhandling @@ -2042,7 +2084,7 @@ \setfalse\c_space_vspacing_done \the\everybeforeblankhandling} -\def\addpredefinedblankskip#1#2% +\unexpanded\def\addpredefinedblankskip#1#2% {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax} @@ -2089,8 +2131,56 @@ \def\spac_vspacing_nop_ignore {\ifmmode\else\par\fi} -\def\directvspacing#1% - {\par\clf_vspacing{#1}} +% \unexpanded\def\directvspacing#1% +% {\par\clf_vspacing{#1}} +% +% +% \def\directdefaultvspacing +% {\ifinpagebody % somewhat weird +% \clf_vspacing{\currentvspacing}% +% \else\ifconditional\c_spac_packed_blank +% \clf_vspacing{\currentvspacing}% +% \fi\fi} +% +% \unexpanded\def\useblankparameter#1% faster local variant +% {\edef\m_spac_blank_asked{#1\c!blank}% +% \ifx\m_spac_blank_asked\empty\else +% \clf_vspacing{\m_spac_blank_asked} +% \fi} + +\installcorenamespace{vspacing} + +\unexpanded\def\directvspacing#1% + {\par + \ifcsname\??vspacing#1\endcsname + \lastnamedcs + \else + \spac_vspacing_yes_preset{#1}% + \fi} + +\def\spac_vspacing_yes_preset#1% + {\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}% + %\writestatus{}{}% + %\writestatus{#1}{\expandafter\meaning\csname\??vspacing#1\endcsname}% + %\writestatus{}{}% + \csname\??vspacing#1\endcsname} + +\def\spac_vspacing_yes_indeed[#1]% + {\ifmmode\else + \directvspacing{#1}% + \fi} + +\def\spac_vspacing_nop_indeed + {\ifmmode\else + \directvspacing\currentvspacing + \fi} + +\def\directdefaultvspacing + {\ifinpagebody % somewhat weird + \directvspacing\currentvspacing + \else\ifconditional\c_spac_packed_blank + \directvspacing\currentvspacing + \fi\fi} \def\directcheckedvspacing {\ifinpagebody % somewhat weird @@ -2101,17 +2191,10 @@ \doubleexpandafter\gobbleoneargument \fi\fi} -\def\directdefaultvspacing - {\ifinpagebody % somewhat weird - \clf_vspacing{\currentvspacing}% - \else\ifconditional\c_spac_packed_blank - \clf_vspacing{\currentvspacing}% - \fi\fi} - \unexpanded\def\useblankparameter#1% faster local variant {\edef\m_spac_blank_asked{#1\c!blank}% \ifx\m_spac_blank_asked\empty\else - \clf_vspacing{\m_spac_blank_asked} + \directvspacing\m_spac_blank_asked \fi} % handy (and faster): @@ -2418,13 +2501,14 @@ \scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax \ifx\m_spac_hanging_location\v!right \hangindent\ifconditional\displaylefttoright-\fi\scratchwidth - \rlap{\hskip\dimexpr\hsize-\wd\nextbox\relax\box\nextbox}% + \rlap{\hskip\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new \else \hangindent\ifconditional\displaylefttoright\else-\fi\scratchwidth \llap{\box\nextbox\hskip\scratchdistance}% \fi \ignorespaces} + %D \macros %D {startfixed} %D diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf index 74e8e3e8ad5..49b023fb8ce 100644 Binary files a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf and b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf differ diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf index a2f2ee28b07..8cbd7014cae 100644 Binary files a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf and b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf differ diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua index 703d36379cb..89df440c966 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['strc-blk'] = { -- this one runs on top of buffers and structure local type, next = type, next -local find, format, validstring = string.find, string.format, string.valid +local find, formatters, validstring = string.find, string.formatters, string.valid local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array local allocate = utilities.storage.allocate @@ -25,6 +25,7 @@ structures.blocks = structures.blocks or { } local blocks = structures.blocks local sections = structures.sections local lists = structures.lists +local helpers = structures.helpers local collected = allocate() local tobesaved = allocate() @@ -42,14 +43,28 @@ end job.register('structures.blocks.collected', tobesaved, initializer) local listitem = utilities.parsers.listitem +local f_block = formatters["block.%s"] + +function blocks.uservariable(index,key,default) + local c = collected[index] + if c then + local u = c.userdata + if u then + local v = u[key] or default + if v then + context(v) + end + end + end +end -function blocks.print(name,data,hide) +local function printblock(index,name,data,hide) if hide then - context.dostarthiddenblock(name) + context.dostarthiddenblock(index,name) else - context.dostartnormalblock(name) + context.dostartnormalblock(index,name) end - context.viafile(data,format("block.%s",validstring(name,"noname"))) + context.viafile(data,f_block(validstring(name,"noname"))) if hide then context.dostophiddenblock() else @@ -57,12 +72,14 @@ function blocks.print(name,data,hide) end end +blocks.print = printblock + function blocks.define(name) states[name] = { all = "hide" } end function blocks.setstate(state,name,tag) - local all = tag == "" + local all = tag == "" local tags = not all and settings_to_array(tag) for n in listitem(name) do local sn = states[n] @@ -98,12 +115,12 @@ function blocks.select(state,name,tag,criterium) local metadata = ri.metadata if names[metadata.name] then if all then - blocks.print(name,ri.data,hide) + printblock(ri.index,name,ri.data,hide) else local mtags = metadata.tags for tag, sta in next, tags do if mtags[tag] then - blocks.print(name,ri.data,hide) + printblock(ri.index,name,ri.data,hide) break end end @@ -112,41 +129,51 @@ function blocks.select(state,name,tag,criterium) end end -function blocks.save(name,tag,buffer) -- wrong, not yet adapted - local data = buffers.getcontent(buffer) - local tags = settings_to_set(tag) - local plus, minus = false, false - if tags['+'] then plus = true tags['+'] = nil end - if tags['-'] then minus = true tags['-'] = nil end - tobesaved[#tobesaved+1] = { - metadata = { - name = name, - tags = tags, - plus = plus, +function blocks.save(name,tag,userdata,buffer) -- wrong, not yet adapted + local data = buffers.getcontent(buffer) + local tags = settings_to_set(tag) + local plus = false + local minus = false + local last = #tobesaved + 1 + local all = states[name].all + if tags['+'] then + plus = true + tags['+'] = nil + end + if tags['-'] then + minus = true + tags['-'] = nil + end + tobesaved[last] = helpers.simplify { + metadata = { + name = name, + tags = tags, + plus = plus, minus = minus, }, + index = last, + data = data or "error", + userdata = userdata and type(userdata) == "string" and helpers.touserdata(userdata), references = { - section = sections.currentid(), + section = sections.currentid(), }, - data = data or "error", } - local allstate = states[name].all if not next(tags) then - if allstate ~= "hide" then - blocks.print(name,data) + if all ~= "hide" then + printblock(last,name,data) elseif plus then - blocks.print(name,data,true) + printblock(last,name,data,true) end else local sn = states[name] for tag, _ in next, tags do if sn[tag] == nil then - if allstate ~= "hide" then - blocks.print(name,data) + if all ~= "hide" then + printblock(last,name,data) break end elseif sn[tag] ~= "hide" then - blocks.print(name,data) + printblock(last,name,data) break end end @@ -156,7 +183,8 @@ end -- interface -implement { name = "definestructureblock", actions = blocks.define, arguments = "string" } -implement { name = "savestructureblock", actions = blocks.save, arguments = "3 strings" } -implement { name = "selectstructureblock", actions = blocks.select, arguments = "4 strings" } -implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = "3 strings" } +implement { name = "definestructureblock", actions = blocks.define, arguments = "string" } +implement { name = "savestructureblock", actions = blocks.save, arguments = "4 strings" } +implement { name = "selectstructureblock", actions = blocks.select, arguments = "4 strings" } +implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = "3 strings" } +implement { name = "structureblockuservariable", actions = blocks.uservariable, arguments = { "integer", "string" } } diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv index c42bb25ec5d..e521987212d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-blk.mkiv @@ -34,48 +34,125 @@ \appendtoks \clf_definestructureblock{\currentblock}% - \setuevalue{\e!begin\currentblock}{\dodoubleempty\strc_blocks_begin[\currentblock]}% - \setuevalue{\e!end \currentblock}{}% + \setuevalue{\e!begin\currentblock}{\strc_blocks_begin{\currentblock}}% + \letvalue {\e!end \currentblock}\donothing \to \everydefineblock -\unexpanded\def\strc_blocks_begin[#1][#2]% - {\normalexpanded{\buff_pickup{@block@}{\e!begin#1}{\e!end#1}} - {}% before - {\clf_savestructureblock{#1}{#2}{@block@}}% - \plusone}% after +% The naive way: +% +% \unexpanded\def\strc_blocks_begin#1% +% {\dotripleempty\strc_blocks_begin_indeed[#1]} +% +% \unexpanded\def\strc_blocks_begin_indeed[#1][#2][#3]% +% {\normalexpanded{\buff_pickup{\??block}{\e!begin#1}{\e!end#1}} +% {}% +% {\clf_savestructureblock{#1}{#2}{#3}{\??block}}% +% \plusone}% +% +% We need to prevent too much lookahead which will gobble newlines +% that are needed for buffers. See blocks-002.tex as example. + +% maybe: systemmode "block:" + +\let\m_block \empty +\let\m_subblock\empty + +\unexpanded\def\strc_blocks_begin#1% + {\edef\m_block {#1}% + \let \m_subblock\empty + \doifelsenextoptionalcs\strc_blocks_begin_yes\strc_blocks_begin_nop} + +\unexpanded\def\strc_blocks_begin_yes[#1]% + {\doifelseassignmentcs{#1}% + \strc_blocks_begin_indeed + \strc_blocks_begin_tagged + {#1}} + +\unexpanded\def\strc_blocks_begin_tagged#1% + {\edef\m_subblock{#1}% + \doifelsenextoptionalcs\strc_blocks_begin_yes_yes\strc_blocks_begin_nop} + +\unexpanded\def\strc_blocks_begin_yes_yes[#1]% + {\strc_blocks_begin_indeed{#1}} + +\unexpanded\def\strc_blocks_begin_nop + {\strc_blocks_begin_indeed{}} + +\unexpanded\def\strc_blocks_begin_indeed#1% + {\normalexpanded{\buff_pickup{\??block}{\e!begin\m_block}{\e!end\m_block}}% + {}% + {\clf_savestructureblock{\m_block}{\m_subblock}{#1}{\??block}}% + \plusone} \let\strc_blocks_setup\relax +\newconstant \c_strc_blocks_index +\newconditional\c_strc_blocks_display + \unexpanded\def\dostarthiddenblock % called at lua end - {\startnointerference - \dostartnormalblock} + {\begingroup + \visiblefalse % blocks float + \startnointerference + \strc_start_block} \unexpanded\def\dostophiddenblock % called at lua end - {\dostopnormalblock - \stopnointerference} + {\strc_stop_block + \stopnointerference + \endgroup} + +\unexpanded\def\dostartnormalblock % called at lua end + {\begingroup + \visibletrue + \strc_start_block} -\unexpanded\def\dostartnormalblock#1% called at lua end - {\bgroup - \visibletrue % will change - \edef\currentblock{#1}% +\unexpanded\def\dostopnormalblock % called at lua end + {\strc_stop_block + \endgroup} + +\def\strc_start_block#1#2% + {\edef\currentblock{#2}% + \c_strc_blocks_index#1\relax \strc_blocks_setup \let\strc_blocks_setup\relax - \blockparameter\c!before - \useblockstyleandcolor\c!style\c!color % maybe moev one line up (font spacing) - \blockparameter\c!inner % better \c!setups + \edef\p_alternative{\blockparameter\c!alternative}% + \ifx\p_alternative\v!text + \setfalse\c_strc_blocks_display + \else + \settrue\c_strc_blocks_display + \fi + \ifconditional\c_strc_blocks_display + \blockparameter\c!before + \fi + \begingroup + \usesetupsparameter\blockparameter\relax + \dostarttagged\t!block\currentblock + \useblockstyleandcolor\c!style\c!color + \blockparameter\c!inner % old + \ifconditional\c_strc_blocks_display + \usealignparameter\blockparameter + \else + \blockparameter\c!left + \fi \ignorespaces} -\unexpanded\def\dostopnormalblock % called at lua end +\def\strc_stop_block {\removeunwantedspaces - \blockparameter\c!after - \par % todo: alternative = text, paragraph - \egroup} + \ifconditional\c_strc_blocks_display + \par + \else + \blockparameter\c!right + \fi + \dostoptagged + \endgroup + \ifconditional\c_strc_blocks_display + \blockparameter\c!after + \fi} \def\strc_blocks_set_state[#1][#2][#3]% state name tag {\clf_setstructureblockstate{#1}{#2}{#3}} \def\strc_blocks_select[#1][#2][#3][#4]% state name tag setups - {\bgroup + {\begingroup \doifelseassignment{#3} {\getparameters[\??blocktemp][\c!criterium=\v!text,#3]% \def\strc_blocks_setup{\setupcurrentblock[#3]}% @@ -83,7 +160,10 @@ {\getparameters[\??blocktemp][\c!criterium=\v!text,#4]% \def\strc_blocks_setup{\setupcurrentblock[#4]}% \clf_selectstructureblock{#1}{#2}{#3}{\csname\??blocktemp\c!criterium\endcsname}}% - \egroup} + \endgroup} + +\def\blockuservariable#1% + {\clf_structureblockuservariable\c_strc_blocks_index{#1}} % hide : save, if [+] also hidden execute % keep : save and normal execute diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi index 57b69cc7f55..d67307ba73b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-con.mkvi @@ -980,11 +980,11 @@ \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}% % \ifx\currentconstructionexpansion\empty - \global\let\currentconstructionexpansion\v!no + \glet\currentconstructionexpansion\v!no \fi % \ifx\currentconstructionreferenceprefix\empty - \global\let\currentconstructionreferenceprefix\referenceprefix + \glet\currentconstructionreferenceprefix\referenceprefix \fi \ifx\currentconstructionexpansion\s!xml \xmlstartraw @@ -994,9 +994,9 @@ \xdef\currentconstructionlist {\constructionparameter\c!list}% \xmlstopraw \ifx\currentconstructionlist\empty - \global\let\currentconstructionlist\currentconstructiontitle + \glet\currentconstructionlist\currentconstructiontitle \fi - \global\let\currentconstructioncoding\s!xml + \glet\currentconstructioncoding\s!xml \else \ifx\currentconstructionexpansion\v!yes \xdef\currentconstructiontitle {\constructionparameter\c!title}% @@ -1016,9 +1016,9 @@ \fi \fi \fi \ifx\currentconstructionlist\empty - \globallet\currentconstructionlist\currentconstructiontitle + \glet\currentconstructionlist\currentconstructiontitle \fi - \globallet\currentconstructioncoding\s!tex + \glet\currentconstructioncoding\s!tex \fi % \ifx\currentconstructiontitle\v!none % will become obsolete @@ -1093,7 +1093,7 @@ \endgroup \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}% \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}% - \edef\noexpand\currentconstructionsynchronize{\ctxlatecommand{enhancelist(\the\scratchcounter)}}% + \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}% }% \fi} @@ -1103,11 +1103,11 @@ \def\reinstateconstructionnumberentry#1% was xdef {\edef\currentconstructionattribute {\clf_getinternallistreference#1}% - \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#1)}}} + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} \def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real {\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination - \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#1)}}} + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} \installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv index 8d1fa371f71..941f561c8ef 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv @@ -65,6 +65,17 @@ \setsectionblock [\v!bodypart] % default +% \setuphead[sectionsegments=\currentheadlevel] +% \setuphead[sectionsegments=current] +% +% \startchapter[title=One,ownnumber={A}] +% \startsection[title=OneOne,ownnumber={A.B}] +% \startsubsection[title=OneOneOne,ownnumber={A.B.C}] +% test +% \stopsubsection +% \stopsection +% \stopchapter + % \appendtoks % \setsectionblock[\v!bodypart]% default % \to \everyjob diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua index 2de26ac64d1..4b2ac04b7f3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.lua @@ -18,6 +18,7 @@ if not modules then modules = { } end modules ['strc-doc'] = { local next, type, tonumber, select = next, type, tonumber, select local find, match = string.find, string.match local concat, fastcopy, insert, remove = table.concat, table.fastcopy, table.insert, table.remove +local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys local max, min = math.max, math.min local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable local setmetatableindex = table.setmetatableindex @@ -37,11 +38,13 @@ local v_auto = variables.auto local v_strict = variables.strict local v_all = variables.all local v_positive = variables.positive +local v_current = variables.current local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end) local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end) local report_structure = logs.reporter("structure","sectioning") +local report_used = logs.reporter("structure") local context = context local commands = commands @@ -122,12 +125,16 @@ local tobesaved = allocate() sections.collected = collected sections.tobesaved = tobesaved --- local function initializer() --- collected = sections.collected --- tobesaved = sections.tobesaved --- end --- --- job.register('structures.sections.collected', tobesaved, initializer) +-- We have to save this mostly redundant list because we can have (rare) +-- cases with own numbers that don't end up in the list so we get out of +-- sync when we use (*). + +local function initializer() + collected = sections.collected + tobesaved = sections.tobesaved +end + +job.register('structures.sections.collected', tobesaved, initializer) local registered = sections.registered or allocate() sections.registered = registered @@ -158,7 +165,7 @@ end local lastsaved = 0 function sections.save(sectiondata) --- local sectionnumber = helpers.simplify(section.sectiondata) -- maybe done earlier +local sectiondata = helpers.simplify(sectiondata) -- maybe done earlier local numberdata = sectiondata.numberdata local ntobesaved = #tobesaved if not numberdata or sectiondata.metadata.nolist then @@ -178,28 +185,28 @@ function sections.currentsectionindex() return lastsaved -- only for special controlled situations end -function sections.load() - setmetatableindex(collected,nil) - local lists = lists.collected - for i=1,#lists do - local list = lists[i] - local metadata = list.metadata - if metadata and metadata.kind == "section" and not metadata.nolist then - local numberdata = list.numberdata - if numberdata then - collected[#collected+1] = numberdata - end - end - end - sections.load = functions.dummy -end - -table.setmetatableindex(collected, function(t,i) - sections.load() - return collected[i] or { } -end) - +-- See comment above (*). We cannot use the following space optimization: +-- +-- function sections.load() +-- setmetatableindex(collected,nil) +-- local lists = lists.collected +-- for i=1,#lists do +-- local list = lists[i] +-- local metadata = list.metadata +-- if metadata and metadata.kind == "section" and not metadata.nolist then +-- local numberdata = list.numberdata +-- if numberdata then +-- collected[#collected+1] = numberdata +-- end +-- end +-- end +-- sections.load = functions.dummy +-- end -- +-- table.setmetatableindex(collected, function(t,i) +-- sections.load() +-- return collected[i] or { } +-- end) sections.verbose = true @@ -382,8 +389,9 @@ function sections.setentry(given) -- new number olddepth = newdepth if metadata.increment then - local oldn, newn = numbers[newdepth] or 0, 0 - local fd = forced[newdepth] + local oldn = numbers[newdepth] or 0 + local newn = 0 + local fd = forced[newdepth] if fd then if fd[1] == "add" then newn = oldn + fd[2] + 1 @@ -438,7 +446,10 @@ end function sections.reportstructure() if sections.verbose then - local numbers, ownnumbers, status, depth = data.numbers, data.ownnumbers, data.status, data.depth + local numbers = data.numbers + local ownnumbers = data.ownnumbers + local status = data.status + local depth = data.depth local d = status[depth] local o = concat(ownnumbers,".",1,depth) local n = (numbers and concat(numbers,".",1,min(depth,#numbers))) or 0 @@ -711,8 +722,12 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref criterium = 0 end -- - local firstprefix, lastprefix = 0, 16 -- too much, could max found level - if segments then + local firstprefix = 0 + local lastprefix = 16 -- too much, could max found level + if segments == v_current then + firstprefix = data.depth + lastprefix = firstprefix + elseif segments then local f, l = match(tostring(segments),"^(.-):(.+)$") if l == "*" or l == v_all then l = 100 -- new @@ -731,9 +746,11 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref end end -- - local numbers, ownnumbers = entry.numbers, entry.ownnumbers + local numbers = entry.numbers + local ownnumbers = entry.ownnumbers if numbers then - local done, preceding = false, false + local done = false + local preceding = false -- local result = kind == "direct" and { } if result then @@ -751,11 +768,14 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref if prefixlist and (kind == "section" or kind == "prefix" or kind == "direct") then -- find valid set (problem: for sectionnumber we should pass the level) -- no holes - local b, e, bb, ee = 1, #prefixlist, 0, 0 + local b = 1 + local e = #prefixlist + local bb = 0 + local ee = 0 -- find last valid number for k=e,b,-1 do local prefix = prefixlist[k] - local index = sections.getlevel(prefix) or k + local index = sections.getlevel(prefix) or k if index >= firstprefix and index <= lastprefix then local number = numbers and numbers[index] if number then @@ -771,7 +791,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref -- find valid range for k=b,e do local prefix = prefixlist[k] - local index = sections.getlevel(prefix) or k + local index = sections.getlevel(prefix) or k if index >= firstprefix and index <= lastprefix then local number = numbers and numbers[index] if number then @@ -972,6 +992,47 @@ function sections.getnumber(depth,what) -- redefined here context(askednumber) end +-- maybe handy + +function sections.showstructure() + + local tobesaved = structures.lists.tobesaved + + if not tobesaved then + return + end + + local levels = setmetatableindex("table") + local names = setmetatableindex("table") + + report_used() + report_used("sections") + for i=1,#tobesaved do + local si = tobesaved[i] + local md = si.metadata + if md and md.kind == "section" then + local level = md.level + local name = md.name + local numbers = si.numberdata.numbers + local title = si.titledata.title + report_used(" %i : %-10s %-20s %s",level,concat(numbers,"."),name,title) + levels[level][name] = true + names[name][level] = true + end + end + report_used() + report_used("levels") + for level, list in sortedhash(levels) do + report_used(" %s : % t",level,sortedkeys(list)) + end + report_used() + report_used("names") + for name, list in sortedhash(names) do + report_used(" %-10s : % t",name,sortedkeys(list)) + end + report_used() +end + -- experimental local levels = { } @@ -1042,6 +1103,7 @@ implement { name = "getsomefullstructurenumber", actions = sections.fullnumber, implement { name = "getspecificstructuretitle", actions = sections.structuredata, arguments = { "string", "'titledata.title'",false,"string" } } implement { name = "reportstructure", actions = sections.reportstructure } +implement { name = "showstructure", actions = sections.showstructure } implement { name = "registersection", diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv index 805525487af..516d87efeb7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-doc.mkiv @@ -19,6 +19,16 @@ %D This will move: +% \unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext +% {\clf_setinternalreference +% prefix {\currentstructurereferenceprefix}% +% reference {\currentstructurereference} +% internal \locationcount +% view {\interactionparameter\c!focus}% +% \relax +% \xdef\currentstructureattribute {\the\lastdestinationattribute}% +% \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}}} + \unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext {\clf_setinternalreference prefix {\currentstructurereferenceprefix}% @@ -26,7 +36,20 @@ internal \locationcount view {\interactionparameter\c!focus}% \relax - \xdef\currentstructureattribute {\the\lastdestinationattribute}% - \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\the\locationcount}}} + \xdef\currentstructureattribute + {\the\lastdestinationattribute}% + \xdef\currentstructuresynchronize + {\currentstructuresynchronize + \strc_lists_inject_enhance{#1}}} + +\unexpanded\def\setstructurecomponentsynchronization#1% todo: use ctxcontext + {\clf_setinternalreference + prefix {\currentstructurecomponentreferenceprefix}% + reference {\currentstructurecomponentreference} + internal \locationcount + view {\interactionparameter\c!focus}% + \relax + \xdef\currentstructurecomponentattribute {\the\lastdestinationattribute}% + \xdef\currentstructurecomponentsynchronize{\strc_lists_inject_enhance{#1}}} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua index 466fd515e04..e3a0ea30edb 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.lua @@ -7,3 +7,37 @@ if not modules then modules = { } end modules ['strc-flt'] = { } -- nothing + +local sequencers = utilities.sequencers +local appendaction = sequencers.appendaction +local enableaction = sequencers.enableaction +local disableaction = sequencers.disableaction + +local texgetdimen = tex.getdimen + +local trace = trackers.register("structure.sidefloats.pageflush") +local report = logs.reporter("structure","floats") + +local forcepageflush = builders.vspacing.forcepageflush + +function builders.checksidefloat(mode,indented) + local s = texgetdimen("d_page_sides_vsize") + if s > 0 then + if trace then + report("force flushing page state, height %p",s) + end + forcepageflush() + end + return indented +end + +appendaction ("newgraf","system","builders.checksidefloat") +disableaction("newgraf","builders.checksidefloat") + +interfaces.implement { + name = "enablesidefloatchecker", + onlyonce = true, + actions = function() + enableaction("newgraf","builders.checksidefloat") + end, +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi index 632c6768694..02f6fd75343 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-flt.mkvi @@ -61,9 +61,11 @@ \installcorenamespace{float} \installcorenamespace{floatbuilder} \installcorenamespace{floatcaption} +\installcorenamespace{floatframed} \installframedcommandhandler \??float {float} \??float \installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption +\installframedcommandhandler \??floatframed {floatframed} \??floatframed \let\setupfloats \setupfloat \let\setupcaption \setupfloatcaption @@ -97,6 +99,8 @@ \c!textcolor=, \c!align=, \c!number=\v!yes, + \c!offset=\v!overlay, + \c!frame=\v!off, % \c!expansion=, % \c!prefix=, % \c!prefixconnector=, @@ -110,7 +114,7 @@ % \c!stopper=, \c!suffixseparator=, % currently rather hard coded \c!suffix=\floatcaptionsuffix, - \c!distance=\emwidth, + \c!distance=\emwidth, % plus .5\emwidth minus .25\emwidth \c!conversion=\v!numbers, \c!maxwidth=\hsize, \c!command=] @@ -171,6 +175,11 @@ \c!sidethreshold=.5\strutdp, % set to "old" to check with old method \c!numbering=\v!yes] +\setupfloatframed + [\c!frame=\v!off, + \c!offset=\v!overlay, + \c!strut=\v!no] + %D Individial settings: \installcounterassociation{floatcaption} @@ -207,6 +216,7 @@ \def\strc_floats_define_a[#1][#2][#3]% name names parent {\definefloatcaption[#1][#3]% + \definefloatframed[#1][#3]% \definecounter[#1][#3]% \definelist[#1][#3]% \copylabeltext[#1=#3]% @@ -215,6 +225,7 @@ \def\strc_floats_define_b[#1][#2][#3]% name parent settings {\definefloatcaption[#1][#2]% + \definefloatframed[#1][#2]% \definecounter[#1][#2]% \definelist[#1][#2]% \copylabeltext[#1=#2]% @@ -224,6 +235,7 @@ \def\strc_floats_define_c[#1][#2]% name names {\registerfloatcaptioncounter{#1}% \definefloatcaption[#1]% + \definefloatframed[#1]% \definecounter[#1]% \definelist[#1]% \presetlabeltext[#1=\Word{#1}~]% @@ -332,6 +344,7 @@ \def\strc_floats_make_complete_caption {\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}% + \strc_floats_make_complete_caption_before \synchronizedisplaydirection % temp hack, till we have a proper model \noindent \gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking @@ -361,8 +374,26 @@ \thecurrentfloatcaption\endgraf \fi \endgroup + \strc_floats_make_complete_caption_after \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}} +%let\strc_floats_make_complete_caption_before\relax +\let\strc_floats_make_complete_caption_after \relax + +\def\strc_floats_make_complete_caption_before + {\doifelseframed\floatcaptionparameter\strc_floats_make_complete_caption_before_indeed\relax} + +\def\strc_floats_make_complete_caption_before_indeed + {\edef\m_strc_align{\floatcaptionparameter\c!align}% + \edef\m_strc_strut{\floatcaptionparameter\c!strut}% + \letfloatcaptionparameter\c!align\v!normal + \letfloatcaptionparameter\c!strut\v!no + \inheritedfloatcaptionframed + \bgroup + \letfloatcaptionparameter\c!align\m_strc_align + \letfloatcaptionparameter\c!strut\m_strc_strut + \let\strc_floats_make_complete_caption_after\egroup} + % \definefloat [figure-1] [figure] % \definefloat [figure-2] [figure] % \setupfloat [figure-1] [location=left,leftmargin=10mm] @@ -425,7 +456,7 @@ %D {\global\advance\c_strc_floats_n\plusone %D \xdef\strc_float_realpage{\datasetvariable\s!float{\number\c_strc_floats_n}\s!page}% %D \ifx\strc_float_realpage\empty -%D \globallet\strc_float_realpage\realpageno % \realfolio +%D \glet\strc_float_realpage\realpageno % \realfolio %D \fi} %D \stoptyping %D @@ -444,7 +475,7 @@ {\global\advance\c_strc_floats_n\plusone \xdef\strc_float_realpage{\pagestaterealpage\s!float{\number\c_strc_floats_n}}% \ifx\strc_float_realpage\empty - \globallet\strc_float_realpage\realpageno % \realfolio + \glet\strc_float_realpage\realpageno % \realfolio \fi} %D test case: @@ -482,7 +513,7 @@ \donothing {\writestatus\m!floatblocks{unknown float type '\currentfloat'}% \let\currentfloat\v!figure}% also a hack - \global\let\lastplacedfloat\currentfloat + \glet\lastplacedfloat\currentfloat \let\m_strc_floats_saved_userdata\empty \let\currentfloatcaption\currentfloat} @@ -493,8 +524,8 @@ {\global\emptyfloatcaptionfalse \global\nofloatcaptionfalse \global\nofloatnumberfalse - \global\let\askedfloatmethod \empty - \global\let\askedfloatoptions\empty} + \glet\askedfloatmethod \empty + \glet\askedfloatoptions\empty} % place @@ -505,10 +536,13 @@ \let\floatlocationmethod\empty \def\strc_floats_analyze_location - {% moved here, will do more + {% more will be moved here \let\floatlabel \empty \let\floatcolumn\empty \let\floatrow \empty + % + \edef\floatcaptionlocation{\floatcaptionparameter\c!location}% + % \setfloatmethodvariables\floatlocation} \unexpanded\def\strc_floats_place#tag% @@ -571,25 +605,49 @@ \strc_floats_set_current_tag{#tag}% \dodoubleempty\strc_floats_start_place_indeed} +%D We abuse the settings to pick up some float parameters too which makes it +%D messy. + \def\strc_floats_start_place_indeed[#settings][#userdata]% {\strc_floats_reset_variables - \edef\savedfloatlocation{\floatcaptionparameter\c!location}% + % save + \edef\m_location {\floatcaptionparameter\c!location}% + \edef\m_topoffset {\floatcaptionparameter\c!topoffset}% + \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}% + \edef\m_freeregion {\floatcaptionparameter\c!freeregion}% + % preset + \letfloatcaptionparameter \c!location \empty \setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}% \setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}% \setexpandedfloatcaptionparameter\c!freeregion {\floatparameter\c!freeregion}% - \setupcurrentfloatcaption[\c!location=,\c!reference=,\c!title=,\c!marking=,\c!list=,\c!bookmark=,#settings]% - \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}% - \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}% - \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}% - \def\m_strc_floats_saved_userdata{#2}% + \letfloatcaptionparameter \c!reference \empty + \letfloatcaptionparameter \c!title \empty + \letfloatcaptionparameter \c!marking \empty + \letfloatcaptionparameter \c!list \empty + \letfloatcaptionparameter \c!bookmark \empty + % pickup + \setupcurrentfloatcaption[#settings]% + \ifsecondargument + \setupcurrentfloatuserdata[#userdata]% + \def\m_strc_floats_saved_userdata{#userdata}% + \else + \let\m_strc_floats_saved_userdata\empty + \fi + % check \edef\floatlocation{\floatcaptionparameter\c!location}% - \setfloatcaptionparameter\c!location{\savedfloatlocation}% not expanded \ifx\floatlocation\empty \edef\floatlocation{\floatparameter\c!default}% \fi - \ifsecondargument - \setupcurrentfloatuserdata[#userdata]% - \fi + % inherit + \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}% + \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}% + \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}% + % restore + \letfloatcaptionparameter\c!location \m_location + \letfloatcaptionparameter\c!topoffset \m_topoffset + \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset + \letfloatcaptionparameter\c!freeregion \m_freeregion + % \strc_floats_analyze_location \doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal \bgroup @@ -928,9 +986,9 @@ \def\strc_floats_place_packaged_boxes_indeed#userdata% {\bgroup \ifconditional\usesamefloatnumber - \globallet\currentfloatnumber \previousfloatnumber - \globallet\currentfloatattribute \empty - \globallet\currentfloatsynchronize\relax + \glet\currentfloatnumber \previousfloatnumber + \glet\currentfloatattribute \empty + \glet\currentfloatsynchronize\relax \else \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}% \edef\currentfloatgroup {\floatcaptionparameter\c!group}% @@ -962,10 +1020,10 @@ \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,% \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]% [#userdata]% - \globallet\previousfloatnumber \m_strc_counters_last_registered_index - \globallet\currentfloatnumber \m_strc_counters_last_registered_index - \globallet\currentfloatattribute \m_strc_counters_last_registered_attribute - \globallet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize + \glet\previousfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatnumber \m_strc_counters_last_registered_index + \glet\currentfloatattribute \m_strc_counters_last_registered_attribute + \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize \fi % \global\setfalse\usesamefloatnumber % one shot @@ -1191,11 +1249,11 @@ {\global\setbox\floatbox\hpack to \scratchwidth {\doifnotinset\v!right\floatlocation\hss \box\floatbox - \doifnotinset\v!left \floatlocation\hss}} + \doifnotinset\v!left\floatlocation\hss}} -\def\strc_floats_realign_floatbox_horizontal_two +\def\strc_floats_realign_floatbox_horizontal_two % why is this {\global\setbox\floatbox\hpack to \scratchwidth - {\doifnot{\floatparameter\c!location}\v!left \hss + {\doifnot{\floatparameter\c!location}\v!left\hss \box\floatbox \doifnot{\floatparameter\c!location}\v!right\hss}} @@ -1336,7 +1394,7 @@ % % \def\strc_floats_align_content_indeed % {\alignstrutmode\zerocount -% \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} +% \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} % {\shiftalignedline % {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}% % {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}}% @@ -1371,7 +1429,7 @@ \def\strc_floats_align_content_indeed {\alignstrutmode\zerocount \ifx\forcedfloatmethod\v!local \else - \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} + \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin} {\strc_floats_shift_indeed\floatparameter}% \expandafter\strc_floats_align_indeed \fi} @@ -1462,23 +1520,21 @@ \fi\fi \strc_floats_align_content{\copy\b_strc_floats_content}}} + \def\strc_floats_prepare_page_caption - {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}% - \edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}% + {\edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}% \edef\p_strc_floats_caption_minwidth{\floatcaptionparameter\c!minwidth}% \edef\p_strc_floats_caption_align {\floatcaptionparameter\c!align}% \dostarttagged\t!floatcaption\empty - \ifx\p_strc_floats_caption_location\v!top - \strc_floats_prepare_page_caption_top_bottom - \else\ifx\p_strc_floats_caption_location\v!bottom - \strc_floats_prepare_page_caption_top_bottom - \else\ifx\p_strc_floats_caption_width\v!fit - \strc_floats_prepare_side_auto_caption - \else\ifx\p_strc_floats_caption_width\v!max - \strc_floats_prepare_side_auto_caption - \else - \strc_floats_prepare_side_width_caption - \fi\fi\fi\fi + \doifcommonelse\floatcaptionlocation{\v!top,\v!bottom} + {\strc_floats_prepare_page_caption_top_bottom} + {\ifx\p_strc_floats_caption_width\v!fit + \strc_floats_prepare_side_auto_caption + \else\ifx\p_strc_floats_caption_width\v!max + \strc_floats_prepare_side_auto_caption + \else + \strc_floats_prepare_side_width_caption + \fi\fi}% \dostoptagged} \def\strc_floats_prepare_page_caption_top_bottom @@ -1508,7 +1564,11 @@ \fi} \def\strc_floats_caption_set_align - {\normalexpanded{\setupalign[\v!reset,\p_strc_floats_caption_align]}} + {\edef\m_align{\v!reset\ifx\p_strc_floats_caption_align\empty\else,\fi\p_strc_floats_caption_align}% + \doifinset\v!tolerant \floatcaptionlocation{\edef\m_align{\m_align,\v!tolerant}}% + \doifinset\v!verytolerant\floatcaptionlocation{\edef\m_align{\m_align,\v!verytolerant}}% + \doifinset\v!stretch \floatcaptionlocation{\edef\m_align{\m_align,\v!stretch}}% + \setupalign[\m_align]} \def\strc_floats_prepare_side_auto_caption {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax @@ -1640,7 +1700,7 @@ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack {\d_strc_float_temp_height\ht\b_strc_floats_content \box\b_strc_floats_content - \doifnotinset\v!hang{\floatcaptionparameter\c!location} + \doifnotinset\v!hang\floatcaptionlocation {\dotfskip{\floatcaptionparameter\c!distance}}% \vbox to\d_strc_float_temp_height{#1}}} @@ -1648,7 +1708,7 @@ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack {\d_strc_float_temp_height\ht\b_strc_floats_content \vbox to\d_strc_float_temp_height{#1}% - \doifnotinset\v!hang{\floatcaptionparameter\c!location} + \doifnotinset\v!hang\floatcaptionlocation {\dotfskip{\floatcaptionparameter\c!distance}}% \box\b_strc_floats_content}} @@ -1718,7 +1778,7 @@ \def\strc_floats_build_box_next % beware, we first check on left/rightmargin because there can be left/right also {\let\next\strc_floats_build_box_next_left - \processallactionsinset[\floatcaptionparameter\c!location] + \processallactionsinset[\floatcaptionlocation] [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin, \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin, \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin, @@ -1736,7 +1796,7 @@ \let\next\strc_floats_build_box_high \else \let\next\strc_floats_build_box_middle - \processallactionsinset[\floatcaptionparameter\c!location] + \processallactionsinset[\floatcaptionlocation] [ \v!low=>\let\next\strc_floats_build_box_low, \v!middle=>\let\next\strc_floats_build_box_middle, \v!high=>\let\next\strc_floats_build_box_high]% @@ -1749,14 +1809,13 @@ \def\strc_floats_flush_left_caption_hang {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}} -\def\strc_floats_flush_caption_hang % expanded can go - {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}% - \doifelseinset\v!righthanging\p_strc_floats_caption_location +\def\strc_floats_flush_caption_hang + {\doifelseinset\v!righthanging\floatcaptionlocation {\strc_floats_flush_right_caption_hang} - {\doifelseinset\v!lefthanging\p_strc_floats_caption_location + {\doifelseinset\v!lefthanging\floatcaptionlocation {\strc_floats_flush_left_caption_hang} - {\doifelseinset\v!hang\p_strc_floats_caption_location - {\doifelseinset\v!outer\p_strc_floats_caption_location + {\doifelseinset\v!hang\floatcaptionlocation + {\doifelseinset\v!outer\floatcaptionlocation {\doifelserightpagefloat{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}} {\doifelseinset\v!right\floatcaptiondirectives {\strc_floats_flush_right_caption_hang} @@ -1834,6 +1893,7 @@ {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width \ifconditional\c_strc_floats_par_float \strc_floats_locate_side_float{\box\b_strc_floats_caption}% \vss\strc_floats_between_stack @@ -1845,12 +1905,13 @@ \strc_floats_align_content{\box\b_strc_floats_content}% \fi}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy - \vbox to \noflines\lineheight{\unvbox\scratchbox}} % \vpack ? + \vpack to \noflines\lineheight{\unvbox\scratchbox}} \def\strc_floats_build_box_bottom_stack_grid {\dp\b_strc_floats_caption\strutdepth \setbox\scratchbox\vbox {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width \ifconditional\c_strc_floats_par_float \hpack{\box\b_strc_floats_content}% \vss\strc_floats_between_stack @@ -1862,7 +1923,7 @@ \strc_floats_locate_text_float{\box\b_strc_floats_caption}% \fi}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy - \vbox to \noflines\lineheight{\unvbox\scratchbox}} % \vpack ? + \vpack to \noflines\lineheight{\unvbox\scratchbox}} \def\strc_floats_build_box_top_stack_stretch {\dp\b_strc_floats_caption\strutdepth @@ -1872,6 +1933,7 @@ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight % pack ? {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width \ifconditional\c_strc_floats_par_float \strc_floats_locate_side_float{\box\b_strc_floats_caption}% \vss\strc_floats_between_stack\vss @@ -1885,16 +1947,17 @@ \def\strc_floats_build_box_bottom_stack_stretch {\dp\b_strc_floats_caption\strutdepth - \setbox\scratchbox\vbox % pack ? - {\strc_floats_align_content{\copy\b_strc_floats_content }% + \setbox\scratchbox\vpack + {\strc_floats_align_content{\copy\b_strc_floats_content}% \strc_floats_align_caption{\copy\b_strc_floats_caption}}% \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy \vbox to \noflines\lineheight {\d_strc_float_temp_width\wd\b_strc_floats_content + \hsize\d_strc_float_temp_width \ifconditional\c_strc_floats_par_float \hpack{\box\b_strc_floats_content}% \vss\strc_floats_between_stack\vss - \strc_floats_locate_side_float{\box\b_strc_floats_caption} + \strc_floats_locate_side_float{\box\b_strc_floats_caption}% \else \page_otr_command_set_float_hsize \strc_floats_align_content{\box\b_strc_floats_content}% @@ -1906,14 +1969,14 @@ {\let\next\strc_floats_build_box_top_stack_normal \processfirstactioninset[\floatcaptionparameter\c!location] [ \v!grid=>\let\next\strc_floats_build_box_top_stack_grid, - \v!stretch=>\let\next\strc_floats_build_box_top_stack_stretch]% + \v!lines=>\let\next\strc_floats_build_box_top_stack_stretch]% was \v!grid but interfered \next} \def\strc_floats_build_box_bottom {\let\next\strc_floats_build_box_bottom_stack_normal \processfirstactioninset[\floatcaptionparameter\c!location] [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid, - \v!stretch=>\let\next\strc_floats_build_box_bottom_stack_stretch]% + \v!lines=>\let\next\strc_floats_build_box_bottom_stack_stretch]% was \v!grid but interfered \next} \def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}} @@ -1921,23 +1984,50 @@ \unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}} -\let\strc_floats_mark_box_as_free\relax - \def\strc_floats_build_box - {\global\setbox\floatbox\vbox % pack ? probably not + {\strc_floats_build_box_before + \global\setbox\floatbox\vbox % pack ? probably not {\strc_floats_set_local_hsize \forgetall \ifconditional\c_floats_store_minimal_package \strc_floats_build_box_separate_make \else - \let\floatcaptionarrangement\s!default + % \let\floatcaptionarrangement\s!default + \let\floatcaptionarrangement\v!bottom % for Alan \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname \lastnamedcs \else \strc_floats_build_box_default \fi - \fi}} + \fi}% + \strc_floats_build_box_after} + +% \let\strc_floats_build_box_before\relax +% \let\strc_floats_build_box_after \relax + +\def\strc_floats_build_box_before + {\let\currentfloatframed\currentfloat + \floatwidth\wd + \ifdim\wd\b_strc_floats_content>\wd\b_strc_floats_caption + \b_strc_floats_content\else\b_strc_floats_caption + \fi} + +\def\strc_floats_build_box_after + {\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax} + +\def\strc_floats_build_box_after_indeed + {\global\setbox\floatbox\hpack + {\edef\m_width{\floatframedparameter\c!width}% + \ifx\m_width\v!fit + \let\m_width\floatwidth + \else\ifx\m_width\v!broad + \let\m_width\v!fit + \fi\fi + \letfloatframedparameter\c!strut\v!no + \letfloatframedparameter\c!width\m_width + \inheritedfloatframedframed + {\box\floatbox}}} % special purpose: used in floatcombinations @@ -1954,7 +2044,7 @@ \vpack to \onepoint{\box\b_strc_floats_caption}} \def\strc_floats_build_box_separate_split#1% - {\setbox\scratchbox\vbox{% + {\setbox\scratchbox\vbox\bgroup \setbox\scratchbox\vpack{#1}% \unvbox\scratchbox\relax \setbox\scratchbox\lastbox @@ -1965,13 +2055,20 @@ \unvbox\scratchbox \setbox\scratchbox\lastbox % \exitloop - % \fi}% + % \fi + %}% \splittopskip\zeropoint \global\setbox\b_strc_floats_separate_content\vsplit\scratchbox to \onepoint \global\setbox\b_strc_floats_separate_caption\vsplit\scratchbox to \onepoint - \global\setbox\b_strc_floats_separate_content\vpack{\unvbox\b_strc_floats_separate_content\setbox0\lastbox\unvbox0}% - \global\setbox\b_strc_floats_separate_caption\tpack{\unvbox\b_strc_floats_separate_caption\setbox0\lastbox\unvbox0}% - }} + \egroup + \global\setbox\b_strc_floats_separate_content\vpack + {\unvbox\b_strc_floats_separate_content + \setbox\scratchbox\lastbox + \unvbox\scratchbox}% + \global\setbox\b_strc_floats_separate_caption\tpack + {\unvbox\b_strc_floats_separate_caption + \setbox\scratchbox\lastbox + \unvbox\scratchbox}} % \def\strc_floats_build_box_step#1% % {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}} @@ -2105,8 +2202,9 @@ \def\strc_floats_prepare_side_caption_fit % or center when smaller {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax - \setbox\b_strc_floats_caption\vbox + \setbox\b_strc_floats_caption\vbox {\forgetall % needed? + \strc_floats_caption_set_align \hsize\wd\b_strc_floats_content \strc_floats_make_complete_caption}% \else @@ -2295,6 +2393,8 @@ \definesystemconstant{fxbt} \definesystemconstant{fixd} +% can move to page-one: + \installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here \installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force \installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left @@ -2330,76 +2430,6 @@ \installfloatmethod \s!singlecolumn \s!fxbt \page_one_place_float_bottom \installfloatmethod \s!singlecolumn \s!fixd \page_one_place_float_force -\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here -\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force -%installfloatmethod \s!multicolumn \v!left -%installfloatmethod \s!multicolumn \v!right -%installfloatmethod \s!multicolumn \v!text -\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top -\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom -%installfloatmethod \s!multicolumn \v!auto -%installfloatmethod \s!multicolumn \v!margin -%installfloatmethod \s!multicolumn \v!opposite -%installfloatmethod \s!multicolumn \v!page -%installfloatmethod \s!multicolumn \v!leftpage -%installfloatmethod \s!multicolumn \v!rightpage -%installfloatmethod \s!multicolumn \v!inmargin -%installfloatmethod \s!multicolumn \v!inleft -%installfloatmethod \s!multicolumn \v!inright -%installfloatmethod \s!multicolumn \v!leftmargin -%installfloatmethod \s!multicolumn \v!rightmargin -%installfloatmethod \s!multicolumn \v!leftedge -%installfloatmethod \s!multicolumn \v!rightedge -%installfloatmethod \s!multicolumn \v!somewhere -%installfloatmethod \s!multicolumn \v!backspace -%installfloatmethod \s!multicolumn \v!cutspace -%installfloatmethod \s!multicolumn \s!tblr -%installfloatmethod \s!multicolumn \s!lrtb -%installfloatmethod \s!multicolumn \s!tbrl -%installfloatmethod \s!multicolumn \s!rltb -%installfloatmethod \s!multicolumn \s!fxtb -%installfloatmethod \s!multicolumn \s!btlr -%installfloatmethod \s!multicolumn \s!lrbt -%installfloatmethod \s!multicolumn \s!btrl -%installfloatmethod \s!multicolumn \s!rlbt -%installfloatmethod \s!multicolumn \s!fxbt -%installfloatmethod \s!multicolumn \s!fixd - -\installfloatmethod \s!columnset \v!here \page_set_place_float_here -\installfloatmethod \s!columnset \v!force \page_set_place_float_force -%installfloatmethod \s!columnset \v!left -%installfloatmethod \s!columnset \v!right -%installfloatmethod \s!columnset \v!text -\installfloatmethod \s!columnset \v!top \page_set_place_float_top -\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom -%installfloatmethod \s!columnset \v!auto -%installfloatmethod \s!columnset \v!margin -%installfloatmethod \s!columnset \v!opposite -\installfloatmethod \s!columnset \v!page \page_set_place_float_page -%installfloatmethod \s!columnset \v!leftpage -%installfloatmethod \s!columnset \v!rightpage -%installfloatmethod \s!columnset \v!inmargin -%installfloatmethod \s!columnset \v!inleft -%installfloatmethod \s!columnset \v!inright -%installfloatmethod \s!columnset \v!leftmargin -%installfloatmethod \s!columnset \v!rightmargin -%installfloatmethod \s!columnset \v!leftedge -%installfloatmethod \s!columnset \v!rightedge -%installfloatmethod \s!columnset \v!somewhere -%installfloatmethod \s!columnset \v!backspace -%installfloatmethod \s!columnset \v!cutspace -\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot -\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot -\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot -\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot -\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot -\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot -\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot -\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot -\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot -\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot -\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force - %D Local floats: \installcorenamespace{localfloats} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi index 0bea62de8d0..0fc20432081 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-itm.mkvi @@ -352,8 +352,8 @@ \csname\??itemgroupsetting\currentitemgroup\endcsname} \def\strc_itemgroups_reset_continue_state - {\global\expandafter\let\csname\??itemgroupoption \currentitemgroup\endcsname\relax - \global\expandafter\let\csname\??itemgroupsetting\currentitemgroup\endcsname\relax} + {\expandafter\glet\csname\??itemgroupoption \currentitemgroup\endcsname\relax + \expandafter\glet\csname\??itemgroupsetting\currentitemgroup\endcsname\relax} % These will become keywords. We will also add a feature to keep the while set % together. diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi index cd10c9def20..4a6f142458e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lnt.mkvi @@ -242,13 +242,13 @@ \def\strc_linenotes_traced_indeed#1% {\iftracelinenotes - \hbox to \zeropoint + \hpack to \zeropoint {\forgetall \hsize\zeropoint \hss - \vbox to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}% + \vpack to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}% {\color[blue]{\vl}}% - \vbox to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}% + \vpack to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}% \hss}% \prewordbreak \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua index 13bdf77865b..bc6135e7242 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.lua @@ -35,6 +35,8 @@ local commands = commands local implement = interfaces.implement local conditionals = tex.conditionals +local ctx_latelua = context.latelua + local structures = structures local lists = structures.lists local sections = structures.sections @@ -97,7 +99,8 @@ local v_default = variables.default -- for the moment not public -- local function zerostrippedconcat(t,separator) - local f, l = 1, #t + local f = 1 + local l = #t for i=f,l do if t[i] == 0 then f = f + 1 @@ -307,7 +310,8 @@ local synchronizepage = function(r) -- bah ... will move return synchronizepage(r) end -function lists.enhance(n) +local function enhancelist(specification) + local n = specification.n local l = cached[n] if not l then report_lists("enhancing %a, unknown internal",n) @@ -348,6 +352,8 @@ function lists.enhance(n) end end +lists.enhance = enhancelist + -- we can use level instead but we can also decide to remove level from the metadata local nesting = { } @@ -847,18 +853,22 @@ end function lists.userdata(name,r,tag) -- to tex (todo: xml) local result = lists.result[r] if result then - local userdata, metadata = result.userdata, result.metadata + local userdata = result.userdata local str = userdata and userdata[tag] if str then - return str, metadata + return str, result.metadata end end end function lists.uservalue(name,r,tag,default) -- to lua local str = lists.result[r] - str = str and str.userdata - str = str and str[tag] + if str then + str = str.userdata + end + if str then + str = str[tag] + end return str or default end @@ -1071,8 +1081,19 @@ implement { implement { name = "enhancelist", - actions = lists.enhance, - arguments = "integer" + arguments = "integer", + actions = function(n) + enhancelist { n = n } + end +} + +implement { + name = "deferredenhancelist", + arguments = "integer", + protected = true, -- for now, pre 1.09 + actions = function(n) + ctx_latelua { action = enhancelist, n = n } + end, } implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi index 153d879b791..7bc859b670b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-lst.mkvi @@ -145,8 +145,9 @@ {\endgroup} % \unexpanded -\def\strc_lists_inject_enhance#listindex#internal% - {\normalexpanded{\ctxlatecommand{enhancelist(\number#listindex)}}} + +\def\strc_lists_inject_enhance#listindex% + {\expandafter\clf_deferredenhancelist\number#listindex\relax} \unexpanded\def\strc_lists_inject_yes[#settings][#userdata]% can be used directly {\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let... @@ -168,16 +169,16 @@ userdata {\detokenize\expandafter{\normalexpanded{#userdata}}} \relax \edef\currentlistnumber{\the\scratchcounter}% -\setxvalue{\??listlocations\currentlist}{\the\locationcount}% + \setxvalue{\??listlocations\currentlist}{\the\locationcount}% \ifx\p_location\v!here % this branch injects nodes ! - \strc_lists_inject_enhance{\currentlistnumber}{\the\locationcount}% + \strc_lists_inject_enhance{\currentlistnumber}% \clf_setinternalreference internal \locationcount view {\interactionparameter\c!focus}% \relax % this will change \xdef\currentstructurelistattribute{\the\lastdestinationattribute}% - \dontleavehmode\hbox attr \destinationattribute \lastdestinationattribute{}% todo + \dontleavehmode\hpack attr \destinationattribute \lastdestinationattribute{}% todo \else % and this one doesn't \clf_enhancelist\currentlistnumber\relax @@ -467,7 +468,7 @@ \relax} \def\firststructureelementinlist#list% expandable - {\clf_firstinset{#list}} + {\firstinset{#list}} \def\structurelistsize {\clf_listsize} @@ -871,7 +872,7 @@ \appendtoks \dontcomplain - \letinteractionparameter\c!width\zeropoint % a weird one + % \letinteractionparameter\c!width\zeropoint % a weird one \to \t_lists_every_renderingsetup \appendtoks @@ -1091,7 +1092,7 @@ \fi \ifconditional\c_lists_has_page \ifconditional\c_lists_show_page - \setbox\b_strc_lists_page\hbox { + \setbox\b_strc_lists_page\hpack { \scratchdimen\listalternativeparameter\c!width \hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi { \hfill diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua index 24a7fd4919f..0221b9b8f19 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mar.lua @@ -13,78 +13,82 @@ local insert, concat = table.insert, table.concat local tostring, next, rawget, type = tostring, next, rawget, type local lpegmatch = lpeg.match -local context = context -local commands = commands +local context = context +local commands = commands -local implement = interfaces.implement +local implement = interfaces.implement -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex -local nuts = nodes.nuts -local tonut = nuts.tonut +local nuts = nodes.nuts +local tonut = nuts.tonut -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local getbox = nuts.getbox +local getid = nuts.getid +local getlist = nuts.getlist +local getattr = nuts.getattr +local getbox = nuts.getbox -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id +local nextnode = nuts.traversers.node -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes -local texsetattribute = tex.setattribute +local glyph_code = nodecodes.glyph +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local whatsit_code = nodecodes.whatsit -local a_marks = attributes.private("structure","marks") +local lateluawhatsit_code = whatsitcodes.latelua -local trace_marks_set = false trackers.register("marks.set", function(v) trace_marks_set = v end) -local trace_marks_get = false trackers.register("marks.get", function(v) trace_marks_get = v end) -local trace_marks_all = false trackers.register("marks.detail", function(v) trace_marks_all = v end) +local texsetattribute = tex.setattribute -local report_marks = logs.reporter("structure","marks") +local a_marks = attributes.private("structure","marks") -local variables = interfaces.variables +local trace_marks_set = false trackers.register("marks.set", function(v) trace_marks_set = v end) +local trace_marks_get = false trackers.register("marks.get", function(v) trace_marks_get = v end) +local trace_marks_all = false trackers.register("marks.detail", function(v) trace_marks_all = v end) -local v_first = variables.first -local v_last = variables.last -local v_previous = variables.previous -local v_next = variables.next -local v_top = variables.top -local v_bottom = variables.bottom -local v_current = variables.current -local v_default = variables.default -local v_page = variables.page -local v_all = variables.all -local v_keep = variables.keep +local report_marks = logs.reporter("structure","marks") -local v_nocheck_suffix = ":" .. variables.nocheck +local variables = interfaces.variables -local v_first_nocheck = variables.first .. v_nocheck_suffix -local v_last_nocheck = variables.last .. v_nocheck_suffix -local v_previous_nocheck = variables.previous .. v_nocheck_suffix -local v_next_nocheck = variables.next .. v_nocheck_suffix -local v_top_nocheck = variables.top .. v_nocheck_suffix -local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix +local v_first = variables.first +local v_last = variables.last +local v_previous = variables.previous +local v_next = variables.next +local v_top = variables.top +local v_bottom = variables.bottom +local v_current = variables.current +local v_default = variables.default +local v_page = variables.page +local v_all = variables.all +local v_keep = variables.keep -local structures = structures -local marks = structures.marks -local lists = structures.lists +local v_nocheck_suffix = ":" .. variables.nocheck -local settings_to_array = utilities.parsers.settings_to_array +local v_first_nocheck = variables.first .. v_nocheck_suffix +local v_last_nocheck = variables.last .. v_nocheck_suffix +local v_previous_nocheck = variables.previous .. v_nocheck_suffix +local v_next_nocheck = variables.next .. v_nocheck_suffix +local v_top_nocheck = variables.top .. v_nocheck_suffix +local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix -local boxes_too = false -- at some point we can also tag boxes or use a zero char +local structures = structures +local marks = structures.marks +local lists = structures.lists + +local settings_to_array = utilities.parsers.settings_to_array + +local boxes_too = false -- at some point we can also tag boxes or use a zero char directives.register("marks.boxestoo", function(v) boxes_too = v end) -marks.data = marks.data or allocate() +local data = marks.data or allocate() +marks.data = data storage.register("structures/marks/data", marks.data, "structures.marks.data") -local data = marks.data local stack, topofstack = { }, 0 local ranges = { @@ -116,9 +120,9 @@ end -- identify range local function sweep(head,first,last) - for n in traverse(head) do - local id = getid(n) - if id == glyph_code then + for n, id, subtype in nextnode, head do + -- we need to handle empty heads so we test for latelua + if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then local a = getattr(n,a_marks) if not a then -- next @@ -433,7 +437,8 @@ local function resolve(name,first,last,strict,quitonfalse,notrace) if trace_marks_get and not notrace then report_marks("found chain [ % => T ]",fullchain) end - local chaindata, chainlength = { }, #fullchain + local chaindata = { } + local chainlength = #fullchain for i=1,chainlength do local cname = fullchain[i] if data[cname].set > 0 then @@ -509,7 +514,8 @@ local methods = { } local function doresolve(name,rangename,swap,df,dl,strict) local range = ranges[rangename] or ranges[v_page] - local first, last = range.first, range.last + local first = range.first + local last = range.last if trace_marks_get then report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a", "resolving",name,rangename,swap or false,first,last,df,dl,strict or false) @@ -638,7 +644,10 @@ function marks.tracers.showtable() context.tabulaterowbold("name","parent","chain","children","fullchain") context.ML() for k, v in table.sortedpairs(data) do - local parent, chain, children, fullchain = v.parent or "", v.chain or "", v.children or { }, v.fullchain or { } + local parent = v.parent or "" + local chain = v.chain or "" + local children = v.children or { } + local fullchain = v.fullchain or { } table.sort(children) -- in-place but harmless context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," ")) end @@ -647,28 +656,49 @@ end -- pushing to context: -local separator = context.nested.markingseparator -local command = context.nested.markingcommand -local ctxconcat = context.concat - -local function fetchonemark(name,range,method) - context(command(name,fetched(name,range,method))) -end +-- local separator = context.nested.markingseparator +-- local command = context.nested.markingcommand +-- local ctxconcat = context.concat + +-- local function fetchonemark(name,range,method) +-- context(command(name,fetched(name,range,method))) +-- end + +-- local function fetchtwomarks(name,range) +-- ctxconcat( { +-- command(name,fetched(name,range,v_first)), +-- command(name,fetched(name,range,v_last)), +-- }, separator(name)) +-- end + +-- local function fetchallmarks(name,range) +-- ctxconcat( { +-- command(name,fetched(name,range,v_previous)), +-- command(name,fetched(name,range,v_first)), +-- command(name,fetched(name,range,v_last)), +-- }, separator(name)) +-- end + + local ctx_separator = context.markingseparator + local ctx_command = context.markingcommand + + local function fetchonemark(name,range,method) + ctx_command(name,fetched(name,range,method)) + end -local function fetchtwomarks(name,range) - ctxconcat( { - command(name,fetched(name,range,v_first)), - command(name,fetched(name,range,v_last)), - }, separator(name)) -end + local function fetchtwomarks(name,range) + ctx_command(name,fetched(name,range,v_first)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_last)) + end -local function fetchallmarks(name,range) - ctxconcat( { - command(name,fetched(name,range,v_previous)), - command(name,fetched(name,range,v_first)), - command(name,fetched(name,range,v_last)), - }, separator(name)) -end + local function fetchallmarks(name,range) + ctx_command(name,fetched(name,range,v_previous)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_first)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_last)) + end function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first if trace_marks_get then diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv index 775d2aca157..0b80a26cd63 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-mat.mkiv @@ -208,9 +208,9 @@ \c!reference=#1,\c!title=\namedformulaentry,\c!bookmark=]% [#2]% \glet\namedformulaentry\empty % \relax - \globallet#3\m_strc_counters_last_registered_index - \globallet#4\m_strc_counters_last_registered_synchronize - \globallet#5\m_strc_counters_last_registered_attribute} + \glet#3\m_strc_counters_last_registered_index + \glet#4\m_strc_counters_last_registered_synchronize + \glet#5\m_strc_counters_last_registered_attribute} % modes: 0=unset, 1=forced, 2=none, 3=reference @@ -880,6 +880,9 @@ \par \fi \bgroup % HERE + \iftrialtypesetting\else + \global\advance\c_strc_formulas_n\plusone + \fi \def\currentformula{#1}% \strc_math_set_split \dostarttaggedchained\t!formula\currentformula\??formula @@ -896,7 +899,7 @@ {\edef\p_option{\formulaparameter\c!option}% \edef\p_option{\ifx\p_option\empty\else\p_option,\fi#2}}% \else - \edef\p_option{\formulaparameter\c!option} + \edef\p_option{\formulaparameter\c!option}% \fi \ifx\p_option\empty \else \rawprocesscommacommand[\p_option]\strc_formulas_option @@ -922,10 +925,15 @@ % tagging of formulanumbers is not ok (we get two display maths blobs) +\newcount\c_strc_formulas_n + +\ifdefined\dotagregisterformula \else \let\dotagregisterformula\gobbleoneargument \fi + \unexpanded\def\strc_formulas_stop_formula {\strc_formulas_place_number % in case it hasn't happened yet \strc_formulas_flush_number % in case we are in native mode \dostarttagged\t!formulacontent\empty + \dotagregisterformula\c_strc_formulas_n \csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname \dostoptagged \dostoptagged diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua index bb9d64beb57..b2c8106e153 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-not.lua @@ -247,15 +247,38 @@ end notes.internal = internal notes.ordered = ordered +-- local function onsamepageasprevious(tag) +-- local same = false +-- local n = getn(tag,n) +-- local current = get(tag,n) +-- local previous = get(tag,n-1) +-- if current and previous then +-- local cr = current.references +-- local pr = previous.references +-- same = cr and pr and cr.realpage == pr.realpage +-- end +-- return same and true or false +-- end + local function onsamepageasprevious(tag) - local same = false - local n = getn(tag,n) - local current, previous = get(tag,n), get(tag,n-1) - if current and previous then - local cr, pr = current.references, previous.references - same = cr and pr and cr.realpage == pr.realpage + local n = getn(tag,n) + local current = get(tag,n) + if not current then + return false + end + local cr = current.references + if not cr then + return false + end + local previous = get(tag,n-1) + if not previous then + return false + end + local pr = previous.references + if not pr then + return false end - return same and true or false + return cr.realpage == pr.realpage end notes.doifonsamepageasprevious = onsamepageasprevious @@ -471,7 +494,7 @@ local texsetglue = tex.setglue local function check_spacing(n,i) local gn, pn, mn = texgetglue(n) local gi, pi, mi = texgetglue(i > 1 and "s_strc_notes_inbetween" or "s_strc_notes_before") - local gt, pt, mt = gn+gi, pn+pi, mn+mi + local gt, pt, mt = gn + gi, pn + pi, mn + mi if trace_insert then report_insert("%s %i: %p plus %p minus %p","always ",n,gn,pn,mn) report_insert("%s %i: %p plus %p minus %p",i > 1 and "inbetween" or "before ",n,gi,pi,mi) diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi index 8952f0e9c2c..3ce01ef3454 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-not.mkvi @@ -456,7 +456,7 @@ \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}% \settrue\processingnote \ifconditional\c_strc_notes_skip - \globallet\lastnotesymbol\strc_notes_inject_symbol_nop + \glet\lastnotesymbol\strc_notes_inject_symbol_nop \else \iftypesettinglines % otherwise problems with \type {xxx} \ignorelines % makes footnotes work in \startlines ... \stoplines @@ -465,7 +465,7 @@ \strc_notes_inject_symbol_yes \else \unskip\unskip - \globallet\lastnotesymbol\strc_notes_inject_symbol_yes + \glet\lastnotesymbol\strc_notes_inject_symbol_yes \fi \fi \ifconditional\postponingnotes % todo: per note class @@ -734,7 +734,7 @@ \dostoptagged \egroup \endgroup - \globallet\lastnotesymbol\relax} + \glet\lastnotesymbol\relax} \unexpanded\def\strc_notes_inject_dummy % temp hack {\removeunwantedspaces @@ -745,7 +745,7 @@ \fi \nobreak \hpack to .5\emwidth{}% - \globallet\lastnotesymbol\relax} + \glet\lastnotesymbol\relax} \unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list {\edef\p_textseparator{\noteparameter\c!textseparator}% @@ -1057,18 +1057,6 @@ \newskip \s_strc_notes_distance % we need to implement stretch \newcount\c_strc_notes_columns -% \def\strc_notes_set_distance -% {\begingroup -% \setbox\scratchbox\vbox % no reuse as it can mirror -% {\forgetall -% \restoreglobalbodyfont % really needed -% \dontcomplain -% \noteparameter\c!before -% \placenoterule -% \noteparameter\c!after}% -% \expandafter\endgroup\expandafter -% \s_strc_notes_distance\the\htdp\scratchbox\relax} % also dp now - \newskip \s_strc_notes_before \newskip \s_strc_notes_inbetween \newconditional\c_strc_notes_first_flushed @@ -1382,19 +1370,22 @@ \fi} \appendtoks - \strc_notes_set_penalties - \forgetall % again - \strc_notes_set_bodyfont - \redoconvertfont % to undo \undo calls in in headings etc - \splittopskip\strutht % not actually needed here - \splitmaxdepth\strutdp % not actually needed here - % not: -% \leftmargindistance \noteparameter\c!margindistance -% \rightmargindistance\leftmargindistance -% \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? -% \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? -% \fi - % + \strc_notes_set_penalties + \forgetall % again + \strc_notes_set_bodyfont + \redoconvertfont % to undo \undo calls in in headings etc + \splittopskip\strutht % not actually needed here + \splitmaxdepth\strutdp % not actually needed here + % + % not: + % + % \leftmargindistance \noteparameter\c!margindistance + % \rightmargindistance\leftmargindistance + % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? + % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? + % \fi + % + \pickupattributes \to \everyinsidenoteinsert % maybe but better use [scope=local] here @@ -1551,7 +1542,7 @@ \unexpanded\def\postponenotes {\ifconditional\postponingnotes\else \global\settrue\postponingnotes - \global\let\flushnotes\doflushnotes + \glet\flushnotes\doflushnotes \clf_postponenotes \fi} @@ -1560,7 +1551,7 @@ \unexpanded\def\startpostponingnotes % experimental, page-mix {\ifconditional\postponingnotes\else \global\settrue\postponingnotes - %\global\let\flushnotes\doflushnotes + %\glet\flushnotes\doflushnotes \clf_postponenotes \fi} @@ -1581,7 +1572,7 @@ \clf_flushpostponednotes% this also resets the states ! \global\setfalse\postponednote \global\setfalse\postponingnotes - \global\let\flushnotes\relax + \glet\flushnotes\relax \endgroup \fi} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua index e1a133f4a30..25e575a56f7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-num.lua @@ -273,7 +273,7 @@ end function counters.compact(name,level,onlynumbers) local cd = counterdata[name] if cd then - local data = cd.data + local data = cd.data local compact = { } for i=1,level or #data do local d = data[i] @@ -541,22 +541,26 @@ function counters.converted(name,spec) -- name can be number and reference to st local cd if type(name) == "number" then cd = specials.retrieve("counter",name) - cd = cd and cd.counter + if cd then + cd = cd.counter + end else cd = counterdata[name] end if cd then - local spec = spec or { } - local numbers, ownnumbers = { }, { } - local reverse = spec.order == v_reverse - local kind = spec.type or "number" - local data = cd.data + local spec = spec or { } + local numbers = { } + local ownnumbers = { } + local reverse = spec.order == v_reverse + local kind = spec.type or "number" + local data = cd.data for k=1,#data do local v = data[k] -- somewhat messy, what if subnr? only last must honour kind? local vn if v.own then - numbers[k], ownnumbers[k] = v.number, v.own + numbers[k] = v.number + ownnumbers[k] = v.own else if kind == v_first then vn = v.first @@ -577,13 +581,14 @@ function counters.converted(name,spec) -- name can be number and reference to st end end end - numbers[k], ownnumbers[k] = vn or v.number, nil + numbers[k] = vn or v.number + ownnumbers[k] = nil end end - cd.numbers = numbers + cd.numbers = numbers cd.ownnumbers = ownnumbers sections.typesetnumber(cd,'number',spec) - cd.numbers = nil + cd.numbers = nil cd.ownnumbers = nil end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv index be35e7671ef..747df29a563 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-num.mkiv @@ -578,9 +578,9 @@ \xdef\currentstructurecomponentlist {#2\c!list}% \xmlstopraw \ifx\currentstructurecomponentlist\empty - \globallet\currentstructurecomponentlist\currentstructurecomponenttitle + \glet\currentstructurecomponentlist\currentstructurecomponenttitle \fi - \globallet\currentstructurecomponentcoding\s!xml + \glet\currentstructurecomponentcoding\s!xml \else \ifx\currentstructurecomponentexpansion\v!yes \xdef\currentstructurecomponenttitle {#2\c!title}% @@ -600,9 +600,9 @@ \fi \fi \fi \ifx\currentstructurecomponentlist\empty - \globallet\currentstructurecomponentlist\currentstructurecomponenttitle + \glet\currentstructurecomponentlist\currentstructurecomponenttitle \fi - \globallet\currentstructurecomponentcoding\s!tex + \glet\currentstructurecomponentcoding\s!tex \fi % \setnextinternalreference @@ -669,11 +669,9 @@ %} \relax \xdef\m_strc_counters_last_registered_index{\the\scratchcounter}% - \clf_setinternalreference - internal \locationcount - \relax - \xdef\m_strc_counters_last_registered_attribute {\the\lastdestinationattribute}% - \xdef\m_strc_counters_last_registered_synchronize{\strc_lists_inject_enhance{\m_strc_counters_last_registered_index}{\the\locationcount}}} + \setstructurecomponentsynchronization\m_strc_counters_last_registered_index + \glet\m_strc_counters_last_registered_attribute \currentstructurecomponentattribute + \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize} \let\m_strc_counters_last_registered_index \relax \let\m_strc_counters_last_registered_attribute \relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua index dcd35fc20b7..ee1b245b99b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.lua @@ -113,8 +113,9 @@ end -- end function pages.number(realdata,pagespec) - local userpage, block = realdata.number, realdata.block or "" -- sections.currentblock() - local numberspec = realdata.numberdata + local userpage = realdata.number + local block = realdata.block or "" -- sections.currentblock() + local numberspec = realdata.numberdata local conversionset = (pagespec and pagespec.conversionset ~= "" and pagespec.conversionset) or (numberspec and numberspec.conversionset ~= "" and numberspec.conversionset) or "" local conversion = (pagespec and pagespec.conversion ~= "" and pagespec.conversion ) or (numberspec and numberspec.conversion ~= "" and numberspec.conversion ) or "" local starter = (pagespec and pagespec.starter ~= "" and pagespec.starter ) or (numberspec and numberspec.starter ~= "" and numberspec.starter ) or "" @@ -212,9 +213,11 @@ end function helpers.prefixlastpage(data,prefixspec,pagespec) if data then - local r = data.references - local ls, lr = r.section, r.realpage - r.section, r.realpage = r.lastsection or r.section, r.lastrealpage or r.realpage + local r = data.references + local ls = r.section + local lr = r.realpage + r.section = r.lastsection or r.section + r.realpage = r.lastrealpage or r.realpage helpers.prefixpage(data,prefixspec,pagespec) r.section, r.realpage = ls, lr end @@ -227,7 +230,8 @@ function helpers.analyze(entry,specification) if not entry then return false, false, "no entry" end - local yes, no = variables.yes, variables.no + local yes = variables.yes + local no = variables.no -- section data local references = entry.references if not references then diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv index d56f0de544e..01361e2c53b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-pag.mkiv @@ -152,7 +152,7 @@ \setupsubpagenumber [\c!way=\v!by\v!part, - \c!state=\v!stop] + \c!state=\v!start] % was stop but start looks better in logging % Counters @@ -263,7 +263,7 @@ \def\currentpage{\the\realpageno}% rather useless \appendtoks - \ifnum\realpageno>\lastpage \globallet\lastpage\lastrealpage \fi + \ifnum\realpageno>\lastpage \glet\lastpage\lastrealpage \fi \to \everyinitializepagecounters % States: @@ -309,6 +309,8 @@ % some day ifsinglesided and ifdoublesided will become obsolete +\newtoks\everysidedswitch + \appendtoks \singlesidedfalse \setfalse\layoutisdoublesided \doublesidedfalse \setfalse\layoutissinglesided @@ -317,13 +319,7 @@ \processallactionsinset[\directpagenumberingparameter\c!alternative] [ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided, \v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]% - \ifdefined\trackingmarginnotestrue - \ifdoublesided - \trackingmarginnotestrue - \else - \trackingmarginnotesfalse - \fi - \fi + \the\everysidedswitch \pageduplexmode \ifsinglesided \ifdoublesided\plustwo\else\zerocount\fi @@ -334,6 +330,16 @@ \strc_pagenumbers_set_location \to \everysetuppagenumbering +\appendtoks + \ifdefined\trackingmarginnotestrue + \ifdoublesided + \trackingmarginnotestrue + \else + \trackingmarginnotesfalse + \fi + \fi +\to \everysidedswitch + \ifdefined \page_backgrounds_recalculate \else \let\page_backgrounds_recalculate\relax \fi @@ -401,11 +407,10 @@ \unexpanded\def\strc_pagenumbers_check_state_change#1#2% {\edef\m_strc_pagenumbers_state_new{\namedcounterparameter#1\c!state}% \ifx\m_strc_pagenumbers_state_new\m_strc_pagenumbers_state_old \else - \doifelse\m_strc_pagenumbers_state_new\v!start - {#2\plustwo}% - {#2\zerocount}% + #2\ifx\m_strc_pagenumbers_state_new\v!start\plustwo\else\zerocount\fi \fi} + \appendtoks % todo: set state: none, start, stop, reset \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage \to \everysetuprealpagenumber diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua index f20d931619b..e01bacaac32 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.lua @@ -52,6 +52,8 @@ local context = context local commands = commands local implement = interfaces.implement +local ctx_latelua = context.latelua + local texgetcount = tex.getcount local texsetcount = tex.setcount local texconditionals = tex.conditionals @@ -72,6 +74,7 @@ local lists = structures.lists local counters = structures.counters local jobpositions = job.positions +local getpos = jobpositions.getpos -- some might become local @@ -137,6 +140,7 @@ storage.register("structures/references/defined", references.defined, "structure local initializers = { } local finalizers = { } +local somefound = false -- so we don't report missing when we have a fresh start function references.registerinitializer(func) -- we could use a token register instead initializers[#initializers+1] = func @@ -162,6 +166,7 @@ local function initializer() -- can we use a tobesaved as metatable for collecte end end end + somefound = next(collected) end local function finalizer() @@ -370,6 +375,8 @@ implement { arguments = "2 strings", } +local reported = setmetatableindex("table") + function references.set(data) local references = data.references local reference = references.reference @@ -388,16 +395,23 @@ function references.set(data) if ref == "" then -- skip elseif check_duplicates and pd[ref] then - if prefix and prefix ~= "" then - report_references("redundant reference %a in namespace %a",ref,prefix) - else - report_references("redundant reference %a",ref) + if not prefix then + prefix = "" + end + if not reported[prefix][ref] then + if prefix ~= "" then + report_references("redundant reference %a in namespace %a",ref,prefix) + else + report_references("redundant reference %a",ref) + end + reported[prefix][ref] = true end else n = n + 1 pd[ref] = data local r = data.references ctx_dofinishreference(prefix or "",ref or "",r and r.internal or 0) + -- ctx_latelua(function() structures.references.enhance(prefix or ref,ref or "") end) end end process_settings(reference,action) @@ -411,8 +425,6 @@ end -- end -- end -local getpos = function() getpos = backends.codeinjections.getpos return getpos () end - local function synchronizepage(reference) -- non public helper reference.realpage = texgetcount("realpageno") if jobpositions.used then @@ -422,17 +434,30 @@ end references.synchronizepage = synchronizepage -function references.enhance(prefix,tag) - local l = tobesaved[prefix][tag] +local function enhancereference(specification) + local l = tobesaved[specification.prefix][specification.tag] if l then synchronizepage(l.references) end end +references.enhance = enhancereference + +-- implement { +-- name = "enhancereference", +-- arguments = "2 strings", +-- actions = function(prefix,tag) +-- enhancereference { prefix = prefix, tag = tag } +-- end, +-- } + implement { - name = "enhancereference", - actions = references.enhance, + name = "deferredenhancereference", arguments = "2 strings", + protected = true, + actions = function(prefix,tag) + ctx_latelua { action = enhancereference, prefix = prefix, tag = tag } + end, } -- -- -- related to strc-ini.lua -- -- -- @@ -1004,9 +1029,9 @@ local function loadexternalreferences(name,utilitydata) local pages = struc.pages.collected -- pagenumber data -- a bit weird one, as we don't have the externals in the collected for prefix, set in next, external do -if prefix == "" then - prefix = name -- this can clash! -end + if prefix == "" then + prefix = name -- this can clash! + end for reference, data in next, set do if trace_importing then report_importing("registering %a reference, kind %a, name %a, prefix %a, reference %a", @@ -1034,9 +1059,9 @@ end if kind and realpage then references.pagedata = pages[realpage] local prefix = references.prefix or "" -if prefix == "" then - prefix = name -- this can clash! -end + if prefix == "" then + prefix = name -- this can clash! + end local target = external[prefix] if not target then target = { } @@ -1468,7 +1493,7 @@ local function identify_inner(set,var,prefix,collected,derived) end end -- we now ignore the split prefix and treat the whole inner as a potential - -- referenice into the global list + -- reference into the global list local i = collected[prefix] if i then i = i[inner] @@ -1524,6 +1549,17 @@ local function identify_outer(set,var,i) end return v end +-- weird too (we really need to check how this table is build + local v = identify_inner(set,var,var.outer,external) + if v then + v.kind = "outer with inner" + set.external = true + if trace_identifying then + report_identify_outer(set,v,i,"2c") + end + return v + end +-- -- somewhat rubish: we use outer as first step in the externals table so it makes no -- sense to have it as prefix so the next could be an option local external = external[""] @@ -1798,8 +1834,7 @@ local nofidentified = 0 local function identify(prefix,reference) if not reference then - prefix = "" - reference = prefix + prefix, reference = "", prefix end local set = resolve(prefix,reference) local bug = false @@ -1847,7 +1882,9 @@ function references.valid(prefix,reference,specification) local str = f_valid(prefix,reference) local u = unknowns[str] if not u then - interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal + if somefound then + interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal + end unknowns[str] = 1 nofunknowns = nofunknowns + 1 else @@ -1964,13 +2001,14 @@ local function setinternalreference(specification) local internal = specification.internal local destination = unsetvalue if innermethod == v_auto or innermethod == v_name then - local t, tn = { }, 0 -- maybe add to current (now only used for tracing) + local t = { } -- maybe add to current (now only used for tracing) + local tn = 0 local reference = specification.reference local view = specification.view if reference then local prefix = specification.prefix if prefix and prefix ~= "" then - prefix = prefix .. ":" -- watch out, : here + local prefix = prefix .. ":" -- watch out, : here local function action(ref) tn = tn + 1 t[tn] = prefix .. ref @@ -1987,7 +2025,7 @@ local function setinternalreference(specification) -- ugly .. later we decide to ignore it when we have a real one -- but for testing we might want to see them all if internal then - if innermethod ~= v_name then -- so page and auto + if innermethod ~= v_name then -- innermethod == v_auto -- we don't want too many #1 #2 #3 etc tn = tn + 1 t[tn] = internal -- when number it's internal @@ -2064,7 +2102,7 @@ function references.setandgetattribute(data) -- maybe do internal automatically local done = references.set(data) -- we had kind i.e .item -> full if done then attr = setinternalreference { - prefix = prefix, + prefix = rdat.prefix, reference = rdat.reference, internal = rdat.internal, view = rdat.view @@ -2285,7 +2323,8 @@ genericfilters.default = genericfilters.text function genericfilters.page(data,prefixspec,pagespec) local pagedata = data.pagedata if pagedata then - local number, conversion = pagedata.number, pagedata.conversion + local number = pagedata.number + local conversion = pagedata.conversion if not number then -- error elseif conversion then @@ -2527,10 +2566,19 @@ local function referencepagestate(position,detail,spread) if not actions then return 0 else - if not actions.pagestate then + local pagestate = actions.pagestate + for i=1,#actions do + local a = actions[i] + if a.outer then + pagestate = 0 + actions.pagestate = pagestate + break + end + end + if not pagestate then references.analyze(actions,position,spread) -- delayed unless explicitly asked for + pagestate = actions.pagestate end - local pagestate = actions.pagestate if detail then return pagestate elseif pagestate == 4 then diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi index d0752407c90..c7f20481592 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ref.mkvi @@ -29,7 +29,7 @@ \registerctxluafile{strc-rsc}{} \registerctxluafile{strc-ref}{} -\registerctxluafile{node-ref}{} +\registerctxluafile{node-ref}{optimize} \unprotect @@ -45,19 +45,18 @@ % \definespecial\dosetexecuteJScode % ... -%D This module deals with referencing. In \CONTEXT\ referencing is one of -%D the core features, although at a first glance probably nobody will -%D notice. This is good, because referencing should be as hidden as possible. +%D This module deals with referencing. In \CONTEXT\ referencing is one of the core +%D features, although at a first glance probably nobody will notice. This is good, +%D because referencing should be as hidden as possible. %D -%D Before we start implementing functionality we provide a way to set -%D up this mechanism. +%D Before we start implementing functionality we provide a way to set up this +%D mechanism. %D %D \showsetup{setupreferencing} %D -%D In interactive documents verbose references don't always -%D make sense (what is a page number in an unnumbered -%D document). By setting the \type{interaction} variable, one -%D can influences the way interactive references are set. +%D In interactive documents verbose references don't always make sense (what is a +%D page number in an unnumbered document). By setting the \type{interaction} +%D variable, one can influences the way interactive references are set. \let\referenceprefix\empty @@ -122,20 +121,19 @@ \dosetdirectpagereference\m_strc_references_asked \fi} -%D Actually there is not much difference between a text and a -%D full reference, but it's the concept that counts. The low -%D level implementation is: +%D Actually there is not much difference between a text and a full reference, but +%D it's the concept that counts. The low level implementation is: \newcount\lastreferenceattribute \newcount\lastdestinationattribute \def\strc_references_finish#prefix#reference#internal% - {\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#reference")}}} + {\normalexpanded{\clf_deferredenhancereference{#prefix}{#reference}}} \let\dofinishreference\strc_references_finish % used at lua end -% This is somewhat tricky: we want to keep the reference with the following word but -% that word should also hyphenate. We need to find a better way. +%D This is somewhat tricky: we want to keep the reference with the following word but +%D that word should also hyphenate. We need to find a better way. % 0 = nothing % 1 = bind to following word @@ -167,6 +165,32 @@ \unhbox\b_strc_destination_nodes \fi} +\def\strc_references_placeholder + {\ifx\dotaggedplaceholder\empty\else + \attribute\destinationattribute\lastdestinationattribute + \dotaggedplaceholder + \fi} + +\unexpanded\def\strc_references_destination_point_yes + {\strc_references_inject_before % new + \dostarttagged\t!reference\empty + \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup + \strc_references_flush_destination_nodes + \strc_references_placeholder + \egroup + \dostoptagged + \strc_references_inject_after} + +\unexpanded\def\strc_references_destination_point_nop + {\strc_references_inject_before % new + \dostarttagged\t!reference\empty + \dontleavehmode\hbox \bgroup + \strc_references_flush_destination_nodes + \strc_references_placeholder + \egroup + \dostoptagged + \strc_references_inject_after} + \unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute @@ -188,14 +212,14 @@ \xmlstartraw \xdef\currentreferencedata{#text}% data, no text else conflict \xmlstopraw - \globallet\currentreferencecoding\s!xml + \glet\currentreferencecoding\s!xml \else \ifx\currentreferenceexpansion\v!yes \xdef\currentreferencedata{#text}% \else \xdef\currentreferencedata{\detokenize{#text}}% \fi - \globallet\currentreferencecoding\s!tex + \glet\currentreferencecoding\s!tex \fi % beware, the structures.references.set writes a \setnextinternalreference @@ -240,17 +264,9 @@ \xdef\currentdestinationattribute{\number\lastdestinationattribute}% % will become an option: \ifnum\lastdestinationattribute>\zerocount - \strc_references_inject_before % new - \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup - \strc_references_flush_destination_nodes - \egroup - \strc_references_inject_after % new + \strc_references_destination_point_yes \else\ifvoid\b_strc_destination_nodes\else - \strc_references_inject_before % new - \dontleavehmode\hbox \bgroup - \strc_references_flush_destination_nodes - \egroup - \strc_references_inject_after % new + \strc_references_destination_point_nop \fi\fi} \def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable @@ -324,17 +340,9 @@ \xdef\currentdestinationattribute{\number\lastdestinationattribute}% % will become an option: \ifnum\lastdestinationattribute>\zerocount - \strc_references_inject_before % new - \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup - \strc_references_flush_destination_nodes - \egroup - \strc_references_inject_after % new + \strc_references_destination_point_yes \else\ifvoid\b_strc_destination_nodes\else - \strc_references_inject_before % new - \dontleavehmode\hbox \bgroup - \strc_references_flush_destination_nodes - \egroup - \strc_references_inject_after % new + \strc_references_destination_point_nop \fi\fi} \unexpanded\def\strc_references_direct_full @@ -479,10 +487,10 @@ {\scratchwidth \wd\nextbox \scratchheight\ht\nextbox \scratchdepth \dp\nextbox - \setbox\nextbox\hbox % \hpack ? + \setbox\nextbox\hpack {\framed[\c!frame=\v!off,#2]{\box\nextbox}}% \strc_references_set_simple_reference{#1}% - \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute % \hpack ? + \setbox\nextbox\hpack attr \destinationattribute \currentdestinationattribute % \hpack ? {\strc_references_flush_destination_nodes \box\nextbox}% \setbox\nextbox\hpack{\box\nextbox}% @@ -494,7 +502,7 @@ \def\strc_references_content_nop_finish#1#2% {\strc_references_set_simple_reference{#1}% - \hbox attr \destinationattribute \currentdestinationattribute % \hpack ? + \hpack attr \destinationattribute \currentdestinationattribute % \hpack ? {\strc_references_flush_destination_nodes \box\nextbox}% \egroup} @@ -502,34 +510,31 @@ %D \macros %D {everyreference} %D -%D For rather tricky purposes, one can assign sanitizing -%D macros to \type{\everyreference} (no longer that relevant). +%D For rather tricky purposes, one can assign sanitizing macros to \type +%D {\everyreference} (no longer that relevant). \newevery \everyreference \relax -%D This is really needed, since for instance Polish has a -%D different alphabet and needs accented entries in registers. +%D This is really needed, since for instance Polish has a different alphabet and +%D needs accented entries in registers. \appendtoks \cleanupfeatures \to \everyreference -%D We did not yet discuss prefixing. Especially in interactive -%D documents, it's not always easy to keep track of duplicate -%D references. The prefix mechanism, which we will describe -%D later on, solves this problem. By (automatically) adding a -%D prefix one keeps references local, but the global ones in -%D view. To enable this feature, we explictly split the prefix -%D from the reference. +%D We did not yet discuss prefixing. Especially in interactive documents, it's not +%D always easy to keep track of duplicate references. The prefix mechanism, which we +%D will describe later on, solves this problem. By (automatically) adding a prefix +%D one keeps references local, but the global ones in view. To enable this feature, +%D we explictly split the prefix from the reference. \let\referenceprefix\empty -%D For a long time the only way to access an external file was -%D to use the file prefix (\type {somefile::}. However, when -%D you split up a document, redefining the references may be -%D such a pain, that another approach is feasible. By setting -%D the \type {autofile} variable to \type {yes} or \type -%D {page}, you can access the reference directly. +%D For a long time the only way to access an external file was to use the file +%D prefix (\type {somefile::}. However, when you split up a document, redefining the +%D references may be such a pain, that another approach is feasible. By setting the +%D \type {autofile} variable to \type {yes} or \type {page}, you can access the +%D reference directly. %D %D \starttabulate[||||] %D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR @@ -540,9 +545,9 @@ \unexpanded\def\usereferences[#filename]{} % obsolete -%D As mentioned we will also use the cross reference mechanism -%D for navigational purposes. The main reason for this is that -%D we want to treat both categories alike: +%D As mentioned we will also use the cross reference mechanism for navigational +%D purposes. The main reason for this is that we want to treat both categories +%D alike: %D %D \starttyping %D \goto{go back}[PreviousJump] @@ -553,15 +558,13 @@ %D \type{colofon page} reference is, apart from hyperlinking, a %D rather normal reference. %D -%D We already saw that cross refences are written to and read -%D from a file. The pure navigational ones don't need to be -%D written to file, but both for fast processing and -%D transparant integration, they are saved internally as a sort -%D of reference. We can easily distinguish such system -%D references from real cross reference ones by their tag. +%D We already saw that cross refences are written to and read from a file. The pure +%D navigational ones don't need to be written to file, but both for fast processing +%D and transparant integration, they are saved internally as a sort of reference. We +%D can easily distinguish such system references from real cross reference ones by +%D their tag. %D -%D We also use the odd/even characteristic to determine the -%D page state. +%D We also use the odd/even characteristic to determine the page state. \let\currentrealreference \empty \let\currentpagereference \empty @@ -576,11 +579,10 @@ % % 0 = no page ref, 1=same page, 2=before, 3=after -%D Cross references appear as numbers (figure~1.1, chapter~2) -%D or pagenumbers (page~2, page 3--2), and are called with -%D \type{\in} and \type{\at}. In interactive documents we also -%D have \type{\goto}, \type{\button} and alike. These are more -%D versatile and look like: +%D Cross references appear as numbers (figure~1.1, chapter~2) or pagenumbers +%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In +%D interactive documents we also have \type {\goto}, \type {\button} and alike. +%D These are more versatile and look like: %D %D \starttyping %D \goto[reference] @@ -592,23 +594,19 @@ %D \goto[action{argument}] %D \stoptyping %D -%D The first one is a normal reference, the second and third -%D are references to a file or \URL. The brace delimited -%D references for instance refer to a \JAVASCRIPT. The last -%D example shows that we can pass arguments to the actions. +%D The first one is a normal reference, the second and third are references to a +%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT. +%D The last example shows that we can pass arguments to the actions. %D -%D Now we've come to the testing step. As we can see below, -%D this macro does bit more than testing: it also resolves -%D the reference. This means that whenever we test for the -%D existance of a reference at an outer level, we have all the -%D relevant properties of that reference avaliable inside the -%D true branche~(\type{#2}). +%D Now we've come to the testing step. As we can see below, this macro does bit more +%D than testing: it also resolves the reference. This means that whenever we test +%D for the existance of a reference at an outer level, we have all the relevant +%D properties of that reference avaliable inside the true branche~(\type {#2}). %D -%D The prefix has to do with localizing references. When a -%D prefix is set, looking for a reference comes to looking for -%D the prefixed one, and when not found, looking for the non -%D prefixed one. Consider for instance the prefix set to -%D \type{sidetrack}. +%D The prefix has to do with localizing references. When a prefix is set, looking +%D for a reference comes to looking for the prefixed one, and when not found, +%D looking for the non prefixed one. Consider for instance the prefix set to \type +%D {sidetrack}. %D %D \starttyping %D \pagereference[important] @@ -625,17 +623,15 @@ %D ...{sidetrack}{important}... %D \stoptyping %D -%D Now when we call for \type{unimportant}, we will indeed get -%D the pagenumber associated to this reference. But when we -%D call for \type{important}, while the prefix is still set, we -%D will get the pagenumber bound to the prefixed one. +%D Now when we call for \type{unimportant}, we will indeed get the pagenumber +%D associated to this reference. But when we call for \type{important}, while the +%D prefix is still set, we will get the pagenumber bound to the prefixed one. %D %D {\em Some day, when processing time and memory are no longer %D performance factors, we will introduce multi||level %D prefixes.} %D -%D Before we start analyzing, I introduce a general -%D definition macro. Consider: +%D Before we start analyzing, I introduce a general definition macro. Consider: %D %D \starttyping %D \goto{do}[JS(My_Script{"test",123}),titlepage] @@ -652,8 +648,7 @@ %D %D \showsetup{definereference} %D -%D We can trace references by setting the next switch to -%D true. +%D We can trace references by setting the next switch to true. \unexpanded\def\definereference {\dodoubleempty\strc_references_define_reference} @@ -673,23 +668,22 @@ %D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)] %D \stoptyping %D -%D Actually supporting chains is up to the special driver. Here -%D we only provide the hooks. +%D Actually supporting chains is up to the special driver. Here we only provide the +%D hooks. %D \macros %D {highlighthyperlinks} %D -%D The next switch can be used to make user hyperlinks are -%D not highlighted when clicked on. +%D The next switch can be used to make user hyperlinks are not highlighted when +%D clicked on. \newconditional\highlighthyperlinks \settrue\highlighthyperlinks %D \macros %D {gotonewwindow} %D -%D To make the {\em goto previous jump} feature more -%D convenient when using more than one file, it makes sense -%D to force the viewer to open a new window for each file +%D To make the {\em goto previous jump} feature more convenient when using more than +%D one file, it makes sense to force the viewer to open a new window for each file %D opened. \newconditional\gotonewwindow \setfalse\gotonewwindow @@ -708,13 +702,11 @@ \let\doifreferencefoundelse \doifelsereferencefound -%D The tester only splits the reference in components but does -%D not look into them. The following macro does a preroll and -%D determines for instance the current real reference pagenumber. -%D The \type {\currentrealreference} macro does the same so unless -%D one wants to use the pagestate the next macro seldom needs to -%D be called. - +%D The tester only splits the reference in components but does not look into them. +%D The following macro does a preroll and determines for instance the current real +%D reference pagenumber. The \type {\currentrealreference} macro does the same so +%D unless one wants to use the pagestate the next macro seldom needs to be called. +%D %D The inner case is simple. Only two cases have to be taken %D care of: %D @@ -723,8 +715,8 @@ %D \goto{some text}[prefix:reference] %D \stoptyping %D -%D References to other files however are treated strict or -%D tolerant, depending on their loading and availability: +%D References to other files however are treated strict or tolerant, depending on +%D their loading and availability: %D %D \starttyping %D \useexternaldocument[somefile][filename][a nice description] @@ -734,72 +726,61 @@ %D \goto{unchecked reference}[anotherfile::reference] %D \stoptyping %D -%D An unknown reference is reported on the screen, in the log -%D file and, when enabled, in the left margin of the text. +%D An unknown reference is reported on the screen, in the log file and, when +%D enabled, in the left margin of the text. \let\unknownreference\gobbleoneargument -%D When a reference is not found, we typeset a placeholder -%D (two glyphs are often enough to represent the reference -%D text). +%D When a reference is not found, we typeset a placeholder (two glyphs are often +%D enough to represent the reference text). \def\dummyreference{{\tttf ??}} \def\emptyreference{{\tttf !!}} -%D To prevent repetitive messages concerning a reference -%D being defined, we set such an unknown reference to an empty -%D one after the first encounter. - -%D Apart from cross references supplied by the user, \CONTEXT\ -%D generates cross references itself. Most of them are not -%D saved as a reference, but stored with their source, for -%D instance a list or an index entry. Such automatically -%D generated, for the user invisible, references are called -%D {\em internal references}. The user supplied ones are -%D labeled as {\em external references}. -%D -%D A second important characteristic is that when we want to -%D support different backends (viewers), we need to support -%D named destinations as well as page numbers. I invite readers -%D to take a glance at the special driver modules to understand -%D the fine points of this. As a result we will deal with {\em -%D locations} as well as {\em real page numbers}. We explictly -%D call this pagenumber a real one, because it is independant -%D of the page numbering scheme used in the document. -%D -%D One of the reasons for \CONTEXT\ being the first \TEX\ base -%D macropackage to support sophisticated interactive \PDF\ -%D files, lays in the mere fact that real page numbers are -%D available in most two pass data, like references, list data -%D and index entries. -%D -%D We will speak of \type{thisis...} when we are marking a -%D location, and \type{goto...} when we point to such a -%D location. The latter one can be seen as a hyperlink to the -%D former one. In the next macros one we use constructs like: +%D To prevent repetitive messages concerning a reference being defined, we set such +%D an unknown reference to an empty one after the first encounter. +%D +%D Apart from cross references supplied by the user, \CONTEXT\ generates cross +%D references itself. Most of them are not saved as a reference, but stored with +%D their source, for instance a list or an index entry. Such automatically +%D generated, for the user invisible, references are called {\em internal +%D references}. The user supplied ones are labeled as {\em external references}. +%D +%D A second important characteristic is that when we want to support different +%D backends (viewers), we need to support named destinations as well as page +%D numbers. I invite readers to take a glance at the special driver modules to +%D understand the fine points of this. As a result we will deal with {\em locations} +%D as well as {\em real page numbers}. We explictly call this pagenumber a real one, +%D because it is independant of the page numbering scheme used in the document. +%D +%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to +%D support sophisticated interactive \PDF\ files, lays in the mere fact that real +%D page numbers are available in most two pass data, like references, list data and +%D index entries. +%D +%D We will speak of \type {thisis...} when we are marking a location, and +%D \type {goto...} when we point to such a location. The latter one can be seen as a +%D hyperlink to the former one. In the next macros one we use constructs like: %D %D \starttyping %D \dostart... %D \dostop... %D \stoptyping %D -%D Such macros are used to invoke the relevant specials from -%D the special driver modules (see \type{spec-ini}). The flag -%D \type{\iflocation} signals if we're in interactive mode. +%D The flag \type {\iflocation} signals if we're in interactive mode. \ifdefined\buttonheight \else \newdimen\buttonheight \fi \ifdefined\buttonwidth \else \newdimen\buttonwidth \fi -%D Internal references can best be set using the next few -%D macros. Setting such references to unique values is -%D completely up to the macros that call them. +%D Internal references can best be set using the next few macros. Setting such +%D references to unique values is completely up to the macros that call them. %D %D \starttyping %D \thisissomeinternal{tag}{identifier} %D \gotosomeinternal {tag}{identifier}{pagenumber}{text} %D \stoptyping - -%D We could do this in lua ... +%D +%D We could do this in \LUA\ \unknown \newif \iflocation \newcount\locationcount @@ -823,7 +804,7 @@ \clf_setinternalreference reference {#kind:#name}% no view \relax - \hbox attr \destinationattribute\lastdestinationattribute{}% + \hpack attr \destinationattribute\lastdestinationattribute{}% \endgroup} \installcorenamespace{savedinternalreference} @@ -845,12 +826,10 @@ \def\gotonextinternal#text#target% {\directgoto{#text}[internal(#target)]} -%D In this module we define three system references: one for -%D handling navigational, viewer specific, commands, another -%D for jumping to special pages, like the first or last one, -%D and a third reference for linking tree like lists, like -%D tables of contents. The latter two adapt themselves to the -%D current state. +%D In this module we define three system references: one for handling navigational, +%D viewer specific, commands, another for jumping to special pages, like the first +%D or last one, and a third reference for linking tree like lists, like tables of +%D contents. The latter two adapt themselves to the current state. %D %D An example of an action is: %D @@ -863,11 +842,10 @@ %D \starttyping %D \goto{some text}[\v!action(PreviousJump] %D \stoptyping - -%D One can also activate an automatic prefix mechanism. By -%D setting the \type{\prefix} variable to \type{+}, the prefix -%D is incremented, when set to \type{-} or empty, the prefix is -%D reset. Other values become the prefix. +%D +%D One can also activate an automatic prefix mechanism. By setting the +%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to +%D \type {-} or empty, the prefix is reset. Other values become the prefix. \newcount\prefixcounter @@ -892,13 +870,6 @@ \unexpanded\def\setupglobalreferenceprefix[#prefix]% {\xdef\referenceprefix{#prefix}} -% \unexpanded\def\pushreferenceprefix#prefix% -% {\pushmacro\referenceprefix -% \xdef\referenceprefix{#prefix}} % global - -% \unexpanded\def\popreferenceprefix -% {\popmacro\referenceprefix} - \unexpanded\def\globalpushreferenceprefix#prefix% {\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}} @@ -935,16 +906,14 @@ \setupreferenceprefix[\referencingparameter\c!prefix] \to \everysetupreferencing -%D We can typeset a reference using \type{\in}, \type{\at} and -%D \type{\about} and goto specific locations using -%D \type{\goto}. The last one does not make that much sense in -%D a paper document. To complicate things, \PLAIN\ \TEX\ also -%D implements an \type {\in} but fortunately that one only -%D makes sense in math mode. +%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and +%D goto specific locations using \type {\goto}. The last one does not make that much +%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an +%D \type {\in} but fortunately that one only makes sense in math mode. %D -%D Typesetting the reference is a bit more complicated than one -%D would at first sight expect. This is due to the fact that we -%D distinguish three (five) alternative calls: +%D Typesetting the reference is a bit more complicated than one would at first sight +%D expect. This is due to the fact that we distinguish three (five) alternative +%D calls: %D %D \placefigure %D [here][three calls] @@ -971,25 +940,11 @@ %D \getbuffer %D \stoplines %D -%D The dual \type{{}} results in a split reference. In a -%D document meant for paper, one is tempted to use the last -%D (most straightforward) alternative. When a document is also -%D meant voor electronic distribution, the former alternatives -%D have preference, because everything between the \type{\in} -%D and~\type{[} becomes active (and when asked for, typeset -%D in a different color and typeface). - -% \unexpanded\def\in {\mathortext\donormalmathin \strc_references_in} -% \unexpanded\def\at {\mathortext\donormalmathat \strc_references_at} -% \unexpanded\def\about{\mathortext\donormalmathabout\strc_references_about} -% \unexpanded\def\from {\mathortext\donormalmathfrom \strc_references_from} -% \unexpanded\def\over {\mathortext\donormalmathover \strc_references_about} - -% \definecommand in {\strc_references_in} -% \definecommand at {\strc_references_at} -% \definecommand about {\strc_references_about} -% \definecommand from {\strc_references_from} -% \definecommand over {\strc_references_about} % needed here, else math problems +%D The dual \type {{}} results in a split reference. In a document meant for paper, +%D one is tempted to use the last (most straightforward) alternative. When a +%D document is also meant voor electronic distribution, the former alternatives have +%D preference, because everything between the \type {\in} and~\type {[} becomes +%D active (and when asked for, typeset in a different color and typeface). \appendtoks \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi @@ -1009,8 +964,7 @@ \def\currentreferencedefault {\clf_filterreference{default}} \def\currentreferencerealpage{\clf_filterreference{realpage}} -%D The most straightforward way of retrieving references is -%D using \type{\ref}. +%D The most straightforward way of retrieving references is using \type {\ref}. \unexpanded\def\getreference % checking, unexpanded {\dodoubleargument\strc_references_get_reference} @@ -1040,12 +994,11 @@ \referencingparameter\c!right \endgroup} -%D The previously discussed setup macro lets us specify the -%D representation of references. A symbol reference does not -%D show the specific data, like the number of a figure, but -%D shows one of: \hbox {$^\goforwardcharacter$ -%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending -%D on the direction to go. +%D The previously discussed setup macro lets us specify the representation of +%D references. A symbol reference does not show the specific data, like the number +%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$ +%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to +%D go. %D %D \starttyping %D ... \somewhere{backward text}{forward text}[someref] ... @@ -1141,7 +1094,7 @@ \expandafter\sixthofsixarguments \fi} \unexpanded\def\referencesymbol - {\hbox\bgroup + {\hpack\bgroup \strut \markreferencepage \high @@ -1210,17 +1163,23 @@ \newtoks\defaultleftreferencetoks \newtoks\defaultrightreferencetoks -\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this +%def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this \let\rightofreferencecontent \empty \let\leftofreference \empty \let\rightofreference \empty +\unexpanded\def\leftofreferencecontent + {\removeunwantedspaces + \nonbreakablespace + \ignorespaces} + \installcorenamespace{referencinginteraction} \def\strc_references_interaction_all {\the\leftreferencetoks \doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing \leftofreference + \doifelsesometoks\leftreferencetoks\onlynonbreakablespace\relax % new, replace space by nonbreakable if present \currentreferencecontent \rightofreference \doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing @@ -1242,15 +1201,6 @@ \setvalue{\??referencinginteraction\v!symbol}% {\referencesymbol} -% \def\referencesequence -% {\csname\??referencinginteraction -% \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname -% \referencingparameter\c!interaction -% \else -% \v!all -% \fi -% \endcsname} - \def\referencesequence {\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname \expandafter\lastnamedcs @@ -1311,9 +1261,8 @@ %D \macros %D {definereferenceformat} %D -%D The next few macros were made for for David Arnold and Taco -%D Hoekwater. They can be used for predefining reference -%D texts, and thereby stimulate efficiency. +%D The next few macros were made for for David Arnold and Taco Hoekwater. They can +%D be used for predefining reference texts, and thereby stimulate efficiency. %D %D \starttyping %D \definereferenceformat[informula] [left=(,right=),text=formula] @@ -1328,11 +1277,11 @@ %D the \informulas [b] \andformula [for:c] %D \stoptyping %D -%D Instead of a text, one can specify a label, which should -%D be defined with \type {\setuplabeltext}. +%D Instead of a text, one can specify a label, which should be defined with \type +%D {\setuplabeltext}. %D -%D Watch out: the second argument is somewhat special and mostly -%D meant for a suffix to a number: +%D Watch out: the second argument is somewhat special and mostly meant for a suffix +%D to a number: %D %D \startbuffer %D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] @@ -1437,21 +1386,18 @@ % % \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext] -%D In interactive documents going to a specific location is not -%D bound to cross references. The \type{\goto} commands can be -%D used to let users access another part of the document. In -%D this respect, interactive tables of contents and registers -%D can be considered goto's. Because in fact a \type{\goto} is -%D just a reference without reference specific data, the -%D previous macros are implemented using the goto -%D functionality. +%D In interactive documents going to a specific location is not bound to cross +%D references. The \type {\goto} commands can be used to let users access another +%D part of the document. In this respect, interactive tables of contents and +%D registers can be considered goto's. Because in fact a \type {\goto} is just a +%D reference without reference specific data, the previous macros are implemented +%D using the goto functionality. %D %D \showsetup{goto} %D -%D One important characteristic is that the first argument of -%D \type{\goto} (and therefore \type{\at} and \type{\in} is -%D split at spaces. This means that, although hyphenation is -%D prevented, long references can cross line endings. +%D One important characteristic is that the first argument of \type {\goto} (and +%D therefore \type {\at} and \type {\in} is split at spaces. This means that, +%D although hyphenation is prevented, long references can cross line endings. % \starttext % \setupinteraction[state=start] @@ -1740,21 +1686,19 @@ \clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}% {\clf_injectcurrentreference \global\lastsavedreferenceattribute\lastreferenceattribute - \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} + \hpack attr \referenceattribute \lastreferenceattribute {\box\scratchbox}} {\box\scratchbox}% \endgroup} -%D An reference to another document can be specified as a file -%D or as an \URL. Both are handled by the same mechanism and -%D can be issued by saying something like: +%D An reference to another document can be specified as a file or as an \URL. Both +%D are handled by the same mechanism and can be issued by saying something like: %D %D \starttyping %D \goto[dictionary::the letter a] %D \stoptyping %D -%D One can imagine that many references to such a dictionary -%D are made, so in most cases such a document reference in an -%D indirect one. +%D One can imagine that many references to such a dictionary are made, so in most +%D cases such a document reference in an indirect one. %D %D \showsetup{useexternaldocument} %D @@ -1766,8 +1710,8 @@ %D [The Famous English Dictionary] %D \stoptyping %D -%D The next macro implements these relations, and also take -%D care of loading the document specific references. +%D The next macro implements these relations, and also take care of loading the +%D document specific references. %D %D The \URL\ alternative takes four arguments: %D @@ -1789,9 +1733,8 @@ %D \useURL [id] [url] %D \stoptyping %D -%D This time we don't load the references when no file is -%D specified. This is logical when one keeps in mind that a -%D valid \URL\ can also be a mail address. +%D This time we don't load the references when no file is specified. This is logical +%D when one keeps in mind that a valid \URL\ can also be a mail address. \unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments \unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments @@ -1814,8 +1757,7 @@ %D \macros %D {url,setupurl} %D -%D We also have: \type{\url} for directly calling the -%D description. So we can say: +%D We also have: \type {\url} for directly calling the description. So we can say: %D %D \starttyping %D \useURL [one] [http://www.test.nl] @@ -1843,8 +1785,8 @@ \hyphenatedurl{\clf_geturl{#label}}% \endgroup} -%D This macro is hooked into a support macro, and thereby -%D \URL's break ok, according to the setting of a switch, +%D This macro is hooked into a support macro, and thereby \URL's break ok, according +%D to the setting of a switch, %D %D \startbuffer %D \useURL @@ -1858,9 +1800,8 @@ %D %D \getbuffer -%D When defining the external source of information, one can -%D also specify a suitable name (the last argument). This name -%D can be called upon with: +%D When defining the external source of information, one can also specify a suitable +%D name (the last argument). This name can be called upon with: %D %D \showsetup{from} %D @@ -1895,9 +1836,8 @@ %D \goto{some text}[identifier::location] %D \stoptyping -%D A special case of references are those to programs. These, -%D very system dependant references are implemented by abusing -%D some of the previous macros. +%D A special case of references are those to programs. These, very system dependant +%D references are implemented by abusing some of the previous macros. %D %D \showsetup{setupprograms} %D \showsetup{defineprogram} @@ -1918,15 +1858,14 @@ \def\strc_references_define_program[#name][#program][#description]% {\clf_defineprogram{#name}{#program}{#description}} -\def\program[#name]% incompatible, more consistent, hardy used anyway +\unexpanded\def\program[#name]% incompatible, more consistent, hardy used anyway {\dontleavehmode \begingroup \useprogramsstyleandcolor\c!style\c!color \clf_getprogram{#name}% \endgroup} -%D As we can see, we directly use the special reference -%D mechanism, which means that +%D As we can see, we directly use the special reference mechanism, which means that %D %D \starttyping %D \goto{some text}[program(name{args})] @@ -1934,11 +1873,10 @@ %D %D is valid. -%D The next macro provides access to the actual pagenumbers. -%D When documenting and sanitizing the original reference -%D macros, I decided to keep the present meaning as well as to -%D make this meaning available as a special reference method. -%D So now one can use: +%D The next macro provides access to the actual pagenumbers. When documenting and +%D sanitizing the original reference macros, I decided to keep the present meaning +%D as well as to make this meaning available as a special reference method. So now +%D one can use: %D %D \starttyping %D \gotopage{some text}[location] @@ -1967,8 +1905,7 @@ \def\gotopage#text[#target]% {\goto{#text}[\v!page(#target)]} -%D The previous definitions are somewhat obsolete so we don't -%D use it here. +%D The previous definitions are somewhat obsolete so we don't use it here. %D We can cross link documents by using: %D @@ -1980,16 +1917,14 @@ %D \coupledocument[print][somefile][chapter,section] %D \stoptyping %D -%D After which when applicable, we have available the -%D references: +%D After which when applicable, we have available the references: %D %D \starttyping %D \goto{print version}[print::chapter] %D \stoptyping %D -%D and alike. The title placement definition macros have a -%D key \type{file}, which is interpreted as the file to jump -%D to, that is, when one clicks on the title. +%D and alike. The title placement definition macros have a key \type {file}, which +%D is interpreted as the file to jump to, that is, when one clicks on the title. \def\coupledocument {\doquadrupleempty\strc_references_couple_document} @@ -2002,8 +1937,8 @@ %D \macros %D {dotextprefix} %D -%D In previous macros we used \type {\dotextprefix} to -%D generate a space between a label and a number. +%D In previous macros we used \type {\dotextprefix} to generate a space between +%D a label and a number. %D %D \starttyping %D \dotextprefix{text} @@ -2026,9 +1961,8 @@ \fi \endgroup} -%D In the next settings we see some variables that were not -%D used here and that concern the way the pagenumbers refered -%D to are typeset. +%D In the next settings we see some variables that were not used here and that +%D concern the way the pagenumbers refered to are typeset. \setupreferencing [\c!state=\v!start, diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua index 2c667fba3cc..47ba1c5338b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.lua @@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['strc-reg'] = { } local next, type, tonumber = next, type, tonumber -local format, gmatch = string.format, string.gmatch +local char, format, gmatch = string.char, string.format, string.gmatch local equal, concat, remove = table.are_equal, table.concat, table.remove local lpegmatch, P, C, Ct = lpeg.match, lpeg.P, lpeg.C, lpeg.Ct local allocate = utilities.storage.allocate @@ -38,6 +38,7 @@ local texgetcount = tex.getcount local variables = interfaces.variables local v_forward = variables.forward local v_all = variables.all +local v_no = variables.no local v_yes = variables.yes local v_packed = variables.packed local v_current = variables.current @@ -47,7 +48,7 @@ local v_last = variables.last local v_text = variables.text local context = context -local commands = commands +local ctx_latelua = context.latelua local implement = interfaces.implement @@ -81,10 +82,12 @@ local ctx_startregisterpages = context.startregisterpages local ctx_stopregisterpages = context.stopregisterpages local ctx_startregisterseewords = context.startregisterseewords local ctx_stopregisterseewords = context.stopregisterseewords + local ctx_registerentry = context.registerentry local ctx_registerseeword = context.registerseeword local ctx_registerpagerange = context.registerpagerange local ctx_registeronepage = context.registeronepage + local ctx_registerpacked = context.registerpacked -- possible export, but ugly code (overloads) @@ -452,23 +455,6 @@ local tagged = { } local function preprocessentries(rawdata) local entries = rawdata.entries if entries then - -- - -- local e = entries[1] or "" - -- local k = entries[2] or "" - -- local et, kt, entryproc, pageproc - -- if type(e) == "table" then - -- et = e - -- else - -- entryproc, e = splitprocessor(e) - -- et = lpegmatch(entrysplitter,e) - -- end - -- if type(k) == "table" then - -- kt = k - -- else - -- pageproc, k = splitprocessor(k) - -- kt = lpegmatch(entrysplitter,k) - -- end - -- local processors = rawdata.processors local et = entries.entries local kt = entries.keys @@ -533,6 +519,7 @@ local function storeregister(rawdata) -- metadata, references, entries metadata.kind = "entry" end -- + -- if not metadata.catcodes then metadata.catcodes = tex.catcodetable -- get end @@ -581,17 +568,20 @@ local function storeregister(rawdata) -- metadata, references, entries return #entries end -registers.store = storeregister - -function registers.enhance(name,n) - local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name] +local function enhanceregister(specification) + local name = specification.name + local n = specification.n + local saved = tobesaved[name] + local data = saved.metadata.notsaved and collected[name] or saved local entry = data.entries[n] if entry then entry.references.realpage = texgetcount("realpageno") end end -function registers.extend(name,tag,rawdata) -- maybe do lastsection internally +-- This can become extendregister(specification)! + +local function extendregister(name,tag,rawdata) -- maybe do lastsection internally if type(tag) == "string" then tag = tagged[tag] end @@ -635,6 +625,10 @@ function registers.extend(name,tag,rawdata) -- maybe do lastsection internally end end +registers.store = storeregister +registers.enhance = enhanceregister +registers.extend = extendregister + function registers.get(tag,n) local list = tobesaved[tag] return list and list.entries[n] @@ -642,13 +636,24 @@ end implement { name = "enhanceregister", - actions = registers.enhance, arguments = { "string", "integer" }, + actions = function(name,n) + enhanceregister { name = name, n = n } -- todo: move to scanner + end, +} + +implement { + name = "deferredenhanceregister", + arguments = { "string", "integer" }, + protected = true, + actions = function(name,n) + ctx_latelua { action = enhanceregister, name = name, n = n } + end, } implement { name = "extendregister", - actions = registers.extend, + actions = extendregister, arguments = "2 strings", } @@ -714,7 +719,8 @@ function registers.compare(a,b) local ka = a.metadata.kind local kb = b.metadata.kind if ka == kb then - local page_a, page_b = a.references.realpage, b.references.realpage + local page_a = a.references.realpage + local page_b = b.references.realpage if not page_a or not page_b then return 0 elseif page_a < page_b then @@ -739,7 +745,7 @@ local seeindex = 0 -- meerdere loops, seewords, dan words, anders seewords -local function crosslinkseewords(result) -- all words +local function crosslinkseewords(result,check) -- all words -- collect all seewords local seewords = { } for i=1,#result do @@ -783,24 +789,17 @@ local function crosslinkseewords(result) -- all words local seeparent = seeparents[text] if seeparent then local seeindex = seewords[text] - local s, ns, d, w, l = { }, 0, data.split, seeparent.split, data.list - -- trick: we influence sorting by adding fake subentries - for i=1,#d do - ns = ns + 1 - s[ns] = d[i] -- parent - end - for i=1,#w do - ns = ns + 1 - s[ns] = w[i] -- see - end - data.split = s - -- we also register a fake extra list entry so that the - -- collapser works okay - l[#l+1] = { text, "" } data.references.seeindex = seeindex if trace_registers then report_registers("see crosslink %03i: %s",seeindex,text) end + seeword.valid = true + elseif check then + report_registers("invalid crosslink : %s, %s",text,"ignored") + seeword.valid = false + else + report_registers("invalid crosslink : %s, %s",text,"passed") + seeword.valid = true end end end @@ -824,17 +823,22 @@ local function removeemptyentries(result) end end -function registers.prepare(data) +function registers.prepare(data,options) -- data has 'list' table local strip = sorters.strip local splitter = sorters.splitters.utf local result = data.result if result then + local seeprefix = char(0) for i=1, #result do local entry = result[i] local split = { } local list = entry.list if list then + if entry.seeword then + -- we can have multiple seewords, only two levels supported + list[#list+1] = { seeprefix .. strip(entry.seeword.text) } + end for l=1,#list do local ll = list[l] local word = ll[1] @@ -848,7 +852,7 @@ function registers.prepare(data) entry.split = split end removeemptyentries(result) - crosslinkseewords(result) + crosslinkseewords(result,options.check ~= v_no) end end @@ -861,7 +865,9 @@ function registers.sort(data,options) end function registers.unique(data,options) - local result, nofresult, prev = { }, 0, nil + local result = { } + local nofresult = 0 + local prev = nil local dataresult = data.result for k=1,#dataresult do local v = dataresult[k] @@ -873,7 +879,8 @@ function registers.unique(data,options) elseif pr.realpage ~= vr.realpage then -- ok else - local pl, vl = pr.lastrealpage, vr.lastrealpage + local pl = pr.lastrealpage + local vl = vr.lastrealpage if pl or vl then if not vl then -- ok @@ -901,7 +908,11 @@ end function registers.finalize(data,options) -- maps character to index (order) local result = data.result data.metadata.nofsorted = #result - local split, nofsplit, lasttag, done, nofdone = { }, 0, nil, nil, 0 + local split = { } + local nofsplit = 0 + local lasttag = nil + local done = nil + local nofdone = 0 local firstofsplit = sorters.firstofsplit for k=1,#result do local v = result[k] @@ -922,8 +933,46 @@ function registers.finalize(data,options) -- maps character to index (order) data.result = split end +-- local function analyzeregister(class,options) +-- local data = collected[class] +-- if data and data.entries then +-- options = options or { } +-- sorters.setlanguage(options.language,options.method,options.numberorder) +-- registers.filter(data,options) -- filter entries into results (criteria) +-- registers.prepare(data,options) -- adds split table parallel to list table +-- registers.sort(data,options) -- sorts results +-- registers.unique(data,options) -- get rid of duplicates +-- registers.finalize(data,options) -- split result in ranges +-- data.metadata.sorted = true +-- return data.metadata.nofsorted or 0 +-- else +-- return 0 +-- end +-- end + local function analyzeregister(class,options) - local data = collected[class] + local data = rawget(collected,class) + if not data then + local list = utilities.parsers.settings_to_array(class) + local entries = { } + local metadata = false + for i=1,#list do + local l = list[i] + local d = collected[l] + local e = d.entries + for i=1,#e do + entries[#entries+1] = e[i] + end + if not metadata then + metadata = d.metadata + end + end + data = { + metadata = metadata or { }, + entries = entries, + } + collected[class] = data + end if data and data.entries then options = options or { } sorters.setlanguage(options.language,options.method,options.numberorder) @@ -973,8 +1022,10 @@ implement { -- todo: ownnumber local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec) - local fer, ter = f_entry.references, t_entry.references + local fer = f_entry.references + local ter = t_entry.references ctx_registerpagerange( + f_entry.metadata.name or "", f_entry.processors and f_entry.processors[2] or "", fer.internal or 0, fer.realpage or 0, @@ -996,6 +1047,7 @@ end local function pagenumber(entry,prefixspec,pagespec) local er = entry.references ctx_registeronepage( + entry.metadata.name or "", entry.processors and entry.processors[2] or "", er.internal or 0, er.realpage or 0, @@ -1004,7 +1056,8 @@ local function pagenumber(entry,prefixspec,pagespec) end local function packed(f_entry,t_entry) - local fer, ter = f_entry.references, t_entry.references + local fer = f_entry.references + local ter = t_entry.references ctx_registerpacked( fer.internal or 0, ter.internal or 0 @@ -1013,8 +1066,12 @@ end local function collapsedpage(pages) for i=2,#pages do - local first, second = pages[i-1], pages[i] - local first_first, first_last, second_first, second_last = first[1], first[2], second[1], second[2] + local first = pages[i-1] + local second = pages[i] + local first_first = first[1] + local first_last = first[2] + local second_first = second[1] + local second_last = second[2] local first_last_pn = first_last .references.realpage local second_first_pn = second_first.references.realpage local second_last_pn = second_last .references.realpage @@ -1110,7 +1167,8 @@ function registers.flush(data,options,prefixspec,pagespec) done[i] = false end local data = sublist.data - local d, n = 0, 0 + local d = 0 + local n = 0 ctx_startregistersection(sublist.tag) for d=1,#data do local entry = data[d] @@ -1126,6 +1184,7 @@ function registers.flush(data,options,prefixspec,pagespec) end -- ok, this is tricky: we use e[i] delayed so we need it to be local -- but we don't want to allocate too many entries so there we go + while d < #data do d = d + 1 local entry = data[d] @@ -1164,8 +1223,8 @@ function registers.flush(data,options,prefixspec,pagespec) started = false end if n == i then --- ctx_stopregisterentries() --- ctx_startregisterentries(n) + -- ctx_stopregisterentries() + -- ctx_startregisterentries(n) else while n > i do n = n - 1 @@ -1186,127 +1245,131 @@ function registers.flush(data,options,prefixspec,pagespec) ctx_startregisterentry(0) -- will become a counter started = true if metadata then - ctx_registerentry(processor,internal,seeparent,function() h_title(e[i],metadata) end) + ctx_registerentry(metadata.name or "",processor,internal,seeparent,function() h_title(e[i],metadata) end) else -- can this happen? - ctx_registerentry(processor,internal,seeindex,e[i]) + ctx_registerentry("",processor,internal,seeindex,e[i]) end end end - if kind == 'entry' then - if show_page_number then - ctx_startregisterpages() - if collapse_singles or collapse_ranges then - -- we collapse ranges and keep existing ranges as they are - -- so we get prebuilt as well as built ranges - local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0 - while dd < #data do - dd = dd + 1 - local next = data[dd] - if next and next.metadata.kind == "see" then - dd = dd - 1 - break - else - local el, nl = entry.list, next.list - if not equal(el,nl) then - dd = dd - 1 - --~ first = nil - break - elseif next.references.lastrealpage then - nofpages = nofpages + 1 - pages[nofpages] = first and { first, last or first } or { entry, entry } - nofpages = nofpages + 1 - pages[nofpages] = { next, next } - first, last, prev = nil, nil, nil - elseif not first then - first, prev = next, next - elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ? - last, prev = next, next - else - nofpages = nofpages + 1 - pages[nofpages] = { first, last or first } - first, last, prev = next, nil, next - end - end - end - if first then + + local function case_1() + -- we collapse ranges and keep existing ranges as they are + -- so we get prebuilt as well as built ranges + local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0 + while dd < #data do + dd = dd + 1 + local next = data[dd] + if next and next.metadata.kind == "see" then + dd = dd - 1 + break + else + local el, nl = entry.list, next.list + if not equal(el,nl) then + dd = dd - 1 + --~ first = nil + break + elseif next.references.lastrealpage then + nofpages = nofpages + 1 + pages[nofpages] = first and { first, last or first } or { entry, entry } + nofpages = nofpages + 1 + pages[nofpages] = { next, next } + first, last, prev = nil, nil, nil + elseif not first then + first, prev = next, next + elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ? + last, prev = next, next + else nofpages = nofpages + 1 pages[nofpages] = { first, last or first } + first, last, prev = next, nil, next end - if collapse_ranges and nofpages > 1 then - nofpages = collapsepages(pages) - end - if nofpages > 0 then -- or 0 - d = dd - for p=1,nofpages do - local first, last = pages[p][1], pages[p][2] - if first == last then - if first.references.lastrealpage then - pagerange(first,first,true,prefixspec,pagespec) - else - pagenumber(first,prefixspec,pagespec) - end - elseif last.references.lastrealpage then - pagerange(first,last,true,prefixspec,pagespec) - else - pagerange(first,last,false,prefixspec,pagespec) - end + end + end + if first then + nofpages = nofpages + 1 + pages[nofpages] = { first, last or first } + end + if collapse_ranges and nofpages > 1 then + nofpages = collapsepages(pages) + end + if nofpages > 0 then -- or 0 + d = dd + for p=1,nofpages do + local first, last = pages[p][1], pages[p][2] + if first == last then + if first.references.lastrealpage then + pagerange(first,first,true,prefixspec,pagespec) + else + pagenumber(first,prefixspec,pagespec) end - elseif entry.references.lastrealpage then - pagerange(entry,entry,true,prefixspec,pagespec) + elseif last.references.lastrealpage then + pagerange(first,last,true,prefixspec,pagespec) else - pagenumber(entry,prefixspec,pagespec) + pagerange(first,last,false,prefixspec,pagespec) end - elseif collapse_packed then - local first = nil - local last = nil - while true do - if not first then - first = entry - end - last = entry - if d == #data then - break - else - d = d + 1 - local next = data[d] - if next.metadata.kind == "see" or not equal(entry.list,next.list) then - d = d - 1 - break - else - entry = next - end - end + end + elseif entry.references.lastrealpage then + pagerange(entry,entry,true,prefixspec,pagespec) + else + pagenumber(entry,prefixspec,pagespec) + end + end + + local function case_2() + local first = nil + local last = nil + while true do + if not first then + first = entry + end + last = entry + if d == #data then + break + else + d = d + 1 + local next = data[d] + if next.metadata.kind == "see" or not equal(entry.list,next.list) then + d = d - 1 + break + else + entry = next end - packed(first,last) -- returns internals + end + end + packed(first,last) -- returns internals + end + + local function case_3() + while true do + if entry.references.lastrealpage then + pagerange(entry,entry,true,prefixspec,pagespec) else - while true do - if entry.references.lastrealpage then - pagerange(entry,entry,true,prefixspec,pagespec) - else - pagenumber(entry,prefixspec,pagespec) - end - if d == #data then - break - else - d = d + 1 - local next = data[d] - if next.metadata.kind == "see" or not equal(entry.list,next.list) then - d = d - 1 - break - else - entry = next - end - end + pagenumber(entry,prefixspec,pagespec) + end + if d == #data then + break + else + d = d + 1 + local next = data[d] + if next.metadata.kind == "see" or not equal(entry.list,next.list) then + d = d - 1 + break + else + entry = next end end - ctx_stopregisterpages() end - elseif kind == 'see' then - local t, nt = { }, 0 + end + + local function case_4() + local t = { } + local nt = 0 while true do - nt = nt + 1 - t[nt] = entry + if entry.seeword and entry.seeword.valid then + nt = nt + 1 + t[nt] = entry + end if d == #data then break else @@ -1320,19 +1383,36 @@ function registers.flush(data,options,prefixspec,pagespec) end end end - ctx_startregisterseewords() for i=1,nt do - local entry = t[i] + local entry = t[i] local seeword = entry.seeword local seetext = seeword.text or "" local processor = seeword.processor or (entry.processors and entry.processors[1]) or "" local seeindex = entry.references.seeindex or "" - -- ctx_registerseeword(i,nt,processor,0,seeindex,seetext) - ctx_registerseeword(i,nt,processor,0,seeindex,function() h_title(seetext,metadata) end) + ctx_registerseeword(metadata.name or "",i,nt,processor,0,seeindex,function() h_title(seetext,metadata) end) end + end + + if kind == "entry" then + if show_page_number then + ctx_startregisterpages() + if collapse_singles or collapse_ranges then + case_1() + elseif collapse_packed then + case_2() + else + case_3() + end + ctx_stopregisterpages() + end + elseif kind == "see" then + ctx_startregisterseewords() + case_4() ctx_stopregisterseewords() end + end + if started then ctx_stopregisterentry() started = false @@ -1373,6 +1453,7 @@ implement { { "numberorder" }, { "compress" }, { "criterium" }, + { "check" }, { "pagenumber", "boolean" }, }, { diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv index 04fdef9adc2..559e1bd4231 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-reg.mkiv @@ -83,6 +83,7 @@ \c!pagestyle=\v!slanted, \c!indicator=\v!yes, \c!criterium=\v!all, + \c!check=\v!yes, % check for weird see usage %\c!command=, \c!referencing=\v!on, \c!location=\v!middle, @@ -159,8 +160,8 @@ %D Registering: -\global\let\currentregistername \empty -\global\let\currentregisternumber\!!zerocount +\glet\currentregistername \empty +\glet\currentregisternumber\!!zerocount \def\strc_registers_register_page_entry {\iftrialtypesetting @@ -175,33 +176,33 @@ \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% \xmlstopraw - \globallet\currentregistercoding\s!xml} + \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes_entries {\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop_entries {\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}% \xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}% \xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml {\xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw - \globallet\currentregistercoding\s!xml} + \glet\currentregistercoding\s!xml} \def\strc_registers_register_page_expand_yes {\xdef\currentregisterentries{\registerparameter\c!entries}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_nop {\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% - \globallet\currentregistercoding\s!tex} + \glet\currentregistercoding\s!tex} \def\strc_registers_register_page_expand_xml_keys {\xmlstartraw @@ -304,7 +305,7 @@ \ifx\currentregisterownnumber\v!yes \glet\currentregistersynchronize\relax \else - \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}% + \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% \fi \currentregistersynchronize % here? % needs thinking ... bla\index{bla}. will break before the . but adding a @@ -340,7 +341,7 @@ % internal \locationcount % view {\interactionparameter\c!focus}% \relax % this will change - \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}% + \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}% \currentregistersynchronize % here? \dostarttagged\t!registerlocation\currentregister \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup @@ -352,16 +353,46 @@ \unexpanded\def\strc_registers_insert_entry[#1][#2]% {\def\currentregister{#1}% - \doifelse{\registerparameter\c!ownnumber}\v!yes - \strc_registers_insert_entry_yes - \strc_registers_insert_entry_nop - {#2}} + \edef\p_ownnumber{\registerparameter\c!ownnumber}% + \ifx\p_ownnumber\v!yes + \expandafter\strc_registers_insert_entry_yes + \else + \expandafter\strc_registers_insert_entry_nop + \fi{#2}} + +% \def\strc_registers_insert_entry_nop#1#2% +% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} +% +% \def\strc_registers_insert_entry_yes#1#2#3% +% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} +% +% less tokens passed (nicer for tracing) .. could become installable + +\def\strc_registers_insert_entry_nop + {\ifvmode + \expandafter\strc_registers_insert_entry_nop_par + \else + \expandafter\strc_registers_insert_entry_nop_txt + \fi} + +\def\strc_registers_insert_entry_yes + {\ifvmode + \expandafter\strc_registers_insert_entry_yes_par + \else + \expandafter\strc_registers_insert_entry_yes_txt + \fi} + +\def\strc_registers_insert_entry_nop_par#1#2% + {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} -\def\strc_registers_insert_entry_nop#1#2% - {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}} +\def\strc_registers_insert_entry_yes_par#1#2#3% + {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} -\def\strc_registers_insert_entry_yes#1#2#3% - {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}} +\def\strc_registers_insert_entry_nop_txt#1#2% + {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}} + +\def\strc_registers_insert_entry_yes_txt#1#2#3% + {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}} \unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry} \unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry} @@ -403,14 +434,14 @@ \xmlstartraw \xdef\currentregisterentries{\registerparameter\c!entries}% \xmlstopraw - \globallet\currentregistercoding\s!xml + \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{\registerparameter\c!entries}% \else \xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}% \fi - \globallet\currentregistercoding\s!tex + \glet\currentregistercoding\s!tex \fi % I hate this kind of mess ... but it's a user request. \ifx\currentregisterentries\empty @@ -493,7 +524,7 @@ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \xmlstopraw - \globallet\currentregistercoding\s!xml + \glet\currentregistercoding\s!xml \else \ifx\currentregisterexpansion\v!yes \xdef\currentregisterentries{#3}% not ok yet @@ -502,7 +533,7 @@ \xdef\currentregisterentries{\detokenize{#3}}% not ok yet \xdef\currentregisterseeword{\detokenize{#4}}% not ok yet \fi - \globallet\currentregistercoding\s!tex + \glet\currentregistercoding\s!tex \fi \setnextinternalreference % we could consider storing register entries in list @@ -544,8 +575,8 @@ \def\strc_registers_determine_characteristics[#1][#2]% {\begingroup - \edef\currentregister{#1}% - \setupregister[\currentregister][#2]% + \setupregister[#1][#2]% + \edef\currentregister{\firstinset{#1}}% \normalexpanded{\endgroup\noexpand\xdef\noexpand\utilityregisterlength{\clf_analyzeregister {\currentregister}% {% @@ -569,6 +600,8 @@ \dontcomplain \to \everyplaceregister +\newconditional\c_strc_registers_text_interaction + \unexpanded\def\placeregister {\dodoubleempty\strc_registers_place} @@ -576,30 +609,29 @@ {\iffirstargument \begingroup %\forgetall - \edef\currentregister{#1}% - \setupregister[\currentregister][#2]% + \setupregister[#1][#2]% can be a list + \edef\currentregister{\firstinset{#1}}% \the\everyplaceregister \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone \startmixedcolumns[\currentregister] - \strc_registers_place_indeed + \strc_registers_place_indeed{#1}% \stopmixedcolumns \else - \strc_registers_place_indeed + \strc_registers_place_indeed{#1}% \fi \endgroup \fi} -\newconditional\c_strc_registers_text_interaction - -\def\strc_registers_place_indeed +\def\strc_registers_place_indeed#1% {\doifelse{\registerparameter\c!interaction}\v!text \settrue\setfalse\c_strc_registers_text_interaction \clf_processregister - {\currentregister}% + {#1}% {% language {\registerparameter\s!language}% method {\registerparameter\c!method}% numberorder {\registerparameter\c!numberorder}% + check {\registerparameter\c!check}% compress {\registerparameter\c!compress}% criterium {\registerparameter\c!criterium}% pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi @@ -639,9 +671,9 @@ \def\strc_registers_complete[#1][#2]% {\iffirstargument \begingroup - \edef\currentregister{#1}% + \edef\currentregister{\firstinset{#1}}% \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}% - \placeregister[\currentregister][#2]% + \placeregister[#1][#2]% \page[\v!yes]% \stopnamedsection \endgroup @@ -835,15 +867,16 @@ \unexpanded\def\startregisterpages {\begingroup \dostarttagged\t!registerpages\empty - \useregisterstyleandcolor\c!pagestyle\c!pagecolor} + \useregisterstyleandcolor\c!pagestyle\c!pagecolor + \registerparameter\c!pageleft} \unexpanded\def\stopregisterpages - {\dostoptagged + {\registerparameter\c!pageright + \dostoptagged \endgroup} \unexpanded\def\startregisterseewords - {%\par % \ifhmode\crlf\fi % otherwise wrong level - \begingroup + {\begingroup \dostarttagged\t!registerpage\empty \useregisterstyleandcolor\c!pagestyle\c!pagecolor} @@ -876,46 +909,69 @@ % \fi} \unexpanded\def\withregisterpagecommand#1#2#3#4% - {\def\currentregisterpageindex{#2}% - \iflocation - \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% + {\ifcase#3\relax + {\tt [entry\space not\space flushed]}% \else - \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% + \def\currentregisterpageindex{#2}% + \iflocation + \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]% + \else + \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}% + \fi \fi} -\unexpanded\def\registeronepage#1#2#3#4% #1:processor content - {\registerpageseparator - \global\setconstant\c_strc_registers_page_state\plusone - \dostarttagged\t!registerpage\empty - \withregisterpagecommand{#1}{#2}{#3}{#4}% - \dostoptagged} - -\unexpanded\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable - {\registerpageseparator - \global\setconstant\c_strc_registers_page_state\plusone - \dostarttagged\t!registerpagerange\empty - \dostarttagged\t!registerfrompage\empty - \withregisterpagecommand{#1}{#2}{#3}{#4}% - \dostoptagged - \registeronepagerangeseparator - \dostarttagged\t!registertopage\empty - \withregisterpagecommand{#1}{#5}{#6}{#7}% - \dostoptagged - \dostoptagged} +\unexpanded\def\pushcurrentregister#1% + {\let\m_current_register\currentregister + \edef\currentregister{#1}} + +\unexpanded\def\popcurrentregister + {\let\currentregister\m_current_register} + +\unexpanded\def\registeronepage#1#2#3#4#5% #1:class #2:processor content + {\pushcurrentregister{#1}% + \edef\p_pagenumber{\registerparameter\c!pagenumber}% + \ifx\p_pagenumber\v!no\else + \registerpageseparator + \global\setconstant\c_strc_registers_page_state\plusone + \dostarttagged\t!registerpage\empty + \withregisterpagecommand{#2}{#3}{#4}{#5}% + \dostoptagged + \fi + \popcurrentregister} + +\unexpanded\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable + {\pushcurrentregister{#1}% + \edef\p_pagenumber{\registerparameter\c!pagenumber}% + \ifx\p_pagenumber\v!no\else + \registerpageseparator + \global\setconstant\c_strc_registers_page_state\plusone + \dostarttagged\t!registerpagerange\empty + \dostarttagged\t!registerfrompage\empty + \withregisterpagecommand{#2}{#3}{#4}{#5}% + \dostoptagged + \registeronepagerangeseparator + \dostarttagged\t!registertopage\empty + \withregisterpagecommand{#2}{#6}{#7}{#8}% + \dostoptagged + \dostoptagged + \fi + \popcurrentregister} -\unexpanded\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word - {\def\currentregisterpageindex{#2}% +\unexpanded\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word + {\pushcurrentregister{#1}% + \def\currentregisterpageindex{#3}% \iflocation - \def\currentregisterseeindex{#3}% + \def\currentregisterseeindex{#4}% \ifconditional\c_strc_registers_text_interaction - \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]% + \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]% \else - \doapplyregisterentrycommand{#1}{#4}% + \doapplyregisterentrycommand{#2}{#5}% \fi \else \let\currentregisterseeindex\empty - \doapplyregisterentrycommand{#1}{#4}% - \fi} + \doapplyregisterentrycommand{#2}{#5}% + \fi + \popcurrentregister} \unexpanded\def\doapplyregisterentrycommand#1#2% processor text {\dostarttagged\t!registercontent\empty @@ -935,25 +991,29 @@ \applyprocessor{#1}{#2}% \fi\fi} -\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word - {\registerpageseparator +\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word + {\pushcurrentregister{#1}% + \ifnum#2=\plusone + \registerpageseparator + \fi \global\setconstant\c_strc_registers_page_state\plustwo - \def\currentregisterpageindex{#4}% + \def\currentregisterpageindex{#5}% \dostarttagged\t!registersee\empty \settrue\c_strc_registers_page_done \iflocation - \def\currentregisterseeindex{#5}% + \def\currentregisterseeindex{#6}% \else \let\currentregisterseeindex\empty \fi - \ifnum#1=\plusone - \labeltexts\v!see{\doapplyregisterseecommand{#3}{#6}}% - \else\ifnum#1=#2\relax - \labeltexts\v!and{\doapplyregisterseecommand{#3}{#6}}% + \ifnum#2=\plusone + \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}% + \else\ifnum#2=#3\relax + \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}% \else - ,\space\doapplyregisterseecommand{#3}{#6}% + ,\space\doapplyregisterseecommand{#4}{#7}% \fi\fi - \dostoptagged} + \dostoptagged + \popcurrentregister} \let\registerseeword \defaultregisterseeword \let\registerentry \defaultregisterentry @@ -993,18 +1053,18 @@ \setvalue{\??registersymbol\v!none}% {\let\registerpageseparatorsymbol\empty - \let\registeronepage \gobblefourarguments - \let\registerpagerange \gobblesevenarguments} + \let\registeronepage \gobblefivearguments + \let\registerpagerange\gobbleeightarguments} \setvalue{\??registersymbol 1}% {\let\registerpageseparatorsymbol\space - \def\registeronepage {\symbol[1]\gobblefourarguments}% - \def\registerpagerange{\symbol[1]\gobblesevenarguments}} + \def\registeronepage {\symbol[1]\gobblefivearguments}% + \def\registerpagerange{\symbol[1]\gobbleeightarguments}} \setvalue{\??registersymbol 2}% {\let\registerpageseparatorsymbol\space - \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}% - \def\registerpagerange{\registerpagebuttonsymbol\gobblesevenarguments}} + \def\registeronepage {\registerpagebuttonsymbol\gobblefivearguments}% + \def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}} \unexpanded\def\setregisterpagerendering {\doifelse{\registerparameter\c!pagenumber}\v!no @@ -1016,8 +1076,8 @@ \csname\??registersymbol\currentregisterpagesymbol\endcsname \else \let\registerpageseparatorsymbol\space - \def\registeronepage{\registerparameter\c!symbol\gobblefourarguments}% - \def\registerpagerange{\registerparameter\c!symbol\gobblesevenarguments}% + \def\registeronepage {\registerparameter\c!symbol\gobblefivearguments}% + \def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}% \fi\fi} \appendtoks diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv index 89aa6f55a1a..01464ad8649 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-ren.mkiv @@ -120,7 +120,7 @@ \setheadmarking \doresetstructureheadnumbercontent \ifconditional\c_strc_sectioning_empty - \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}% + \setbox\b_strc_rendering_head\hpack \headreferenceattributes to \zeropoint{\strut}% \else \docheckheadreference \setbox\b_strc_rendering_head\hbox \headreferenceattributes @@ -139,7 +139,7 @@ \dosetstructureheadnumbercontent \doresetstructureheadnumbercontent \ifconditional\c_strc_sectioning_empty - \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}% + \setbox\b_strc_rendering_head\hpack \headreferenceattributes to \zeropoint{\strut}% \else % = needed \docheckheadreference \setbox\b_strc_rendering_head\hbox \headreferenceattributes @@ -151,7 +151,7 @@ \strc_rendering_stop_placement} \unexpanded\def\strc_rendering_place_head_empty - {\hbox\headreferenceattributes{\getheadsyncs}} % \hpack ? + {\hpack\headreferenceattributes{\getheadsyncs}} %D \starttyping %D \def\StretchedBox#1% @@ -197,14 +197,13 @@ \def\strc_rendering_start_placement {\bgroup \setsystemmode\currenthead - % \strc_rendering_initialize_alternatives \strc_rendering_initialize_dimensions - % \strc_rendering_initialize_line_state \reseteverypar % needed indeed \noindent % ipv \whitespace elders, na \forgetall ! \bgroup + \synctexpushline \edef\p_aligntitle{\headparameter\c!aligntitle}% \ifx\p_aligntitle\v!yes \strc_rendering_initialize_hsize_local @@ -325,7 +324,9 @@ % kind of special, we want to snap heads also according to local specs local \setbox\b_strc_rendering_head\hbox {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax - \box\b_strc_rendering_head}% + \box\b_strc_rendering_head + \getheadsyncs % a latelua why not in the box + }% \ifgridsnapping \applygridmethod {\headparameter\c!grid}% @@ -345,14 +346,14 @@ \nointerlineskip \dosomebreak\nobreak \fi - \getheadsyncs +% \getheadsyncs % a latelua why not in the box \else % somehow this goes ok even when we push in the margin probably because we gobble pars % in the process of collecting index entries etc \strut \flushnotes % new, here since we're in par mode \unhbox\b_strc_rendering_head - \getheadsyncs + \getheadsyncs % a latelua \ifconditional\headissomewhere \strc_sectioning_stay_on_this_line % test case: alternative=margintext and \startparagraph .. \else @@ -370,6 +371,7 @@ \fi \fi \fi + \synctexpopline \egroup \egroup \ifconditional\headisdisplay @@ -528,8 +530,14 @@ \def\fakedheadnumber{\vphantom{0}} % needed for mathplus +% \unexpanded\def\fakeheadnumbercontent +% {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}} + \unexpanded\def\fakeheadnumbercontent - {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}} + {\edef\p_hidenumber{\headparameter\c!hidenumber}% + \ifx\p_hidenumber\v!yes\else + \hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}% + \fi} \unexpanded\def\strc_rendering_inject_number_and_text {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition @@ -777,18 +785,18 @@ \startsetups[\??headrenderings:\v!bottom] \ifconditional\headshownumber - \setbox0\hbox { + \setbox\scratchboxone\hbox { \headnumbercontent } - \setbox2\vbox { + \setbox\scratchboxtwo\vbox { \headsetupspacing - \advance\hsize-\wd0\relax + \advance\hsize-\wd\scratchboxone\relax \headtextcontent } \hbox { - \box0 + \box\scratchboxone \hskip\headnumberdistance - \box2 + \box\scratchboxtwo } \else \vbox { @@ -806,18 +814,18 @@ \startsetups[\??headrenderings:\v!top] \ifconditional\headshownumber - \setbox0\hbox { + \setbox\scratchboxone\hbox { \headnumbercontent } - \setbox2\vtop { + \setbox\scratchboxtwo\vtop { \headsetupspacing - \advance\hsize-\wd0\relax + \advance\hsize-\wd\scratchboxone\relax \headtextcontent } \hbox { - \box0 + \box\scratchboxone \hskip\headnumberdistance - \box2 + \box\scratchboxtwo } \else \vtop{ diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv index 9f1d214cfda..005f03df3ae 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-sbe.mkiv @@ -45,7 +45,7 @@ \def\strc_sectionblock_define[#1][#2][#3]% singular plural settings {\strc_sectionblock_define_normal[#1][#3]% - \expandafter\newif\csname if#2\endcsname % obsolete + %\expandafter\newif\csname if#2\endcsname % obsolete \strc_sectionblock_set_environment{#1}\empty \setuvalue{\e!start#2}{\startsectionblock[#1]}% \setuvalue{\e!stop #2}{\stopsectionblock}} @@ -98,7 +98,7 @@ \clf_pushsectionblock{#1} bookmark {\sectionblockparameter\c!bookmark}% \relax - \csname #1true\endcsname % obsolete + %\csname #1true\endcsname % obsolete \setsystemmode\currentsectionblock \the\everybeforesectionblock\relax \showmessage\m!structures1\currentsectionblock} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv index 4e5115a7d36..4066a1f38c8 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-sec.mkiv @@ -35,6 +35,7 @@ \c!label=, \c!coupling=, \c!ownnumber=, + % \c!interaction=\v!list, \c!sectionseparatorset=\s!default, \c!sectionconversionset=\s!default, \c!sectionstopper=, @@ -53,6 +54,10 @@ \def\m_strc_references_prefix_yes{+} \def\m_strc_references_prefix_nop{-} +\let\currentstructurereferenceprefix\empty + +\installglobalmacrostack\currentstructurereferenceprefix + \def\strc_sectioning_set_reference_prefix {\ifx\currentstructurereferenceprefix\empty % nothing @@ -64,7 +69,7 @@ \else \setupglobalreferenceprefix[\currentstructurereferenceprefix]% \fi\fi\fi - \let\currentstructurereferenceprefix\referenceprefix} + \glet\currentstructurereferenceprefix\referenceprefix} % why xdef ? @@ -108,9 +113,10 @@ \def\strc_sectioning_autobookmark#1% {\begingroup + % \settrialtypesetting \the\everypreroll \nodestostring\tempstring{#1}% - \globallet\currentstructurebookmark\tempstring + \glet\currentstructurebookmark\tempstring \endgroup} % zeros: @@ -150,9 +156,9 @@ \strc_sectioning_autobookmark\currentstructuretitle \fi \fi \fi \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle + \glet\currentstructurelist\currentstructuretitle \fi - \globallet\currentstructurecoding\s!xml + \glet\currentstructurecoding\s!xml \else \ifx\currentstructureexpansion\v!yes \xdef\currentstructuretitle {\structureparameter\c!title}% @@ -179,9 +185,9 @@ \fi \fi \fi \ifx\currentstructurelist\empty - \globallet\currentstructurelist\currentstructuretitle + \glet\currentstructurelist\currentstructuretitle \fi - \globallet\currentstructurecoding\s!tex + \glet\currentstructurecoding\s!tex \fi \setnextinternalreference \storeinternalreference\currentstructurename{\the\locationcount}% @@ -249,7 +255,7 @@ userdata {\detokenize{#3}}% will be converted to table at the lua end \relax \xdef\currentstructurelistnumber{\clf_currentsectiontolist}% - % \currentstructuresynchronize has to be called someplace, since it introduces a node + % \currentstructuresynchronize has to be called someplace, since it introduces a node \setstructuresynchronization\currentstructurelistnumber \endgroup} @@ -340,6 +346,9 @@ \installcommandhandler \??head {head} \??head +\installmacrostack\currenthead +\installmacrostack\currentheadparent + \setuphead [% %\c!after=, %\c!align=, @@ -479,16 +488,18 @@ \to \everysetuphead \unexpanded\def\doredefinehead#1#2% called at lua end - {\pushmacro\currenthead - \pushmacro\currentheadparent + {\push_macro_currenthead + \push_macro_currentheadparent \edef\currenthead{#1}% \edef\currentheadparent{#2}% \the\everyredefinehead\relax - \popmacro\currentheadparent - \popmacro\currenthead} + \pop_macro_currentheadparent + \pop_macro_currenthead} \let\currentnamedsection\empty +\installmacrostack\currentnamedsection + \unexpanded\def\startnamedsection {\dotripleempty\strc_sectioning_start_named_section} @@ -577,7 +588,7 @@ \fi} \def\strc_sectioning_setup_indeed[#1][#2][#3]% - {\pushmacro\currenthead + {\push_macro_currenthead \ifthirdargument \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now) \setupcurrenthead[#3]% @@ -585,7 +596,7 @@ \edef\currenthead{#1}% \setupcurrenthead[#2]% \fi - \popmacro\currenthead} + \pop_macro_currenthead} % we share the parameters as sections are roots of heads so eventually we can % consider \definesection -> \definehead with one argument @@ -638,7 +649,8 @@ {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- \unexpanded\def\strc_sectioning_start_named_section[#1][#2][#3]% for the moment no grouping, too annoying with page breaks - {\pushmacro\currentnamedsection + {\push_macro_currentnamedsection + \push_macro_currentstructurereferenceprefix \edef\currentnamedsection{#1}% \setfalse\currentstructureown %\globalpushmacro\currenthead % this does not work out well @@ -659,7 +671,8 @@ \headparameter\c!aftersection \the\everyafterhead \resetsystemmode\currenthead - \popmacro\currentnamedsection} % new, also here now + \pop_macro_currentstructurereferenceprefix + \pop_macro_currentnamedsection} % new, also here now \let\dostarthead\strc_sectioning_start % used at lua end \let\dostophead \strc_sectioning_stop % used at lua end @@ -755,15 +768,25 @@ \setfalse\headshownumber \fi} +% Beware, we do need some node for anchoring marks and normally a zwnj will +% do but it interferes so we deal with it at the \LUA\ end. + \newtoks\everyheadsynchronization +% \appendtoks +% \currentstructuresynchronize +% \to \everyheadsynchronization + +\let\currentstructuresynchronize\donothing + \appendtoks \currentstructuresynchronize + \glet\currentstructuresynchronize\donothing \to \everyheadsynchronization \unexpanded\def\theheadsynchonization - {\the\everyheadsynchronization - \currentstructuresynchronize} + {% no, interferes: \signalcharacter + \the\everyheadsynchronization} % BEWARE: \marking[section]{my text} does not work as we use list indices instead % so we need a 'keep track of raw set option' (or maybe a funny internal prefix) @@ -802,6 +825,17 @@ \let\currentheadlevel \!!zerocount \let\currentheadcounter \!!zerocount +\let\strc_show_used\relax + +\installtextracker + {structures.showused} + {\let\strc_show_used\clf_showstructure} + {\let\strc_show_used\relax} + +\appendtoks + \strc_show_used +\to \everystoptext + \unexpanded\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care \unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care @@ -842,6 +876,9 @@ \ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi +\newtoks\everybeforesectionheadhandle +\newtoks\everyaftersectionheadhandle + \def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller) {\xdef\currenthead {#1}% \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}% @@ -855,7 +892,7 @@ \strc_sectioning_initialize_placement \strc_sectioning_initialize_number % - \flushingcolumnfloatsfalse + \the\everybeforesectionheadhandle % % todo: also mark (for header) % @@ -941,7 +978,9 @@ \strc_sectioning_after_nop \fi\fi \fi - \flushingcolumnfloatstrue + % + \the\everyaftersectionheadhandle + % \setfalse\c_strc_sectioning_ignore_page % ignorespaces prevents spaces creeping in when after=\dontleavehmode \dostarttagged\t!sectioncontent\empty @@ -983,8 +1022,8 @@ \unexpanded\def\strc_rendering_place_head_section % see hidden below {\global\setbox\b_sectioning_delayed\hpack\bgroup \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% - \hpack\headreferenceattributes{}% - \currentstructuresynchronize + \hpack\headreferenceattributes{}% also does the mark + \theheadsynchonization \egroup} \unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check @@ -994,7 +1033,7 @@ {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference - \currentstructuresynchronize}} % and it's a node anyway + \theheadsynchonization}} % and it's a node anyway \def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname} \def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname} @@ -1003,6 +1042,26 @@ \unexpanded\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}} \unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}} +\unexpanded\def\repeathead[#1]% + {\begingroup + \setupinteraction[\c!state=\v!stop]% + \def\currenthead{#1} + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs \relax + \def\getheadtitle {\getmarking[#1]} + \def\getheadnumber{\getmarking[#1\v!number]} + \strc_sectioning_before_yes + \ifconditional\headshownumber + \strc_rendering_place_head_number_and_text + \else + \strc_rendering_place_head_text + \fi + \dostoptagged + \strc_sectioning_after_yes + \endgroup} + % \setuphead[chapter][placehead=hidden] % \chapter {test} % @@ -1154,7 +1213,7 @@ \else \strc_sectioning_check_layout \fi - \globallet\previoushead\currenthead} + \glet\previoushead\currenthead} \def\strc_sectioning_handle_page_yes {\ifconditional\c_strc_sectioning_ignore_page @@ -1178,7 +1237,7 @@ \fi \global\c_strc_sectioning_preceding_level\currentheadlevel \fi - \globallet\previoushead\currenthead} + \glet\previoushead\currenthead} \unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con {\ifconditional\c_strc_sectioning_auto_break diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv index 1fb079f04a8..7f71e88f52f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-syn.mkiv @@ -114,14 +114,14 @@ \xmlstartraw \xdef#2{#4}% \xmlstopraw - \globallet#3\s!xml + \glet#3\s!xml \else \ifx#1\v!yes \xdef#2{#4}% \else \xdef#2{\detokenize{#4}}% \fi - \globallet#3\s!tex + \glet#3\s!tex \fi} %D We now use a simple list variant: diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua index 649465a6ada..0453640ca00 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.lua @@ -15,7 +15,6 @@ local type, next = type, next local insert, remove, unpack, concat, merge = table.insert, table.remove, table.unpack, table.concat, table.merge local find, topattern, format = string.find, string.topattern, string.format local lpegmatch, P, S, C, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Cc -local texattribute = tex.attribute local allocate = utilities.storage.allocate local settings_to_hash = utilities.parsers.settings_to_hash local setmetatableindex = table.setmetatableindex @@ -24,34 +23,44 @@ local trace_tags = false trackers.register("structures.tags", function(v) trace local report_tags = logs.reporter("structure","tags") -local attributes = attributes -local structures = structures -local implement = interfaces.implement - -local a_tagged = attributes.private('tagged') - -local unsetvalue = attributes.unsetvalue -local codeinjections = backends.codeinjections - -local taglist = allocate() -- access by attribute -local specifications = allocate() -- access by fulltag -local labels = allocate() -local stack = { } -local chain = { } -local ids = { } -local enabled = false -local tagcontext = { } -local tagpatterns = { } -local lasttags = { } -local stacksize = 0 -local metadata = nil -- applied to the next element -local documentdata = { } - -local tags = structures.tags -tags.taglist = taglist -- can best be hidden -tags.labels = labels -tags.patterns = tagpatterns -tags.specifications = specifications +local attributes = attributes +local structures = structures +local implement = interfaces.implement + +local a_tagged = attributes.private('tagged') + +local unsetvalue = attributes.unsetvalue +local codeinjections = backends.codeinjections + +local texgetattribute = tex.getattribute +local texsetattribute = tex.setattribute + +local taglist = allocate() -- access by attribute +local specifications = allocate() -- access by fulltag +local labels = allocate() +local stack = { } +local chain = { } +local ids = { } +local enabled = false +local tagcontext = { } +local tagpatterns = { } +local lasttags = { } +local stacksize = 0 +local metadata = nil -- applied to the next element +local documentdata = { } +local extradata = false + +local tags = structures.tags +tags.taglist = taglist -- can best be hidden +tags.labels = labels +tags.patterns = tagpatterns +tags.specifications = specifications + +function tags.current() + if stacksize > 0 then + return stack[stacksize] -- maybe copy or proxy + end +end -- Tags are internally stored as: -- @@ -126,6 +135,7 @@ local properties = allocate { -- todo: more "record = true" to improve forma listcontent = { pdf = "P", nature = "mixed" }, listdata = { pdf = "P", nature = "mixed" }, listpage = { pdf = "Reference", nature = "mixed" }, + listtext = { pdf = "Span", nature = "inline" }, delimitedblock = { pdf = "BlockQuote", nature = "display" }, delimited = { pdf = "Quote", nature = "inline" }, @@ -157,9 +167,11 @@ local properties = allocate { -- todo: more "record = true" to improve forma subformula = { pdf = "Div", nature = "display" }, link = { pdf = "Link", nature = "inline" }, + reference = { pdf = "Span", nature = "inline" }, margintextblock = { pdf = "Span", nature = "inline" }, margintext = { pdf = "Span", nature = "inline" }, + marginanchor = { pdf = "Span", nature = "inline" }, math = { pdf = "Div", nature = "inline" }, -- no display mn = { pdf = "Span", nature = "mixed" }, @@ -204,6 +216,14 @@ local properties = allocate { -- todo: more "record = true" to improve forma combinationpair = { pdf = "Span", nature = "display" }, combinationcontent = { pdf = "Span", nature = "mixed" }, combinationcaption = { pdf = "Span", nature = "mixed" }, + + publications = { pdf = "Div", nature = "display" }, + publication = { pdf = "Div", nature = "mixed" }, + pubfld = { pdf = "Span", nature = "inline" }, + + block = { pdf = "Div", nature = "display" }, + userdata = { pdf = "Div", nature = "display" }, + } tags.properties = properties @@ -215,7 +235,7 @@ local patterns = setmetatableindex(function(t,tag) end) function tags.locatedtag(tag) - local attribute = texattribute[a_tagged] + local attribute = texgetattribute(a_tagged) if attribute >= 0 then local specification = taglist[attribute] if specification then @@ -235,7 +255,7 @@ function tags.locatedtag(tag) end function structures.atlocation(str) - local specification = taglist[texattribute[a_tagged]] + local specification = taglist[texgetattribute(a_tagged)] if specification then if list then local taglist = specification.taglist @@ -287,6 +307,20 @@ function tags.getmetadata() return documentdata or { } end +function tags.registerextradata(name,serializer) + if type(serializer) == "function" then + if extradata then + extradata[name] = serializer + else + extradata = { [name] = serializer } + end + end +end + +function tags.getextradata() + return extradata +end + function tags.start(tag,specification) if not enabled then codeinjections.enabletags() @@ -349,7 +383,7 @@ function tags.start(tag,specification) specification.metadata = documentdata end -- - texattribute[a_tagged] = attribute + texsetattribute(a_tagged,attribute) return attribute end @@ -364,7 +398,7 @@ function tags.restart(attribute) taglist[attribute] = { taglist = { unpack(chain,1,stacksize) } } end stack[stacksize] = attribute - texattribute[a_tagged] = attribute + texsetattribute(a_tagged,attribute) return attribute end @@ -374,12 +408,12 @@ function tags.stop() end local t = stack[stacksize] if not t then - -- if trace_tags then + if trace_tags then report_tags("ignoring end tag, previous chain: %s",stacksize > 0 and concat(chain," ",1,stacksize) or "none") - -- end + end t = unsetvalue end - texattribute[a_tagged] = t + texsetattribute(a_tagged,t) return t end diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv index 2ee71d67c21..84e11a63235 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-tag.mkiv @@ -107,6 +107,7 @@ \def\t!listcontent {listcontent} % P \def\t!listdata {listdata} % P \def\t!listpage {listpage} % Reference +\def\t!listtext {listtext} % Span \def\t!delimitedblock {delimited} % BlockQuote \def\t!delimited {delimited} % Quote @@ -136,9 +137,11 @@ \def\t!subformula {subformula} % Div \def\t!link {link} % Link +\def\t!reference {reference} % Span \def\t!margintext {margintext} % Span \def\t!margintextblock {margintextblock} % Div +\def\t!marginanchor {marginanchor} % Span % we might opt for verbose variants so this is experimental: @@ -162,6 +165,13 @@ \def\t!combinationcontent {combinationcontent} % Span \def\t!combinationcaption {combinationcaption} % Span +\def\t!publications {publications} % Span +\def\t!publication {publication} % Span +\def\t!pubfld {pubfld} % Span + +\def\t!block {block} % Div +\def\t!userdata {userdata} % Div + % \setuptaglabeltext % [en] % [\t!document=document] @@ -180,42 +190,51 @@ \unexpanded\def\strc_tags_set_aspect_nop#1#2{} \unexpanded\def\strc_tags_set_aspect_yes#1#2{\clf_settagaspect{#1}{#2}} % todo: ignore when no export / also \let +\unexpanded\def\ignoretagsinexport[#1]% + {\clf_ignoretagsinexport{#1}} + \installcorenamespace{tagging} \installsetuponlycommandhandler \??tagging {tagging} +% it makes no sense to have labels ... maybe some day as a last 'replace' in the export +% which might be more efficient then ... okay, we now cannot overload but who cares + \unexpanded\def\strc_tags_element_start_yes{\dodoubleempty\strc_tags_element_start_yes_indeed} \unexpanded\def\strc_tags_element_start_nop{\dodoubleempty\strc_tags_element_start_nop_indeed} \unexpanded\def\strc_tags_element_start_yes_indeed {\iftrialtypesetting - \expandafter\strc_tags_element_start_nop_indeed + \expandafter\strc_tags_element_start_yes_indeed_nop \else \expandafter\strc_tags_element_start_yes_indeed_yes \fi} -\unexpanded\def\strc_tags_element_stop - {\iftrialtypesetting - \expandafter\strc_tags_element_stop_nop - \else - \expandafter\strc_tags_element_stop_yes - \fi} - -% it makes no sense to have labels ... maybe some day as a last 'replace' in the export -% which might be more efficient then ... okay, we now cannot overload but who cares +\unexpanded\def\strc_tags_element_start_yes_indeed_nop[#1][#2]% + {} \unexpanded\def\strc_tags_element_start_yes_indeed_yes[#1][#2]% {\clf_starttag_u{#1}{#2}} \unexpanded\def\strc_tags_element_stop_yes - {\clf_stoptag} + {\iftrialtypesetting + \expandafter\strc_tags_element_stop_yes_indeed_nop + \else + \expandafter\strc_tags_element_stop_yes_indeed_yes + \fi} -\unexpanded\def\strc_tags_element_start_nop_indeed[#1][#2]% +\unexpanded\def\strc_tags_element_stop_nop {} -\unexpanded\def\strc_tags_element_stop_nop +\unexpanded\def\strc_tags_element_stop_yes_indeed_nop {} +\unexpanded\def\strc_tags_element_stop_yes_indeed_yes + {\clf_stoptag} + +\let\strc_tags_element_start_nop_indeed\strc_tags_element_start_yes_indeed_nop +\let\strc_tags_element_stop_nop_indeed \strc_tags_element_stop_yes_indeed_nop + \def\strc_tags_report_hyphen#1% {\writestatus\m!languages{setting #1 to U+00AD}} @@ -293,12 +312,18 @@ % \dostarttaggedchained % {tag} {detail} \??hash % \dostarttaggednodetail % {tag} -% \unexpanded\def\strc_tags_enable -% {\let\dostarttagged\strc_tags_start_yes -% \let\dostoptagged \strc_tags_stop_yes} +\newconditional\c_strc_tags_enabled + +\let\dotaggedplaceholder\empty + +\chardef\strc_tags_placeholder_char\zerocount % "FFFC \unexpanded\def\strc_tags_enable - {\let\dostarttagged \strc_tags_enabled_start_detail + {% once enable one is toast + \global\settrue\c_strc_tags_enabled + % and gets: + \let\dotaggedplaceholder \strc_tags_placeholder_char + \let\dostarttagged \strc_tags_enabled_start_detail \let\dostarttaggednodetail\strc_tags_enabled_start_no_detail \let\dostarttaggedchained \strc_tags_enabled_start_chained \let\dostoptagged \strc_tags_enabled_stop @@ -306,12 +331,23 @@ \let\dostopignoretagging \strc_tags_stop_yes_ignore} \unexpanded\def\strc_tags_disable - {\let\dostarttagged \strc_tags_start_nop_detail - \let\dostarttaggednodetail\strc_tags_start_nop_no_detail - \let\dostarttaggedchained \strc_tags_start_nop_chained - \let\dostoptagged \strc_tags_stop_nop - \let\dostartignoretagging \strc_tags_start_nop_ignore - \let\dostopignoretagging \strc_tags_stop_nop_ignore} + {\ifconditional\c_strc_tags_enabled + % so now all are artifacts + \let\dotaggedplaceholder \strc_tags_placeholder_char + \let\dostarttagged \strc_tags_start_nop_detail + \let\dostarttaggednodetail\strc_tags_start_nop_no_detail + \let\dostarttaggedchained \strc_tags_start_nop_chained + \let\dostoptagged \strc_tags_stop_nop_ignore + \else + % initial + \let\dotaggedplaceholder \empty + \let\dostarttagged \strc_tags_start_nop_detail + \let\dostarttaggednodetail\strc_tags_start_nop_no_detail + \let\dostarttaggedchained \strc_tags_start_nop_chained + \let\dostoptagged \strc_tags_stop_nop_ignore + \let\dostartignoretagging \strc_tags_start_nop_ignore + \let\dostopignoretagging \strc_tags_stop_nop_ignore + \fi} % for luigi (beware: fully expandable): @@ -468,13 +504,27 @@ %D This will only work well with sane use. -\appendtoks - \dostartignoretagging -\to \everybeforepagebody +% \appendtoks +% {% +% \doglobal\appendtoks +% \strc_tags_start_yes_ignore +% \to \everybeforepagebody +% \doglobal\appendtoks +% \strc_tags_stop_yes_ignore +% \to \everyafterpagebody +% }% +% \to \everyenableelements + +% This doesn't work well either, so instead we handle the ornaments in the +% tagging in a different way (see attr -> false code). -\appendtoks - \dostopignoretagging -\to \everyafterpagebody +% \appendtoks +% \dostartignoretagging +% \to \everybeforepagebody +% +% \appendtoks +% \dostopignoretagging +% \to \everyafterpagebody % \doifelseinelement{structure:section} {yes} {no} % \doifelseinelement{structure:chapter} {yes} {no} diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-usr.lua b/Master/texmf-dist/tex/context/base/mkiv/strc-usr.lua new file mode 100644 index 00000000000..f121fe296a7 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-usr.lua @@ -0,0 +1,29 @@ +if not modules then modules = { } end modules ['strc-usr'] = { + version = 1.000, + comment = "companion to strc-usr.mkiv", + author = "Wolfgang Schuster", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- The following is copied from \type {tabl-xtb.lua} to make the userdata environment +-- work with \LUA\ documents. + +local context = context +local ctxcore = context.core + +local startuserdata = ctxcore.startuserdata +local stopuserdata = ctxcore.stopuserdata + +local startcollecting = context.startcollecting +local stopcollecting = context.stopcollecting + +function ctxcore.startuserdata(...) + startcollecting() + startuserdata(...) +end + +function ctxcore.stopuserdata() + stopuserdata() + stopcollecting() +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-usr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-usr.mkiv new file mode 100644 index 00000000000..97b656fa087 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/strc-usr.mkiv @@ -0,0 +1,180 @@ +%D \module +%D [ file=strc-bkm, +%D version=2009.04.01, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Bookmarks, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Userdata} + +\registerctxluafile{strc-usr}{} + +%D It's a bit like blocks that also use buffers but more lightweight and with +%D inplace settings. +%D +%D \starttyping +%D \defineuserdata [test] [style=italic] +%D +%D \samplefile{klein} +%D +%D \startuserdata [before=\blank,after=\blank,color=red] +%D \samplefile{greenfield} +%D \stopuserdata +%D +%D \samplefile{sapolsky} +%D +%D \startuserdata [test] +%D \samplefile{bryson} +%D \stopuserdata +%D +%D \samplefile{jojomayer} +%D +%D \startuserdata [test] [before=\blank,after=\blank,color=red] +%D \samplefile{linden} +%D \stopuserdata +%D +%D \samplefile{montgomery} +%D \stoptyping +%D +%D Or from \LUA: +%D +%D \starttyping +%D \startluacode +%D context.startuserdata({color="blue"}) +%D context.samplefile("klein") +%D context.stopuserdata() +%D \stopluacode +%D \stoptyping +%D +%D An example of an alternative: +%D +%D \starttyping +%D \defineuserdataalternative [epigraph] [renderingsetup=userdata:epigraph] +%D +%D \startsetups [userdata:epigraph] +%D \startframedtext [location=right,frame=off,align={flushleft,broad},style=\tfx,offset=.25ex,width=.5\textwidth] +%D \begstrut\inlinebuffer[userdata]\endstrut +%D \hairline +%D \wordright{\userdataparameter{author}} +%D \stopframedtext +%D \stopsetups +%D +%D \defineuserdata +%D [epigraph] +%D [alternative=epigraph] +%D +%D \startuserdata [epigraph] [author={Sean B. Carrol}] +%D The fraction of fossil olfactory receptor genes is significantly higher in +%D all species with full color vision. This suggests that the evolution of +%D trichromatic vision --- which allows these primates to detect food, mates, +%D and danger with visual cues --- has reduced their reliance on the sense of +%D smell. +%D \stopuserdata +%D +%D \startuserdata [epigraph] [author={Sean B. Carrol}] +%D \samplefile{carrol} +%D \stopuserdata +%D \stoptyping + +\unprotect + +\installnamespace {userdata} +\installnamespace {userdataalternative} +\installnamespace {userdatarenderings} + +\installcommandhandler \????userdata {userdata} \????userdata +\installcommandhandler \????userdataalternative {userdataalternative} \????userdataalternative + +\unexpanded\def\startuserdata + {\begingroup + \let\currentuserdata\empty + \doifelsenextoptionalcs\userdata_start_delayed\userdata_start_indeed} + +% This variant works only when the userdata instance exists while the assignment check +% can also be used with undefined instances which falls back to the global settings. +% +% \def\userdata_start_delayed[#1]% +% {\ifcsname\nameduserdatahash{\detokenize\expandafter{\normalexpanded{#1}}}\s!parent\endcsname +% \expandafter\userdata_start_delayed_name +% \else +% \expandafter\userdata_start_delayed_parameters +% \fi[#1]} + +\def\userdata_start_delayed[#1]% + {\doifelseassignmentcs{#1}% + \userdata_start_delayed_parameters + \userdata_start_delayed_name + [#1]} + +\def\userdata_start_delayed_parameters[#1]% + {\setupcurrentuserdata[#1]% + \userdata_start_indeed} + +\def\userdata_start_delayed_name[#1]% + {\edef\currentuserdata{#1}% + \checkuserdataparent + \doifelsenextoptionalcs\userdata_start_delayed_parameters\userdata_start_indeed} + +\def\userdata_start_indeed + {\grabbufferdatadirect\s!userdata{\csstring\startuserdata}{\csstring\stopuserdata}} + +% \unexpanded\def\stopuserdata +% {\useuserdatastyleandcolor\c!style\c!color +% \usealignparameter\userdataparameter +% \edef\currentuserdataalternative{\userdataparameter\c!alternative}% +% \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else +% \let\currentuserdataalternative\s!default +% \fi +% \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}% +% \directsetup\p_renderingsetup +% \endgroup} + +\unexpanded\def\stopuserdata + {\userdataparameter\c!before % HH: moved, so we obey the outer spacing + \dostarttagged\t!userdata\currentuserdata % HH: added, maybe move up ? + \begingroup + \useuserdatastyleandcolor\c!style\c!color + \usealignparameter\userdataparameter % HH: added + \edef\currentuserdataalternative{\userdataparameter\c!alternative}% + \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else + \let\currentuserdataalternative\s!default + \fi + \usesetupsparameter\userdataparameter + \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}% + \directsetup\p_renderingsetup + \endgroup + \dostoptagged + \userdataparameter\c!after % HH: moved + \endgroup} + +\unexpanded\def\getuserdata + {\getbufferdata[\s!userdata]} + +\unexpanded\def\getinlineuserdata + {\inlinebuffer[\s!userdata]} + +\defineuserdataalternative + [\s!default] + [\c!renderingsetup=\????userdatarenderings:\s!default] + +% \startsetups[\????userdatarenderings:\s!default] +% \userdataparameter\c!before +% \usesetupsparameter\userdataparameter +% \getbufferdata[\s!userdata] +% \userdataparameter\c!after +% \stopsetups + +\startsetups[\????userdatarenderings:\s!default] + \getuserdata +\stopsetups + +\setupuserdata + [\c!alternative=\s!default] + +\protect diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua index 40047167c3c..1f31f768130 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua @@ -20,63 +20,67 @@ local nodes = nodes local implement = interfaces.implement -local nodecodes = nodes.nodecodes - -local disc_code = nodecodes.disc -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glue_code = nodecodes.glue -local glyph_code = nodecodes.glyph - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - ------ getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getboth = nuts.getboth -local getdisc = nuts.getdisc -local getid = nuts.getid -local getlist = nuts.getlist -local getattribute = nuts.getattribute -local getbox = nuts.getbox -local getdir = nuts.getdir -local getwidth = nuts.getwidth -local takebox = nuts.takebox - ------ setfield = nuts.setfield -local setlink = nuts.setlink -local setboth = nuts.setboth -local setnext = nuts.setnext -local setbox = nuts.setbox -local setlist = nuts.setlist -local setdisc = nuts.setdisc -local setwidth = nuts.setwidth -local setheight = nuts.setheight -local setdepth = nuts.setdepth - -local flush_node = nuts.flush_node -local flush_list = nuts.flush_list -local copy_node = nuts.copy -local copy_list = nuts.copy_list -local find_tail = nuts.tail -local traverse_id = nuts.traverse_id -local list_dimensions = nuts.dimensions -local hpack = nuts.hpack - -local listtoutf = nodes.listtoutf - -local nodepool = nuts.pool -local new_penalty = nodepool.penalty -local new_hlist = nodepool.hlist -local new_glue = nodepool.glue - -local setlistcolor = nodes.tracers.colors.setlist - -local texget = tex.get -local texgetbox = tex.getbox -local texsetdimen = tex.setdimen +local nodecodes = nodes.nodecodes + +local disc_code = nodecodes.disc +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue +local glyph_code = nodecodes.glyph + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +----- getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getboth = nuts.getboth +local getdisc = nuts.getdisc +local getid = nuts.getid +local getlist = nuts.getlist +local getattribute = nuts.getattribute +local getbox = nuts.getbox +local getdirection = nuts.getdirection +local getwidth = nuts.getwidth +local takebox = nuts.takebox + +----- setfield = nuts.setfield +local setlink = nuts.setlink +local setboth = nuts.setboth +local setnext = nuts.setnext +local setbox = nuts.setbox +local setlist = nuts.setlist +local setdisc = nuts.setdisc +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth +local setshift = nuts.setshift + +local flush_node = nuts.flush_node +local flush_list = nuts.flush_list +local copy_node = nuts.copy +local copy_list = nuts.copy_list +local find_tail = nuts.tail +local getdimensions = nuts.dimensions +local hpack = nuts.hpack + +local nextdisc = nuts.traversers.disc +local nextdir = nuts.traversers.dir +local nexthlist = nuts.traversers.hlist + +local listtoutf = nodes.listtoutf + +local nodepool = nuts.pool +local new_penalty = nodepool.penalty +local new_hlist = nodepool.hlist +local new_glue = nodepool.glue + +local setlistcolor = nodes.tracers.colors.setlist + +local texget = tex.get +local texgetbox = tex.getbox +local texsetdimen = tex.setdimen local function hyphenatedlist(head,usecolor) local current = head and tonut(head) @@ -127,7 +131,7 @@ implement { -- local function hyphenatedhack(head,pre) -- pre = tonut(pre) --- for n in traverse_id(disc_code,tonut(head)) do +-- for n in nextdisc, tonut(head) do -- local hyphen = getfield(n,"pre") -- if hyphen then -- flush_list(hyphen) @@ -361,10 +365,12 @@ implement { } local function getnaturaldimensions(n) - local w, h, d = 0, 0, 0 + local w = 0 + local h = 0 + local d = 0 local l = getlist(getbox(n)) if l then - w, h, d = list_dimensions(l) + w, h, d = getdimensions(l) end texsetdimen("lastnaturalboxwd",w) texsetdimen("lastnaturalboxht",h) @@ -391,10 +397,12 @@ interfaces.implement { name = "getnaturalwd", arguments = "integer", actions = function(n) - local w, h, d = 0, 0, 0 + local w = 0 + local h = 0 + local d = 0 local l = getlist(getbox(n)) if l then - w, h, d = list_dimensions(l) + w, h, d = getdimensions(l) end context("\\dimexpr%i\\scaledpoint\\relax",w) end @@ -416,46 +424,60 @@ interfaces.implement { nodes.setboxtonaturalwd = setboxtonaturalwd -local function firstdirinbox(n) - local b = getbox(n) - if b then - local l = getlist(b) - if l then - for h in traverse_id(hlist_code,l) do - return getdir(h) +local doifelse = commands.doifelse + +do + + local dirvalues = nodes.dirvalues + local lefttoright_code = dirvalues.lefttoright + local righttoleft_code = dirvalues.righttoleft + + local function firstdirinbox(n) + local b = getbox(n) + if b then + local l = getlist(b) + if l then + for d in nextdir, l do + return getdirection(d) + end + for h in nexthlist, l do + return getdirection(h) + end end end + return lefttoright_code end -end -nodes.firstdirinbox = firstdirinbox + nodes.firstdirinbox = firstdirinbox -local doifelse = commands.doifelse + interfaces.implement { + name = "doifelserighttoleftinbox", + arguments = "integer", + actions = function(n) + doifelse(firstdirinbox(n) == righttoleft_code) + end + } -interfaces.implement { - name = "doifelserighttoleftinbox", - arguments = "integer", - actions = function(n) - doifelse(firstdirinbox(n) == "TRT") - end -} +end -- new (handy for mp) .. might move to its own module do - local flush_list = nodes.flush_list - local copy_list = nodes.copy_list - local takebox = nodes.takebox - local texsetbox = tex.setbox - - local new_hlist = nodes.pool.hlist - - local boxes = { } - nodes.boxes = boxes - local cache = table.setmetatableindex("table") - local report = logs.reporter("boxes","cache") - local trace = false + local nuts = nodes.nuts + local tonode = nuts.tonode + local takebox = nuts.takebox + local flush_list = nuts.flush_list + local copy_list = nuts.copy_list + local getwhd = nuts.getwhd + local setbox = nuts.setbox + local new_hlist = nuts.pool.hlist + + local boxes = { } + nodes.boxes = boxes + local cache = table.setmetatableindex("table") + local report = logs.reporter("boxes","cache") + local trace = false trackers.register("nodes.boxes",function(v) trace = v end) @@ -487,7 +509,9 @@ do if trace then report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty") end - return b or nil + if b then + return tonode(b) + end end function boxes.restore(category,name,box,copy) @@ -508,11 +532,9 @@ do if trace then report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty") end - texsetbox(box,b or nil) + setbox(box,b or nil) end - local getwhd = nodes.getwhd - function boxes.dimensions(category,name) name = tonumber(name) or name local b = cache[category][name] @@ -592,13 +614,19 @@ do actions = boxes.reset, } - implement { - name = "lastlinewidth", - actions = function() - local head = tex.lists.page_head - -- list dimensions returns 3 value but we take the first - context(head and list_dimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0) - end - } - end + +implement { + name = "lastlinewidth", + actions = function() + local head = tex.lists.page_head + -- list dimensions returns 3 value but we take the first + context(head and getdimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0) + end +} + +interfaces.implement { + name = "shiftbox", + arguments = { "integer", "dimension" }, + actions = function(n,d) setshift(getbox(n),d) end, +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv index fb9cbdf5dac..59e7105207b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.mkiv @@ -15,10 +15,14 @@ \unprotect -\registerctxluafile{supp-box}{} +\registerctxluafile{supp-box}{optimize} % This file is partially cleaned up. +%D First some defaults: + +\fixupboxesmode\plusone + % handy to have % % \hbox to \hsize @@ -208,8 +212,8 @@ %D \smashedvbox to ... {...} %D \stoptyping -\unexpanded\def\smashedhbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} -\unexpanded\def\smashedvbox{\vbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} +\unexpanded\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} +\unexpanded\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} %D First we define a helper. We use a \LUATEX\ feature in order to avoid %D mathpalettes. @@ -576,7 +580,7 @@ \unexpanded\def\doifelsetext#1% {\begingroup - \setbox\scratchbox\hbox + \setbox\scratchbox\hpack {\settrialtypesetting \ignorespaces#1\removeunwantedspaces}% \ifzeropt\wd\scratchbox @@ -589,7 +593,7 @@ \unexpanded\def\doiftext#1% {\begingroup - \setbox\scratchbox\hbox + \setbox\scratchbox\hpack {\settrialtypesetting \ignorespaces#1\removeunwantedspaces}% \ifzeropt\wd\scratchbox @@ -670,7 +674,7 @@ %D \afterassignment\syst_boxes_with_next_box_indeed %D \else\ifx#2\vbox %D \afterassignment\syst_boxes_with_next_box_indeed -%D \else\ifx#2\normalvtop +%D \else\ifx#2\vtop %D \afterassignment\syst_boxes_with_next_box_indeed %D \else\ifx#2\normalvcenter %D \afterassignment\syst_boxes_with_next_box_indeed @@ -730,9 +734,9 @@ %D Some well known friends, but we implement them our own %D way. We want the macros to work in both math and text mode. -\def\dodorlap{\hpack to \zeropoint{\box\nextbox\normalhss}\endgroup} -\def\dodollap{\hpack to \zeropoint{\normalhss\box\nextbox}\endgroup} -\def\dodoclap{\hpack to \zeropoint{\normalhss\box\nextbox\normalhss}\endgroup} +\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup} +\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup} +\def\dodoclap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup} \def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox} \def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox} @@ -746,8 +750,8 @@ \unexpanded\def\llap{\mathortext\domathllap\dollap} \unexpanded\def\clap{\mathortext\domathclap\doclap} -\def\dodotlap{\vpack to \zeropoint{\normalvss\box\nextbox}\endgroup} -\def\dodoblap{\vpack to \zeropoint{\box\nextbox\normalvss}\endgroup} +\def\dodotlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup} +\def\dodoblap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup} \unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox} \unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox} @@ -1183,8 +1187,8 @@ %D complex macro than needed at first sight. \def\dodoboundtext#1% - {\setbox0\hbox{#1}% - \advance\scratchdimen -\wd0 + {\setbox\scratchboxone\hbox{#1}% + \advance\scratchdimen -\wd\scratchboxone \ifdim\scratchdimen>\zeropoint\relax#1\fi}% \def\doboundtext#1#2#3% still used? @@ -1243,7 +1247,7 @@ \ifdim\wd\nextbox>\scratchdimen \setbox\scratchbox\hbox{\ifdone\space#2\else#2\space\fi}% \advance\scratchdimen -\wd\scratchbox - \setbox0\box\nextbox + \setbox\scratchboxone\box\nextbox \setbox\nextbox\vbox {\hsize\scratchdimen \hfuzz\maxdimen @@ -1254,7 +1258,7 @@ \rightskip\zeropoint \hskip\zeropoint \s!plus 1\s!fill % \hsize \fi - \unhcopy0}% + \unhcopy\scratchboxone}% \ifdim\ht\nextbox>\strutht \setbox\nextbox\vbox % if omitted: missing brace reported {\splittopskip\openstrutheight @@ -1262,7 +1266,7 @@ \setbox\nextbox\vsplit\nextbox to \strutht \else \doloop - {\setbox0\vsplit\nextbox to \strutht + {\setbox\scratchboxone\vsplit\nextbox to \strutht \ifdim\ht\nextbox>\strutht \else \exitloop \fi}% \fi \unvbox\nextbox @@ -1304,13 +1308,13 @@ {%\dontleavehmode \bgroup \let\speciallimitatetext\firstoffourarguments - \setbox0\hbox + \setbox\scratchboxone\hbox {\nohyphens \normallimitatetext{#1}{+#2}{}#4% \normallimitatetext{#1}{-#3}{}}% - \setbox2\hbox + \setbox\scratchboxtwo\hbox {#1}% - \ifdim\wd2<\wd0 #1\else\unhbox0\fi + \ifdim\wd\scratchboxtwo<\wd\scratchboxone #1\else\unhbox\scratchboxone\fi \egroup} \unexpanded\def\limitatetext#1#2#3% \expanded added 2003/01/16 @@ -1328,7 +1332,7 @@ %D \stoptyping \unexpanded\def\limitatefirstline#1#2#3% - {\hbox\bgroup\strut + {\hbox\bgroup\strut % \hpack \setbox\scratchbox\hbox{\begstrut#1\endstrut}% \ifdim\wd\scratchbox>#2\relax \setbox\scratchbox\hbox{#3}% @@ -1340,7 +1344,7 @@ {\unvbox\scratchbox \global\setbox\plusone\lastbox \global\setbox\plusone\hbox{\strut\unhbox\plusone}% - \hbox % to #2 + \hbox % to #2 % \hpack {\ifx\clip\undefined \box\plusone \else\ifdim\wd\plusone>\hsize @@ -1533,7 +1537,7 @@ %D a strut. \unexpanded\def\struttedbox - {\hbox\bgroup + {\hpack\bgroup \dowithnextboxcs\syst_boxes_struttedbox_finish\hbox} \def\syst_boxes_struttedbox_finish @@ -1550,7 +1554,7 @@ %D equals strutdepth. \unexpanded\def\topskippedbox - {\hbox\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox} + {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox} \def\syst_boxes_topskippedbox_finish {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}% @@ -1606,22 +1610,22 @@ \unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen {\bgroup - \setbox0\vpack to \vsize + \setbox\scratchboxone\vpack to \vsize \bgroup \dontcomplain \forgetall - \setbox0\hbox{\vrule\s!width \zeropoint#1}% - \setbox2\vbox{\hrule\s!height\zeropoint#1}% - \advance\vsize \ht2 - \advance\hsize \wd0 + \setbox\scratchboxone\hpack{\vrule\s!width \zeropoint#1}% + \setbox\scratchboxtwo\vpack{\hrule\s!height\zeropoint#1}% + \advance\vsize \ht\scratchboxtwo + \advance\hsize \wd\scratchboxone \vpack to \vsize \bgroup - \vskip-\ht2 + \vskip-\ht\scratchboxtwo \vss \hpack to \hsize \bgroup \dowithnextbox - {\hskip-\wd0 + {\hskip-\wd\scratchboxone \hss \box\nextbox \hss @@ -1629,14 +1633,13 @@ \vss \egroup \egroup - \wd0\hsize - \ht0\vsize - \box0 + \wd\scratchboxone\hsize + \ht\scratchboxone\vsize + \box\scratchboxone \egroup} \hbox} -%D For those who don't want to deal with \type {\hsize} -%D and \type {\vsize}, we have: +%D For those who don't want to deal with \type {\hsize} and \type {\vsize}, we have: %D %D \starttyping %D \centerednextbox width 2bp height 2bp @@ -1670,9 +1673,9 @@ {\bgroup \dowithnextbox {\setlocalhsize - \setbox\scratchbox\hbox{\vrule\s!width \zeropoint#1}% + \setbox\scratchbox\hpack{\vrule\s!width \zeropoint#1}% \ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi - \setbox\scratchbox\vbox{\hrule\s!height\zeropoint#1}% + \setbox\scratchbox\vpack{\hrule\s!height\zeropoint#1}% \ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi \vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}% \egroup}% @@ -1764,7 +1767,7 @@ {\dorecurse\rigidcolumns {\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen \dp\scratchbox\openstrutdepth - \setbox\scratchbox\normalvtop + \setbox\scratchbox\vtop \ifalignrigidcolumns to \ifstretchrigidcolumns\vsize\else\scratchdimen\fi \fi @@ -1874,21 +1877,21 @@ \unexpanded\def\convertvboxtohbox {\makehboxofhboxes - \setbox0\hbox{\unhbox0 \removehboxes}% - \noindent\unhbox0\par} + \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack + \noindent\unhbox\scratchboxone\par} \unexpanded\def\makehboxofhboxes - {\setbox0\emptyhbox - \loop % \doloop { .. \exitloop .. } - \setbox2\lastbox - \ifhbox2 - \setbox0\hbox{\box2\unhbox0}% + {\setbox\scratchboxone\emptyhbox + \loop % \doloop { .. \exitloop .. } + \setbox\scratchboxtwo\lastbox + \ifhbox\scratchboxtwo + \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}% \repeat} \unexpanded\def\removehboxes - {\setbox0\lastbox - \ifhbox0 - {\removehboxes}\unhbox0 + {\setbox\scratchboxone\lastbox + \ifhbox\scratchboxone + {\removehboxes}\unhbox\scratchboxone \fi} % And one special for notes: @@ -1947,7 +1950,7 @@ \doloop {\setbox\hhbox\vsplit\unhhedbox to \lineheight \ifvoid\unhhedbox - \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}% + \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}% \hpack \fi \ht\hhbox\strutht \dp\hhbox\strutdp @@ -2129,7 +2132,27 @@ %D %D \leavevmode\getbuffer +\def\boxisempty#1% + {\ifdim\wd#1=\zeropoint + \ifdim\ht#1=\zeropoint + \ifdim\dp#1=\zeropoint + \zerocount + \else + \plusone + \fi + \else + \plusone + \fi + \else + \plusone + \fi} + \def\syst_boxes_overlay_process + {\ifcase\boxisempty\nextbox\else + \syst_boxes_overlay_process_indeed + \fi} + +\def\syst_boxes_overlay_process_indeed {%\removeunwantedspaces % already done \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi \ifdim\ht\nextbox>\ht\processbox @@ -2198,9 +2221,9 @@ \unexpanded\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter} \unexpanded\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright } -\unexpanded\def\ltop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedleft } -\unexpanded\def\ctop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedcenter} -\unexpanded\def\rtop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedright } +\unexpanded\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft } +\unexpanded\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter} +\unexpanded\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright } %D The alternatives \type {\tbox} and \type {\bbox} can be used %D to properly align boxes, like in: @@ -2222,8 +2245,8 @@ %D %D \getbuffer -\unexpanded\def\tbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} -\unexpanded\def\bbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} +\unexpanded\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} +\unexpanded\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} \def\syst_boxes_tbox_finish {\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax @@ -2289,7 +2312,7 @@ {\ifx\next\bgroup \expanded{\egroup#1 to \the\sizeofbox}% \else - \@EA\afterassignment\@EA\docommand\@EA\scratchdimen + \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen \fi}% \docommand} @@ -2337,7 +2360,7 @@ \newbox\fakedboxcursor -\setbox\fakedboxcursor\hbox +\setbox\fakedboxcursor\hpack {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} \unexpanded\def\boxcursor % overloaded in core-vis @@ -2723,7 +2746,7 @@ % vcenter in text, we kunnen vcenter overloaden \unexpanded\def\halfwaybox - {\hbox\bgroup + {\hpack\bgroup \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox} \def\syst_boxes_halfwaybox_finish @@ -2732,7 +2755,7 @@ \egroup} \unexpanded\def\depthonlybox - {\vtop\bgroup + {\tpack\bgroup \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox} \def\syst_boxes_depthonlybox_finish @@ -2747,12 +2770,7 @@ %D And even rawer: - \let\naturalvtop \normalvtop - \let\naturalvcenter\normalvtop -\unexpanded\def\naturalhbox {\hbox dir TLT} -\unexpanded\def\naturalvbox {\vbox dir TLT} -\unexpanded\def\naturalhpack {\hpack dir TLT} -\unexpanded\def\naturalvpack {\vpack dir TLT} +\let\naturalvcenter\normalvtop % will go away %D \macros %D {vcenter} @@ -2764,7 +2782,7 @@ \dowithnextboxcs\syst_boxes_vcenter_finish\vbox} \def\syst_boxes_vcenter_finish - {\hpack{\normalstartimath\normalvcenter{\box\nextbox}\normalstopimath}% + {\hpack{\normalstartimath\vcenter{\box\nextbox}\normalstopimath}% \egroup} % could be \everymathematics @@ -2780,7 +2798,7 @@ %D A not so well unhboxable box can be made with: \unexpanded\def\frozenhbox - {\hbox\bgroup + {\hpack\bgroup \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox} \def\syst_boxes_frozenhbox_finish @@ -2837,19 +2855,19 @@ \unexpanded\def\spreadhbox#1% rebuilds \hbox{} {\bgroup \ifhbox#1\relax - \setbox2\emptybox + \setbox\scratchboxtwo\emptybox \unhbox#1% \doloop {\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip - \setbox0\lastbox - \ifvoid0 + \setbox\scratchboxone\lastbox + \ifvoid\scratchboxone \exitloop \else - \setbox2\hbox - {\ifhbox0 \spreadhbox0\else\box0\fi - \ifvoid2 \else\hss\unhbox2\fi}% + \setbox\scratchboxtwo\hbox + {\ifhbox\scratchboxone \spreadhbox\scratchboxone\else\box\scratchboxone\fi + \ifvoid\scratchboxtwo \else\hss\unhbox\scratchboxtwo\fi}% \fi}% - \ifvoid2\else\unhbox2\fi + \ifvoid\scratchboxtwo\else\unhbox\scratchboxtwo\fi \else \box#1% \fi @@ -2974,6 +2992,24 @@ % \unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox} % \unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop} +%D This one keeps dimensions and sets the shift field (and so it's more for testing +%D than for real usage): + +\unexpanded\def\shiftbox{\clf_shiftbox} + +%D This one has been moved from a 2 decade old file. It makes something boxed +%D sit on the baseline. + +\unexpanded\def\linebox + {\hpack\bgroup\dowithnextbox + {\scratchdimen\dimexpr\dimexpr\htdp\nextbox-\lineheight\relax/2+\dp\strutbox\relax + \setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}% + \ht\nextbox\ht\strutbox + \dp\nextbox\dp\strutbox + \box\nextbox + \egroup} + \hbox} + \protect \endinput % a bit of test code: diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv index 42a0aa37cf8..277f2b7cac2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-dir.mkiv @@ -11,40 +11,44 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D We no longer have the \ETEX\ direction primitives. - \unprotect -% \expanded{\defineactivecharacter \number"2000E} {\textdir TRT\relax} -% \expanded{\defineactivecharacter \number"2000F} {\textdir TLT\relax} +\chardef\directionlefttoright\zerocount +\chardef\directionrighttoleft\plusone -%D As we have less directions now we can use something +\edef\??bdir{\ifdefined\bodydir bdir\else direction\fi} -% \chardef\@@D@@TLT0 -% \chardef\@@D@@TRT1 -% \chardef\@@D@@RTT0 -% \chardef\@@D@@LRL1 -% -% \def\thetextdir{\csname @@D@@\the\textdir\endcsname} -% -% \ifnum\thetextdir=0 L\else R\fi \textdir TRT \ifnum\thetextdir=0 L\else R\fi +\unexpanded\edef\naturalhbox {\hbox \??bdir\directionlefttoright} +\unexpanded\edef\naturalvbox {\vbox \??bdir\directionlefttoright} +\unexpanded\edef\naturalvtop {\vtop \??bdir\directionlefttoright} +\unexpanded\edef\naturalhpack {\hpack \??bdir\directionlefttoright} +\unexpanded\edef\naturalvpack {\vpack \??bdir\directionlefttoright} +\unexpanded\edef\naturaltpack {\tpack \??bdir\directionlefttoright} -\unexpanded\def\showdirsinmargin - {\inleft{\normalexpanded{\noexpand\hbox dir TLT{\ttxx[\the\pardir,\the\textdir]}}}} +\unexpanded\edef\reversehbox {\hbox \??bdir\directionrighttoleft} +\unexpanded\edef\reversevbox {\vbox \??bdir\directionrighttoleft} +\unexpanded\edef\reversevtop {\vtop \??bdir\directionrighttoleft} +\unexpanded\edef\reversehpack {\hpack \??bdir\directionrighttoleft} +\unexpanded\edef\reversevpack {\vpack \??bdir\directionrighttoleft} +\unexpanded\edef\reversetpack {\tpack \??bdir\directionrighttoleft} -\bgroup - \catcode`L=\othercatcode \gdef\istltdir#1#2#3{\if#2L0\else1\fi} - \catcode`R=\othercatcode \gdef\istrtdir#1#2#3{\if#2R0\else1\fi} -\egroup +\ifdefined\bodydir + \let\bodydir \undefined \let\normalbodydir \undefined + \let\bodydirection\undefined \let\normalbodydirection\undefined +\fi -\def\istlttextdir{\expandafter\istltdir\the\textdir} -\def\istrttextdir{\expandafter\istrtdir\the\textdir} +\ifdefined\pagedir + \let\pagedir \undefined \let\normalpagedir \undefined + \let\pagedirection\undefined \let\normalpagedirection\undefined +\fi -\def\istltpardir {\expandafter\istltdir\the\pardir } -\def\istrtpardir {\expandafter\istrtdir\the\pardir } +% \expanded{\defineactivecharacter \number"2000E} {\textdirection\directionrighttoleft\relax} +% \expanded{\defineactivecharacter \number"2000F} {\textdirection\directionlefttoright\relax} -% \ifcase\istlttextdir Y\else N\fi -% \ifcase\istltpardir Y\else N\fi -% \ifcase\istltdir TRT\relax Y\else N\fi +\def\syst_direction_string#1{\ifcase#1=\plusone r2l\else l2r\fi} + +\unexpanded\def\showdirsinmargin + {\normalexpanded{\inleft{\naturalhbox + {\ttxx[\syst_direction_string\pardirection,\syst_direction_string\textdirection]}}}} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv b/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv index 176233ae5b6..f72a0ff89dc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-mat.mkiv @@ -179,7 +179,7 @@ \popmacro\dodimensionsignal} \unexpanded\def\nodimension#1% - {\unskip#1\global\let\dodimensionsignal\relax} + {\unskip#1\glet\dodimensionsignal\relax} %D \macros %D {cramped} diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-emj.lua b/Master/texmf-dist/tex/context/base/mkiv/symb-emj.lua index 3075e09854f..d6e2aebea6f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-emj.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-emj.lua @@ -19,32 +19,27 @@ local protectglyphs = nodes.handlers.protectglyphs local tonodes = nodes.tonodes local currentfont = font.current --- fast enough, no need to memoize - -local glyph_code = nodes.nodecodes.glyph -local remove_node = nodes.remove -local getid = nodes.getid -local getnext = nodes.getnext -local getchar = nodes.getchar +local nuts = nodes.nuts +local tonode = nuts.tonode +local tonut = nuts.tonut +local remove_node = nuts.remove +local isglyph = nuts.isglyph local function removemodifiers(head) + local head = tonut(head) local current = head while current do - if getid(current) == glyph_code then - local char = getchar(current) -- using categories is too much - if char == 0x200D or (char >= 0x1F3FB and char <= 0x1F3FF) then - head, current = remove_node(head,current,true) - else - current = getnext(current) - end + local char, id = isglyph(current) + if char and char == 0x200D or (char >= 0x1F3FB and char <= 0x1F3FF) then + head, current = remove_node(head,current,true) else current = getnext(current) end end - return head + return tonode(head) end --- attributes +-- fast enough, no need to memoize, maybe use attributes local function checkedemoji(name,id) local str = resolvedemoji(name) diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-fontawesome.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-fontawesome.mkiv index 145adc46c04..c638998ab75 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-fontawesome.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-fontawesome.mkiv @@ -10,749 +10,786 @@ \definefontsynonym [FontAwesome] [file:FontAwesome.otf] %def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\utfchar{0x#1}}} -\def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\tochar{x:#1}}} +\def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\tochar{n:#1}}} -\startsymbolset [fontawesome] +\startsymbolset [fontawesome] [font=fontawesome] - \definesymbol [500px] [\FontAwesomeSymbol{f26e}] - \definesymbol [adjust] [\FontAwesomeSymbol{f042}] - \definesymbol [adn] [\FontAwesomeSymbol{f170}] - \definesymbol [align-center] [\FontAwesomeSymbol{f037}] - \definesymbol [align-justify] [\FontAwesomeSymbol{f039}] - \definesymbol [align-left] [\FontAwesomeSymbol{f036}] - \definesymbol [align-right] [\FontAwesomeSymbol{f038}] - \definesymbol [amazon] [\FontAwesomeSymbol{f270}] - \definesymbol [ambulance] [\FontAwesomeSymbol{f0f9}] - \definesymbol [american-sign-language-interpreting] [\FontAwesomeSymbol{f2a3}] - \definesymbol [anchor] [\FontAwesomeSymbol{f13d}] - \definesymbol [android] [\FontAwesomeSymbol{f17b}] - \definesymbol [angellist] [\FontAwesomeSymbol{f209}] - \definesymbol [angle-double-down] [\FontAwesomeSymbol{f103}] - \definesymbol [angle-double-left] [\FontAwesomeSymbol{f100}] - \definesymbol [angle-double-right] [\FontAwesomeSymbol{f101}] - \definesymbol [angle-double-up] [\FontAwesomeSymbol{f102}] - \definesymbol [angle-down] [\FontAwesomeSymbol{f107}] - \definesymbol [angle-left] [\FontAwesomeSymbol{f104}] - \definesymbol [angle-right] [\FontAwesomeSymbol{f105}] - \definesymbol [angle-up] [\FontAwesomeSymbol{f106}] - \definesymbol [apple] [\FontAwesomeSymbol{f179}] - \definesymbol [archive] [\FontAwesomeSymbol{f187}] - \definesymbol [area-chart] [\FontAwesomeSymbol{f1fe}] - \definesymbol [arrow-circle-down] [\FontAwesomeSymbol{f0ab}] - \definesymbol [arrow-circle-left] [\FontAwesomeSymbol{f0a8}] - \definesymbol [arrow-circle-o-down] [\FontAwesomeSymbol{f01a}] - \definesymbol [arrow-circle-o-left] [\FontAwesomeSymbol{f190}] - \definesymbol [arrow-circle-o-right] [\FontAwesomeSymbol{f18e}] - \definesymbol [arrow-circle-o-up] [\FontAwesomeSymbol{f01b}] - \definesymbol [arrow-circle-right] [\FontAwesomeSymbol{f0a9}] - \definesymbol [arrow-circle-up] [\FontAwesomeSymbol{f0aa}] - \definesymbol [arrow-down] [\FontAwesomeSymbol{f063}] - \definesymbol [arrow-left] [\FontAwesomeSymbol{f060}] - \definesymbol [arrow-right] [\FontAwesomeSymbol{f061}] - \definesymbol [arrow-up] [\FontAwesomeSymbol{f062}] - \definesymbol [arrows] [\FontAwesomeSymbol{f047}] - \definesymbol [arrows-alt] [\FontAwesomeSymbol{f0b2}] - \definesymbol [arrows-h] [\FontAwesomeSymbol{f07e}] - \definesymbol [arrows-v] [\FontAwesomeSymbol{f07d}] - \definesymbol [asl-interpreting] [\FontAwesomeSymbol{f2a3}] - \definesymbol [assistive-listening-systems] [\FontAwesomeSymbol{f2a2}] - \definesymbol [asterisk] [\FontAwesomeSymbol{f069}] - \definesymbol [at] [\FontAwesomeSymbol{f1fa}] - \definesymbol [audio-description] [\FontAwesomeSymbol{f29e}] - \definesymbol [automobile] [\FontAwesomeSymbol{f1b9}] - \definesymbol [backward] [\FontAwesomeSymbol{f04a}] - \definesymbol [balance-scale] [\FontAwesomeSymbol{f24e}] - \definesymbol [ban] [\FontAwesomeSymbol{f05e}] - \definesymbol [bank] [\FontAwesomeSymbol{f19c}] - \definesymbol [bar-chart] [\FontAwesomeSymbol{f080}] - \definesymbol [bar-chart-o] [\FontAwesomeSymbol{f080}] - \definesymbol [barcode] [\FontAwesomeSymbol{f02a}] - \definesymbol [bars] [\FontAwesomeSymbol{f0c9}] - \definesymbol [battery-0] [\FontAwesomeSymbol{f244}] - \definesymbol [battery-1] [\FontAwesomeSymbol{f243}] - \definesymbol [battery-2] [\FontAwesomeSymbol{f242}] - \definesymbol [battery-3] [\FontAwesomeSymbol{f241}] - \definesymbol [battery-4] [\FontAwesomeSymbol{f240}] - \definesymbol [battery-empty] [\FontAwesomeSymbol{f244}] - \definesymbol [battery-full] [\FontAwesomeSymbol{f240}] - \definesymbol [battery-half] [\FontAwesomeSymbol{f242}] - \definesymbol [battery-quarter] [\FontAwesomeSymbol{f243}] - \definesymbol [battery-three-quarters] [\FontAwesomeSymbol{f241}] - \definesymbol [bed] [\FontAwesomeSymbol{f236}] - \definesymbol [beer] [\FontAwesomeSymbol{f0fc}] - \definesymbol [behance] [\FontAwesomeSymbol{f1b4}] - \definesymbol [behance-square] [\FontAwesomeSymbol{f1b5}] - \definesymbol [bell] [\FontAwesomeSymbol{f0f3}] - \definesymbol [bell-o] [\FontAwesomeSymbol{f0a2}] - \definesymbol [bell-slash] [\FontAwesomeSymbol{f1f6}] - \definesymbol [bell-slash-o] [\FontAwesomeSymbol{f1f7}] - \definesymbol [bicycle] [\FontAwesomeSymbol{f206}] - \definesymbol [binoculars] [\FontAwesomeSymbol{f1e5}] - \definesymbol [birthday-cake] [\FontAwesomeSymbol{f1fd}] - \definesymbol [bitbucket] [\FontAwesomeSymbol{f171}] - \definesymbol [bitbucket-square] [\FontAwesomeSymbol{f172}] - \definesymbol [bitcoin] [\FontAwesomeSymbol{f15a}] - \definesymbol [black-tie] [\FontAwesomeSymbol{f27e}] - \definesymbol [blind] [\FontAwesomeSymbol{f29d}] - \definesymbol [bluetooth] [\FontAwesomeSymbol{f293}] - \definesymbol [bluetooth-b] [\FontAwesomeSymbol{f294}] - \definesymbol [bold] [\FontAwesomeSymbol{f032}] - \definesymbol [bolt] [\FontAwesomeSymbol{f0e7}] - \definesymbol [bomb] [\FontAwesomeSymbol{f1e2}] - \definesymbol [book] [\FontAwesomeSymbol{f02d}] - \definesymbol [bookmark] [\FontAwesomeSymbol{f02e}] - \definesymbol [bookmark-o] [\FontAwesomeSymbol{f097}] - \definesymbol [braille] [\FontAwesomeSymbol{f2a1}] - \definesymbol [briefcase] [\FontAwesomeSymbol{f0b1}] - \definesymbol [btc] [\FontAwesomeSymbol{f15a}] - \definesymbol [bug] [\FontAwesomeSymbol{f188}] - \definesymbol [building] [\FontAwesomeSymbol{f1ad}] - \definesymbol [building-o] [\FontAwesomeSymbol{f0f7}] - \definesymbol [bullhorn] [\FontAwesomeSymbol{f0a1}] - \definesymbol [bullseye] [\FontAwesomeSymbol{f140}] - \definesymbol [bus] [\FontAwesomeSymbol{f207}] - \definesymbol [buysellads] [\FontAwesomeSymbol{f20d}] - \definesymbol [cab] [\FontAwesomeSymbol{f1ba}] - \definesymbol [calculator] [\FontAwesomeSymbol{f1ec}] - \definesymbol [calendar] [\FontAwesomeSymbol{f073}] - \definesymbol [calendar-check-o] [\FontAwesomeSymbol{f274}] - \definesymbol [calendar-minus-o] [\FontAwesomeSymbol{f272}] - \definesymbol [calendar-o] [\FontAwesomeSymbol{f133}] - \definesymbol [calendar-plus-o] [\FontAwesomeSymbol{f271}] - \definesymbol [calendar-times-o] [\FontAwesomeSymbol{f273}] - \definesymbol [camera] [\FontAwesomeSymbol{f030}] - \definesymbol [camera-retro] [\FontAwesomeSymbol{f083}] - \definesymbol [car] [\FontAwesomeSymbol{f1b9}] - \definesymbol [caret-down] [\FontAwesomeSymbol{f0d7}] - \definesymbol [caret-left] [\FontAwesomeSymbol{f0d9}] - \definesymbol [caret-right] [\FontAwesomeSymbol{f0da}] - \definesymbol [caret-square-o-down] [\FontAwesomeSymbol{f150}] - \definesymbol [caret-square-o-left] [\FontAwesomeSymbol{f191}] - \definesymbol [caret-square-o-right] [\FontAwesomeSymbol{f152}] - \definesymbol [caret-square-o-up] [\FontAwesomeSymbol{f151}] - \definesymbol [caret-up] [\FontAwesomeSymbol{f0d8}] - \definesymbol [cart-arrow-down] [\FontAwesomeSymbol{f218}] - \definesymbol [cart-plus] [\FontAwesomeSymbol{f217}] - \definesymbol [cc] [\FontAwesomeSymbol{f20a}] - \definesymbol [cc-amex] [\FontAwesomeSymbol{f1f3}] - \definesymbol [cc-diners-club] [\FontAwesomeSymbol{f24c}] - \definesymbol [cc-discover] [\FontAwesomeSymbol{f1f2}] - \definesymbol [cc-jcb] [\FontAwesomeSymbol{f24b}] - \definesymbol [cc-mastercard] [\FontAwesomeSymbol{f1f1}] - \definesymbol [cc-paypal] [\FontAwesomeSymbol{f1f4}] - \definesymbol [cc-stripe] [\FontAwesomeSymbol{f1f5}] - \definesymbol [cc-visa] [\FontAwesomeSymbol{f1f0}] - \definesymbol [certificate] [\FontAwesomeSymbol{f0a3}] - \definesymbol [chain] [\FontAwesomeSymbol{f0c1}] - \definesymbol [chain-broken] [\FontAwesomeSymbol{f127}] - \definesymbol [check] [\FontAwesomeSymbol{f00c}] - \definesymbol [check-circle] [\FontAwesomeSymbol{f058}] - \definesymbol [check-circle-o] [\FontAwesomeSymbol{f05d}] - \definesymbol [check-square] [\FontAwesomeSymbol{f14a}] - \definesymbol [check-square-o] [\FontAwesomeSymbol{f046}] - \definesymbol [chevron-circle-down] [\FontAwesomeSymbol{f13a}] - \definesymbol [chevron-circle-left] [\FontAwesomeSymbol{f137}] - \definesymbol [chevron-circle-right] [\FontAwesomeSymbol{f138}] - \definesymbol [chevron-circle-up] [\FontAwesomeSymbol{f139}] - \definesymbol [chevron-down] [\FontAwesomeSymbol{f078}] - \definesymbol [chevron-left] [\FontAwesomeSymbol{f053}] - \definesymbol [chevron-right] [\FontAwesomeSymbol{f054}] - \definesymbol [chevron-up] [\FontAwesomeSymbol{f077}] - \definesymbol [child] [\FontAwesomeSymbol{f1ae}] - \definesymbol [chrome] [\FontAwesomeSymbol{f268}] - \definesymbol [circle] [\FontAwesomeSymbol{f111}] - \definesymbol [circle-o] [\FontAwesomeSymbol{f10c}] - \definesymbol [circle-o-notch] [\FontAwesomeSymbol{f1ce}] - \definesymbol [circle-thin] [\FontAwesomeSymbol{f1db}] - \definesymbol [clipboard] [\FontAwesomeSymbol{f0ea}] - \definesymbol [clock-o] [\FontAwesomeSymbol{f017}] - \definesymbol [clone] [\FontAwesomeSymbol{f24d}] - \definesymbol [close] [\FontAwesomeSymbol{f00d}] - \definesymbol [cloud] [\FontAwesomeSymbol{f0c2}] - \definesymbol [cloud-download] [\FontAwesomeSymbol{f0ed}] - \definesymbol [cloud-upload] [\FontAwesomeSymbol{f0ee}] - \definesymbol [cny] [\FontAwesomeSymbol{f157}] - \definesymbol [code] [\FontAwesomeSymbol{f121}] - \definesymbol [code-fork] [\FontAwesomeSymbol{f126}] - \definesymbol [codepen] [\FontAwesomeSymbol{f1cb}] - \definesymbol [codiepie] [\FontAwesomeSymbol{f284}] - \definesymbol [coffee] [\FontAwesomeSymbol{f0f4}] - \definesymbol [cog] [\FontAwesomeSymbol{f013}] - \definesymbol [cogs] [\FontAwesomeSymbol{f085}] - \definesymbol [columns] [\FontAwesomeSymbol{f0db}] - \definesymbol [comment] [\FontAwesomeSymbol{f075}] - \definesymbol [comment-o] [\FontAwesomeSymbol{f0e5}] - \definesymbol [commenting] [\FontAwesomeSymbol{f27a}] - \definesymbol [commenting-o] [\FontAwesomeSymbol{f27b}] - \definesymbol [comments] [\FontAwesomeSymbol{f086}] - \definesymbol [comments-o] [\FontAwesomeSymbol{f0e6}] - \definesymbol [compass] [\FontAwesomeSymbol{f14e}] - \definesymbol [compress] [\FontAwesomeSymbol{f066}] - \definesymbol [connectdevelop] [\FontAwesomeSymbol{f20e}] - \definesymbol [contao] [\FontAwesomeSymbol{f26d}] - \definesymbol [copy] [\FontAwesomeSymbol{f0c5}] - \definesymbol [copyright] [\FontAwesomeSymbol{f1f9}] - \definesymbol [creative-commons] [\FontAwesomeSymbol{f25e}] - \definesymbol [credit-card] [\FontAwesomeSymbol{f09d}] - \definesymbol [credit-card-alt] [\FontAwesomeSymbol{f283}] - \definesymbol [crop] [\FontAwesomeSymbol{f125}] - \definesymbol [crosshairs] [\FontAwesomeSymbol{f05b}] - \definesymbol [css3] [\FontAwesomeSymbol{f13c}] - \definesymbol [cube] [\FontAwesomeSymbol{f1b2}] - \definesymbol [cubes] [\FontAwesomeSymbol{f1b3}] - \definesymbol [cut] [\FontAwesomeSymbol{f0c4}] - \definesymbol [cutlery] [\FontAwesomeSymbol{f0f5}] - \definesymbol [dashboard] [\FontAwesomeSymbol{f0e4}] - \definesymbol [dashcube] [\FontAwesomeSymbol{f210}] - \definesymbol [database] [\FontAwesomeSymbol{f1c0}] - \definesymbol [deaf] [\FontAwesomeSymbol{f2a4}] - \definesymbol [deafness] [\FontAwesomeSymbol{f2a4}] - \definesymbol [dedent] [\FontAwesomeSymbol{f03b}] - \definesymbol [delicious] [\FontAwesomeSymbol{f1a5}] - \definesymbol [desktop] [\FontAwesomeSymbol{f108}] - \definesymbol [deviantart] [\FontAwesomeSymbol{f1bd}] - \definesymbol [diamond] [\FontAwesomeSymbol{f219}] - \definesymbol [digg] [\FontAwesomeSymbol{f1a6}] - \definesymbol [dollar] [\FontAwesomeSymbol{f155}] - \definesymbol [dot-circle-o] [\FontAwesomeSymbol{f192}] - \definesymbol [download] [\FontAwesomeSymbol{f019}] - \definesymbol [dribbble] [\FontAwesomeSymbol{f17d}] - \definesymbol [dropbox] [\FontAwesomeSymbol{f16b}] - \definesymbol [drupal] [\FontAwesomeSymbol{f1a9}] - \definesymbol [edge] [\FontAwesomeSymbol{f282}] - \definesymbol [edit] [\FontAwesomeSymbol{f044}] - \definesymbol [eject] [\FontAwesomeSymbol{f052}] - \definesymbol [ellipsis-h] [\FontAwesomeSymbol{f141}] - \definesymbol [ellipsis-v] [\FontAwesomeSymbol{f142}] - \definesymbol [empire] [\FontAwesomeSymbol{f1d1}] - \definesymbol [envelope] [\FontAwesomeSymbol{f0e0}] - \definesymbol [envelope-o] [\FontAwesomeSymbol{f003}] - \definesymbol [envelope-square] [\FontAwesomeSymbol{f199}] - \definesymbol [envira] [\FontAwesomeSymbol{f299}] - \definesymbol [eraser] [\FontAwesomeSymbol{f12d}] - \definesymbol [eur] [\FontAwesomeSymbol{f153}] - \definesymbol [euro] [\FontAwesomeSymbol{f153}] - \definesymbol [exchange] [\FontAwesomeSymbol{f0ec}] - \definesymbol [exclamation] [\FontAwesomeSymbol{f12a}] - \definesymbol [exclamation-circle] [\FontAwesomeSymbol{f06a}] - \definesymbol [exclamation-triangle] [\FontAwesomeSymbol{f071}] - \definesymbol [expand] [\FontAwesomeSymbol{f065}] - \definesymbol [expeditedssl] [\FontAwesomeSymbol{f23e}] - \definesymbol [external-link] [\FontAwesomeSymbol{f08e}] - \definesymbol [external-link-square] [\FontAwesomeSymbol{f14c}] - \definesymbol [eye] [\FontAwesomeSymbol{f06e}] - \definesymbol [eye-slash] [\FontAwesomeSymbol{f070}] - \definesymbol [eyedropper] [\FontAwesomeSymbol{f1fb}] - \definesymbol [fa] [\FontAwesomeSymbol{f2b4}] - \definesymbol [facebook] [\FontAwesomeSymbol{f09a}] - \definesymbol [facebook-f] [\FontAwesomeSymbol{f09a}] - \definesymbol [facebook-official] [\FontAwesomeSymbol{f230}] - \definesymbol [facebook-square] [\FontAwesomeSymbol{f082}] - \definesymbol [fast-backward] [\FontAwesomeSymbol{f049}] - \definesymbol [fast-forward] [\FontAwesomeSymbol{f050}] - \definesymbol [fax] [\FontAwesomeSymbol{f1ac}] - \definesymbol [feed] [\FontAwesomeSymbol{f09e}] - \definesymbol [female] [\FontAwesomeSymbol{f182}] - \definesymbol [fighter-jet] [\FontAwesomeSymbol{f0fb}] - \definesymbol [file] [\FontAwesomeSymbol{f15b}] - \definesymbol [file-archive-o] [\FontAwesomeSymbol{f1c6}] - \definesymbol [file-audio-o] [\FontAwesomeSymbol{f1c7}] - \definesymbol [file-code-o] [\FontAwesomeSymbol{f1c9}] - \definesymbol [file-excel-o] [\FontAwesomeSymbol{f1c3}] - \definesymbol [file-image-o] [\FontAwesomeSymbol{f1c5}] - \definesymbol [file-movie-o] [\FontAwesomeSymbol{f1c8}] - \definesymbol [file-o] [\FontAwesomeSymbol{f016}] - \definesymbol [file-pdf-o] [\FontAwesomeSymbol{f1c1}] - \definesymbol [file-photo-o] [\FontAwesomeSymbol{f1c5}] - \definesymbol [file-picture-o] [\FontAwesomeSymbol{f1c5}] - \definesymbol [file-powerpoint-o] [\FontAwesomeSymbol{f1c4}] - \definesymbol [file-sound-o] [\FontAwesomeSymbol{f1c7}] - \definesymbol [file-text] [\FontAwesomeSymbol{f15c}] - \definesymbol [file-text-o] [\FontAwesomeSymbol{f0f6}] - \definesymbol [file-video-o] [\FontAwesomeSymbol{f1c8}] - \definesymbol [file-word-o] [\FontAwesomeSymbol{f1c2}] - \definesymbol [file-zip-o] [\FontAwesomeSymbol{f1c6}] - \definesymbol [files-o] [\FontAwesomeSymbol{f0c5}] - \definesymbol [film] [\FontAwesomeSymbol{f008}] - \definesymbol [filter] [\FontAwesomeSymbol{f0b0}] - \definesymbol [fire] [\FontAwesomeSymbol{f06d}] - \definesymbol [fire-extinguisher] [\FontAwesomeSymbol{f134}] - \definesymbol [firefox] [\FontAwesomeSymbol{f269}] - \definesymbol [first-order] [\FontAwesomeSymbol{f2b0}] - \definesymbol [flag] [\FontAwesomeSymbol{f024}] - \definesymbol [flag-checkered] [\FontAwesomeSymbol{f11e}] - \definesymbol [flag-o] [\FontAwesomeSymbol{f11d}] - \definesymbol [flash] [\FontAwesomeSymbol{f0e7}] - \definesymbol [flask] [\FontAwesomeSymbol{f0c3}] - \definesymbol [flickr] [\FontAwesomeSymbol{f16e}] - \definesymbol [floppy-o] [\FontAwesomeSymbol{f0c7}] - \definesymbol [folder] [\FontAwesomeSymbol{f07b}] - \definesymbol [folder-o] [\FontAwesomeSymbol{f114}] - \definesymbol [folder-open] [\FontAwesomeSymbol{f07c}] - \definesymbol [folder-open-o] [\FontAwesomeSymbol{f115}] - \definesymbol [font] [\FontAwesomeSymbol{f031}] - \definesymbol [font-awesome] [\FontAwesomeSymbol{f2b4}] - \definesymbol [fonticons] [\FontAwesomeSymbol{f280}] - \definesymbol [fort-awesome] [\FontAwesomeSymbol{f286}] - \definesymbol [forumbee] [\FontAwesomeSymbol{f211}] - \definesymbol [forward] [\FontAwesomeSymbol{f04e}] - \definesymbol [foursquare] [\FontAwesomeSymbol{f180}] - \definesymbol [frown-o] [\FontAwesomeSymbol{f119}] - \definesymbol [futbol-o] [\FontAwesomeSymbol{f1e3}] - \definesymbol [gamepad] [\FontAwesomeSymbol{f11b}] - \definesymbol [gavel] [\FontAwesomeSymbol{f0e3}] - \definesymbol [gbp] [\FontAwesomeSymbol{f154}] - \definesymbol [ge] [\FontAwesomeSymbol{f1d1}] - \definesymbol [gear] [\FontAwesomeSymbol{f013}] - \definesymbol [gears] [\FontAwesomeSymbol{f085}] - \definesymbol [genderless] [\FontAwesomeSymbol{f22d}] - \definesymbol [get-pocket] [\FontAwesomeSymbol{f265}] - \definesymbol [gg] [\FontAwesomeSymbol{f260}] - \definesymbol [gg-circle] [\FontAwesomeSymbol{f261}] - \definesymbol [gift] [\FontAwesomeSymbol{f06b}] - \definesymbol [git] [\FontAwesomeSymbol{f1d3}] - \definesymbol [git-square] [\FontAwesomeSymbol{f1d2}] - \definesymbol [github] [\FontAwesomeSymbol{f09b}] - \definesymbol [github-alt] [\FontAwesomeSymbol{f113}] - \definesymbol [github-square] [\FontAwesomeSymbol{f092}] - \definesymbol [gitlab] [\FontAwesomeSymbol{f296}] - \definesymbol [gittip] [\FontAwesomeSymbol{f184}] - \definesymbol [glass] [\FontAwesomeSymbol{f000}] - \definesymbol [glide] [\FontAwesomeSymbol{f2a5}] - \definesymbol [glide-g] [\FontAwesomeSymbol{f2a6}] - \definesymbol [globe] [\FontAwesomeSymbol{f0ac}] - \definesymbol [google] [\FontAwesomeSymbol{f1a0}] - \definesymbol [google-plus] [\FontAwesomeSymbol{f0d5}] - \definesymbol [google-plus-circle] [\FontAwesomeSymbol{f2b3}] - \definesymbol [google-plus-official] [\FontAwesomeSymbol{f2b3}] - \definesymbol [google-plus-square] [\FontAwesomeSymbol{f0d4}] - \definesymbol [google-wallet] [\FontAwesomeSymbol{f1ee}] - \definesymbol [graduation-cap] [\FontAwesomeSymbol{f19d}] - \definesymbol [gratipay] [\FontAwesomeSymbol{f184}] - \definesymbol [group] [\FontAwesomeSymbol{f0c0}] - \definesymbol [h-square] [\FontAwesomeSymbol{f0fd}] - \definesymbol [hacker-news] [\FontAwesomeSymbol{f1d4}] - \definesymbol [hand-grab-o] [\FontAwesomeSymbol{f255}] - \definesymbol [hand-lizard-o] [\FontAwesomeSymbol{f258}] - \definesymbol [hand-o-down] [\FontAwesomeSymbol{f0a7}] - \definesymbol [hand-o-left] [\FontAwesomeSymbol{f0a5}] - \definesymbol [hand-o-right] [\FontAwesomeSymbol{f0a4}] - \definesymbol [hand-o-up] [\FontAwesomeSymbol{f0a6}] - \definesymbol [hand-paper-o] [\FontAwesomeSymbol{f256}] - \definesymbol [hand-peace-o] [\FontAwesomeSymbol{f25b}] - \definesymbol [hand-pointer-o] [\FontAwesomeSymbol{f25a}] - \definesymbol [hand-rock-o] [\FontAwesomeSymbol{f255}] - \definesymbol [hand-scissors-o] [\FontAwesomeSymbol{f257}] - \definesymbol [hand-spock-o] [\FontAwesomeSymbol{f259}] - \definesymbol [hand-stop-o] [\FontAwesomeSymbol{f256}] - \definesymbol [hard-of-hearing] [\FontAwesomeSymbol{f2a4}] - \definesymbol [hashtag] [\FontAwesomeSymbol{f292}] - \definesymbol [hdd-o] [\FontAwesomeSymbol{f0a0}] - \definesymbol [header] [\FontAwesomeSymbol{f1dc}] - \definesymbol [headphones] [\FontAwesomeSymbol{f025}] - \definesymbol [heart] [\FontAwesomeSymbol{f004}] - \definesymbol [heart-o] [\FontAwesomeSymbol{f08a}] - \definesymbol [heartbeat] [\FontAwesomeSymbol{f21e}] - \definesymbol [history] [\FontAwesomeSymbol{f1da}] - \definesymbol [home] [\FontAwesomeSymbol{f015}] - \definesymbol [hospital-o] [\FontAwesomeSymbol{f0f8}] - \definesymbol [hotel] [\FontAwesomeSymbol{f236}] - \definesymbol [hourglass] [\FontAwesomeSymbol{f254}] - \definesymbol [hourglass-1] [\FontAwesomeSymbol{f251}] - \definesymbol [hourglass-2] [\FontAwesomeSymbol{f252}] - \definesymbol [hourglass-3] [\FontAwesomeSymbol{f253}] - \definesymbol [hourglass-end] [\FontAwesomeSymbol{f253}] - \definesymbol [hourglass-half] [\FontAwesomeSymbol{f252}] - \definesymbol [hourglass-o] [\FontAwesomeSymbol{f250}] - \definesymbol [hourglass-start] [\FontAwesomeSymbol{f251}] - \definesymbol [houzz] [\FontAwesomeSymbol{f27c}] - \definesymbol [html5] [\FontAwesomeSymbol{f13b}] - \definesymbol [i-cursor] [\FontAwesomeSymbol{f246}] - \definesymbol [ils] [\FontAwesomeSymbol{f20b}] - \definesymbol [image] [\FontAwesomeSymbol{f03e}] - \definesymbol [inbox] [\FontAwesomeSymbol{f01c}] - \definesymbol [indent] [\FontAwesomeSymbol{f03c}] - \definesymbol [industry] [\FontAwesomeSymbol{f275}] - \definesymbol [info] [\FontAwesomeSymbol{f129}] - \definesymbol [info-circle] [\FontAwesomeSymbol{f05a}] - \definesymbol [inr] [\FontAwesomeSymbol{f156}] - \definesymbol [instagram] [\FontAwesomeSymbol{f16d}] - \definesymbol [institution] [\FontAwesomeSymbol{f19c}] - \definesymbol [internet-explorer] [\FontAwesomeSymbol{f26b}] - \definesymbol [intersex] [\FontAwesomeSymbol{f224}] - \definesymbol [ioxhost] [\FontAwesomeSymbol{f208}] - \definesymbol [italic] [\FontAwesomeSymbol{f033}] - \definesymbol [joomla] [\FontAwesomeSymbol{f1aa}] - \definesymbol [jpy] [\FontAwesomeSymbol{f157}] - \definesymbol [jsfiddle] [\FontAwesomeSymbol{f1cc}] - \definesymbol [key] [\FontAwesomeSymbol{f084}] - \definesymbol [keyboard-o] [\FontAwesomeSymbol{f11c}] - \definesymbol [krw] [\FontAwesomeSymbol{f159}] - \definesymbol [language] [\FontAwesomeSymbol{f1ab}] - \definesymbol [laptop] [\FontAwesomeSymbol{f109}] - \definesymbol [lastfm] [\FontAwesomeSymbol{f202}] - \definesymbol [lastfm-square] [\FontAwesomeSymbol{f203}] - \definesymbol [leaf] [\FontAwesomeSymbol{f06c}] - \definesymbol [leanpub] [\FontAwesomeSymbol{f212}] - \definesymbol [legal] [\FontAwesomeSymbol{f0e3}] - \definesymbol [lemon-o] [\FontAwesomeSymbol{f094}] - \definesymbol [level-down] [\FontAwesomeSymbol{f149}] - \definesymbol [level-up] [\FontAwesomeSymbol{f148}] - \definesymbol [life-bouy] [\FontAwesomeSymbol{f1cd}] - \definesymbol [life-buoy] [\FontAwesomeSymbol{f1cd}] - \definesymbol [life-ring] [\FontAwesomeSymbol{f1cd}] - \definesymbol [life-saver] [\FontAwesomeSymbol{f1cd}] - \definesymbol [lightbulb-o] [\FontAwesomeSymbol{f0eb}] - \definesymbol [line-chart] [\FontAwesomeSymbol{f201}] - \definesymbol [link] [\FontAwesomeSymbol{f0c1}] - \definesymbol [linkedin] [\FontAwesomeSymbol{f0e1}] - \definesymbol [linkedin-square] [\FontAwesomeSymbol{f08c}] - \definesymbol [linux] [\FontAwesomeSymbol{f17c}] - \definesymbol [list] [\FontAwesomeSymbol{f03a}] - \definesymbol [list-alt] [\FontAwesomeSymbol{f022}] - \definesymbol [list-ol] [\FontAwesomeSymbol{f0cb}] - \definesymbol [list-ul] [\FontAwesomeSymbol{f0ca}] - \definesymbol [location-arrow] [\FontAwesomeSymbol{f124}] - \definesymbol [lock] [\FontAwesomeSymbol{f023}] - \definesymbol [long-arrow-down] [\FontAwesomeSymbol{f175}] - \definesymbol [long-arrow-left] [\FontAwesomeSymbol{f177}] - \definesymbol [long-arrow-right] [\FontAwesomeSymbol{f178}] - \definesymbol [long-arrow-up] [\FontAwesomeSymbol{f176}] - \definesymbol [low-vision] [\FontAwesomeSymbol{f2a8}] - \definesymbol [magic] [\FontAwesomeSymbol{f0d0}] - \definesymbol [magnet] [\FontAwesomeSymbol{f076}] - \definesymbol [mail-forward] [\FontAwesomeSymbol{f064}] - \definesymbol [mail-reply] [\FontAwesomeSymbol{f112}] - \definesymbol [mail-reply-all] [\FontAwesomeSymbol{f122}] - \definesymbol [male] [\FontAwesomeSymbol{f183}] - \definesymbol [map] [\FontAwesomeSymbol{f279}] - \definesymbol [map-marker] [\FontAwesomeSymbol{f041}] - \definesymbol [map-o] [\FontAwesomeSymbol{f278}] - \definesymbol [map-pin] [\FontAwesomeSymbol{f276}] - \definesymbol [map-signs] [\FontAwesomeSymbol{f277}] - \definesymbol [mars] [\FontAwesomeSymbol{f222}] - \definesymbol [mars-double] [\FontAwesomeSymbol{f227}] - \definesymbol [mars-stroke] [\FontAwesomeSymbol{f229}] - \definesymbol [mars-stroke-h] [\FontAwesomeSymbol{f22b}] - \definesymbol [mars-stroke-v] [\FontAwesomeSymbol{f22a}] - \definesymbol [maxcdn] [\FontAwesomeSymbol{f136}] - \definesymbol [meanpath] [\FontAwesomeSymbol{f20c}] - \definesymbol [medium] [\FontAwesomeSymbol{f23a}] - \definesymbol [medkit] [\FontAwesomeSymbol{f0fa}] - \definesymbol [meh-o] [\FontAwesomeSymbol{f11a}] - \definesymbol [mercury] [\FontAwesomeSymbol{f223}] - \definesymbol [microphone] [\FontAwesomeSymbol{f130}] - \definesymbol [microphone-slash] [\FontAwesomeSymbol{f131}] - \definesymbol [minus] [\FontAwesomeSymbol{f068}] - \definesymbol [minus-circle] [\FontAwesomeSymbol{f056}] - \definesymbol [minus-square] [\FontAwesomeSymbol{f146}] - \definesymbol [minus-square-o] [\FontAwesomeSymbol{f147}] - \definesymbol [mixcloud] [\FontAwesomeSymbol{f289}] - \definesymbol [mobile] [\FontAwesomeSymbol{f10b}] - \definesymbol [mobile-phone] [\FontAwesomeSymbol{f10b}] - \definesymbol [modx] [\FontAwesomeSymbol{f285}] - \definesymbol [money] [\FontAwesomeSymbol{f0d6}] - \definesymbol [moon-o] [\FontAwesomeSymbol{f186}] - \definesymbol [mortar-board] [\FontAwesomeSymbol{f19d}] - \definesymbol [motorcycle] [\FontAwesomeSymbol{f21c}] - \definesymbol [mouse-pointer] [\FontAwesomeSymbol{f245}] - \definesymbol [music] [\FontAwesomeSymbol{f001}] - \definesymbol [navicon] [\FontAwesomeSymbol{f0c9}] - \definesymbol [neuter] [\FontAwesomeSymbol{f22c}] - \definesymbol [newspaper-o] [\FontAwesomeSymbol{f1ea}] - \definesymbol [object-group] [\FontAwesomeSymbol{f247}] - \definesymbol [object-ungroup] [\FontAwesomeSymbol{f248}] - \definesymbol [odnoklassniki] [\FontAwesomeSymbol{f263}] - \definesymbol [odnoklassniki-square] [\FontAwesomeSymbol{f264}] - \definesymbol [opencart] [\FontAwesomeSymbol{f23d}] - \definesymbol [openid] [\FontAwesomeSymbol{f19b}] - \definesymbol [opera] [\FontAwesomeSymbol{f26a}] - \definesymbol [optin-monster] [\FontAwesomeSymbol{f23c}] - \definesymbol [outdent] [\FontAwesomeSymbol{f03b}] - \definesymbol [pagelines] [\FontAwesomeSymbol{f18c}] - \definesymbol [paint-brush] [\FontAwesomeSymbol{f1fc}] - \definesymbol [paper-plane] [\FontAwesomeSymbol{f1d8}] - \definesymbol [paper-plane-o] [\FontAwesomeSymbol{f1d9}] - \definesymbol [paperclip] [\FontAwesomeSymbol{f0c6}] - \definesymbol [paragraph] [\FontAwesomeSymbol{f1dd}] - \definesymbol [paste] [\FontAwesomeSymbol{f0ea}] - \definesymbol [pause] [\FontAwesomeSymbol{f04c}] - \definesymbol [pause-circle] [\FontAwesomeSymbol{f28b}] - \definesymbol [pause-circle-o] [\FontAwesomeSymbol{f28c}] - \definesymbol [paw] [\FontAwesomeSymbol{f1b0}] - \definesymbol [paypal] [\FontAwesomeSymbol{f1ed}] - \definesymbol [pencil] [\FontAwesomeSymbol{f040}] - \definesymbol [pencil-square] [\FontAwesomeSymbol{f14b}] - \definesymbol [pencil-square-o] [\FontAwesomeSymbol{f044}] - \definesymbol [percent] [\FontAwesomeSymbol{f295}] - \definesymbol [phone] [\FontAwesomeSymbol{f095}] - \definesymbol [phone-square] [\FontAwesomeSymbol{f098}] - \definesymbol [photo] [\FontAwesomeSymbol{f03e}] - \definesymbol [picture-o] [\FontAwesomeSymbol{f03e}] - \definesymbol [pie-chart] [\FontAwesomeSymbol{f200}] - \definesymbol [pied-piper] [\FontAwesomeSymbol{f2ae}] - \definesymbol [pied-piper-alt] [\FontAwesomeSymbol{f1a8}] - \definesymbol [pied-piper-pp] [\FontAwesomeSymbol{f1a7}] - \definesymbol [pinterest] [\FontAwesomeSymbol{f0d2}] - \definesymbol [pinterest-p] [\FontAwesomeSymbol{f231}] - \definesymbol [pinterest-square] [\FontAwesomeSymbol{f0d3}] - \definesymbol [plane] [\FontAwesomeSymbol{f072}] - \definesymbol [play] [\FontAwesomeSymbol{f04b}] - \definesymbol [play-circle] [\FontAwesomeSymbol{f144}] - \definesymbol [play-circle-o] [\FontAwesomeSymbol{f01d}] - \definesymbol [plug] [\FontAwesomeSymbol{f1e6}] - \definesymbol [plus] [\FontAwesomeSymbol{f067}] - \definesymbol [plus-circle] [\FontAwesomeSymbol{f055}] - \definesymbol [plus-square] [\FontAwesomeSymbol{f0fe}] - \definesymbol [plus-square-o] [\FontAwesomeSymbol{f196}] - \definesymbol [power-off] [\FontAwesomeSymbol{f011}] - \definesymbol [print] [\FontAwesomeSymbol{f02f}] - \definesymbol [product-hunt] [\FontAwesomeSymbol{f288}] - \definesymbol [puzzle-piece] [\FontAwesomeSymbol{f12e}] - \definesymbol [qq] [\FontAwesomeSymbol{f1d6}] - \definesymbol [qrcode] [\FontAwesomeSymbol{f029}] - \definesymbol [question] [\FontAwesomeSymbol{f128}] - \definesymbol [question-circle] [\FontAwesomeSymbol{f059}] - \definesymbol [question-circle-o] [\FontAwesomeSymbol{f29c}] - \definesymbol [quote-left] [\FontAwesomeSymbol{f10d}] - \definesymbol [quote-right] [\FontAwesomeSymbol{f10e}] - \definesymbol [ra] [\FontAwesomeSymbol{f1d0}] - \definesymbol [random] [\FontAwesomeSymbol{f074}] - \definesymbol [rebel] [\FontAwesomeSymbol{f1d0}] - \definesymbol [recycle] [\FontAwesomeSymbol{f1b8}] - \definesymbol [reddit] [\FontAwesomeSymbol{f1a1}] - \definesymbol [reddit-alien] [\FontAwesomeSymbol{f281}] - \definesymbol [reddit-square] [\FontAwesomeSymbol{f1a2}] - \definesymbol [refresh] [\FontAwesomeSymbol{f021}] - \definesymbol [registered] [\FontAwesomeSymbol{f25d}] - \definesymbol [remove] [\FontAwesomeSymbol{f00d}] - \definesymbol [renren] [\FontAwesomeSymbol{f18b}] - \definesymbol [reorder] [\FontAwesomeSymbol{f0c9}] - \definesymbol [repeat] [\FontAwesomeSymbol{f01e}] - \definesymbol [reply] [\FontAwesomeSymbol{f112}] - \definesymbol [reply-all] [\FontAwesomeSymbol{f122}] - \definesymbol [resistance] [\FontAwesomeSymbol{f1d0}] - \definesymbol [retweet] [\FontAwesomeSymbol{f079}] - \definesymbol [rmb] [\FontAwesomeSymbol{f157}] - \definesymbol [road] [\FontAwesomeSymbol{f018}] - \definesymbol [rocket] [\FontAwesomeSymbol{f135}] - \definesymbol [rotate-left] [\FontAwesomeSymbol{f0e2}] - \definesymbol [rotate-right] [\FontAwesomeSymbol{f01e}] - \definesymbol [rouble] [\FontAwesomeSymbol{f158}] - \definesymbol [rss] [\FontAwesomeSymbol{f09e}] - \definesymbol [rss-square] [\FontAwesomeSymbol{f143}] - \definesymbol [rub] [\FontAwesomeSymbol{f158}] - \definesymbol [ruble] [\FontAwesomeSymbol{f158}] - \definesymbol [rupee] [\FontAwesomeSymbol{f156}] - \definesymbol [safari] [\FontAwesomeSymbol{f267}] - \definesymbol [save] [\FontAwesomeSymbol{f0c7}] - \definesymbol [scissors] [\FontAwesomeSymbol{f0c4}] - \definesymbol [scribd] [\FontAwesomeSymbol{f28a}] - \definesymbol [search] [\FontAwesomeSymbol{f002}] - \definesymbol [search-minus] [\FontAwesomeSymbol{f010}] - \definesymbol [search-plus] [\FontAwesomeSymbol{f00e}] - \definesymbol [sellsy] [\FontAwesomeSymbol{f213}] - \definesymbol [send] [\FontAwesomeSymbol{f1d8}] - \definesymbol [send-o] [\FontAwesomeSymbol{f1d9}] - \definesymbol [server] [\FontAwesomeSymbol{f233}] - \definesymbol [share] [\FontAwesomeSymbol{f064}] - \definesymbol [share-alt] [\FontAwesomeSymbol{f1e0}] - \definesymbol [share-alt-square] [\FontAwesomeSymbol{f1e1}] - \definesymbol [share-square] [\FontAwesomeSymbol{f14d}] - \definesymbol [share-square-o] [\FontAwesomeSymbol{f045}] - \definesymbol [shekel] [\FontAwesomeSymbol{f20b}] - \definesymbol [sheqel] [\FontAwesomeSymbol{f20b}] - \definesymbol [shield] [\FontAwesomeSymbol{f132}] - \definesymbol [ship] [\FontAwesomeSymbol{f21a}] - \definesymbol [shirtsinbulk] [\FontAwesomeSymbol{f214}] - \definesymbol [shopping-bag] [\FontAwesomeSymbol{f290}] - \definesymbol [shopping-basket] [\FontAwesomeSymbol{f291}] - \definesymbol [shopping-cart] [\FontAwesomeSymbol{f07a}] - \definesymbol [sign-in] [\FontAwesomeSymbol{f090}] - \definesymbol [sign-language] [\FontAwesomeSymbol{f2a7}] - \definesymbol [sign-out] [\FontAwesomeSymbol{f08b}] - \definesymbol [signal] [\FontAwesomeSymbol{f012}] - \definesymbol [signing] [\FontAwesomeSymbol{f2a7}] - \definesymbol [simplybuilt] [\FontAwesomeSymbol{f215}] - \definesymbol [sitemap] [\FontAwesomeSymbol{f0e8}] - \definesymbol [skyatlas] [\FontAwesomeSymbol{f216}] - \definesymbol [skype] [\FontAwesomeSymbol{f17e}] - \definesymbol [slack] [\FontAwesomeSymbol{f198}] - \definesymbol [sliders] [\FontAwesomeSymbol{f1de}] - \definesymbol [slideshare] [\FontAwesomeSymbol{f1e7}] - \definesymbol [smile-o] [\FontAwesomeSymbol{f118}] - \definesymbol [snapchat] [\FontAwesomeSymbol{f2ab}] - \definesymbol [snapchat-ghost] [\FontAwesomeSymbol{f2ac}] - \definesymbol [snapchat-square] [\FontAwesomeSymbol{f2ad}] - \definesymbol [soccer-ball-o] [\FontAwesomeSymbol{f1e3}] - \definesymbol [sort] [\FontAwesomeSymbol{f0dc}] - \definesymbol [sort-alpha-asc] [\FontAwesomeSymbol{f15d}] - \definesymbol [sort-alpha-desc] [\FontAwesomeSymbol{f15e}] - \definesymbol [sort-amount-asc] [\FontAwesomeSymbol{f160}] - \definesymbol [sort-amount-desc] [\FontAwesomeSymbol{f161}] - \definesymbol [sort-asc] [\FontAwesomeSymbol{f0de}] - \definesymbol [sort-desc] [\FontAwesomeSymbol{f0dd}] - \definesymbol [sort-down] [\FontAwesomeSymbol{f0dd}] - \definesymbol [sort-numeric-asc] [\FontAwesomeSymbol{f162}] - \definesymbol [sort-numeric-desc] [\FontAwesomeSymbol{f163}] - \definesymbol [sort-up] [\FontAwesomeSymbol{f0de}] - \definesymbol [soundcloud] [\FontAwesomeSymbol{f1be}] - \definesymbol [space-shuttle] [\FontAwesomeSymbol{f197}] - \definesymbol [spinner] [\FontAwesomeSymbol{f110}] - \definesymbol [spoon] [\FontAwesomeSymbol{f1b1}] - \definesymbol [spotify] [\FontAwesomeSymbol{f1bc}] - \definesymbol [square] [\FontAwesomeSymbol{f0c8}] - \definesymbol [square-o] [\FontAwesomeSymbol{f096}] - \definesymbol [stack-exchange] [\FontAwesomeSymbol{f18d}] - \definesymbol [stack-overflow] [\FontAwesomeSymbol{f16c}] - \definesymbol [star] [\FontAwesomeSymbol{f005}] - \definesymbol [star-half] [\FontAwesomeSymbol{f089}] - \definesymbol [star-half-empty] [\FontAwesomeSymbol{f123}] - \definesymbol [star-half-full] [\FontAwesomeSymbol{f123}] - \definesymbol [star-half-o] [\FontAwesomeSymbol{f123}] - \definesymbol [star-o] [\FontAwesomeSymbol{f006}] - \definesymbol [steam] [\FontAwesomeSymbol{f1b6}] - \definesymbol [steam-square] [\FontAwesomeSymbol{f1b7}] - \definesymbol [step-backward] [\FontAwesomeSymbol{f048}] - \definesymbol [step-forward] [\FontAwesomeSymbol{f051}] - \definesymbol [stethoscope] [\FontAwesomeSymbol{f0f1}] - \definesymbol [sticky-note] [\FontAwesomeSymbol{f249}] - \definesymbol [sticky-note-o] [\FontAwesomeSymbol{f24a}] - \definesymbol [stop] [\FontAwesomeSymbol{f04d}] - \definesymbol [stop-circle] [\FontAwesomeSymbol{f28d}] - \definesymbol [stop-circle-o] [\FontAwesomeSymbol{f28e}] - \definesymbol [street-view] [\FontAwesomeSymbol{f21d}] - \definesymbol [strikethrough] [\FontAwesomeSymbol{f0cc}] - \definesymbol [stumbleupon] [\FontAwesomeSymbol{f1a4}] - \definesymbol [stumbleupon-circle] [\FontAwesomeSymbol{f1a3}] - \definesymbol [subscript] [\FontAwesomeSymbol{f12c}] - \definesymbol [subway] [\FontAwesomeSymbol{f239}] - \definesymbol [suitcase] [\FontAwesomeSymbol{f0f2}] - \definesymbol [sun-o] [\FontAwesomeSymbol{f185}] - \definesymbol [superscript] [\FontAwesomeSymbol{f12b}] - \definesymbol [support] [\FontAwesomeSymbol{f1cd}] - \definesymbol [table] [\FontAwesomeSymbol{f0ce}] - \definesymbol [tablet] [\FontAwesomeSymbol{f10a}] - \definesymbol [tachometer] [\FontAwesomeSymbol{f0e4}] - \definesymbol [tag] [\FontAwesomeSymbol{f02b}] - \definesymbol [tags] [\FontAwesomeSymbol{f02c}] - \definesymbol [tasks] [\FontAwesomeSymbol{f0ae}] - \definesymbol [taxi] [\FontAwesomeSymbol{f1ba}] - \definesymbol [television] [\FontAwesomeSymbol{f26c}] - \definesymbol [tencent-weibo] [\FontAwesomeSymbol{f1d5}] - \definesymbol [terminal] [\FontAwesomeSymbol{f120}] - \definesymbol [text-height] [\FontAwesomeSymbol{f034}] - \definesymbol [text-width] [\FontAwesomeSymbol{f035}] - \definesymbol [th] [\FontAwesomeSymbol{f00a}] - \definesymbol [th-large] [\FontAwesomeSymbol{f009}] - \definesymbol [th-list] [\FontAwesomeSymbol{f00b}] - \definesymbol [themeisle] [\FontAwesomeSymbol{f2b2}] - \definesymbol [thumb-tack] [\FontAwesomeSymbol{f08d}] - \definesymbol [thumbs-down] [\FontAwesomeSymbol{f165}] - \definesymbol [thumbs-o-down] [\FontAwesomeSymbol{f088}] - \definesymbol [thumbs-o-up] [\FontAwesomeSymbol{f087}] - \definesymbol [thumbs-up] [\FontAwesomeSymbol{f164}] - \definesymbol [ticket] [\FontAwesomeSymbol{f145}] - \definesymbol [times] [\FontAwesomeSymbol{f00d}] - \definesymbol [times-circle] [\FontAwesomeSymbol{f057}] - \definesymbol [times-circle-o] [\FontAwesomeSymbol{f05c}] - \definesymbol [tint] [\FontAwesomeSymbol{f043}] - \definesymbol [toggle-down] [\FontAwesomeSymbol{f150}] - \definesymbol [toggle-left] [\FontAwesomeSymbol{f191}] - \definesymbol [toggle-off] [\FontAwesomeSymbol{f204}] - \definesymbol [toggle-on] [\FontAwesomeSymbol{f205}] - \definesymbol [toggle-right] [\FontAwesomeSymbol{f152}] - \definesymbol [toggle-up] [\FontAwesomeSymbol{f151}] - \definesymbol [trademark] [\FontAwesomeSymbol{f25c}] - \definesymbol [train] [\FontAwesomeSymbol{f238}] - \definesymbol [transgender] [\FontAwesomeSymbol{f224}] - \definesymbol [transgender-alt] [\FontAwesomeSymbol{f225}] - \definesymbol [trash] [\FontAwesomeSymbol{f1f8}] - \definesymbol [trash-o] [\FontAwesomeSymbol{f014}] - \definesymbol [tree] [\FontAwesomeSymbol{f1bb}] - \definesymbol [trello] [\FontAwesomeSymbol{f181}] - \definesymbol [tripadvisor] [\FontAwesomeSymbol{f262}] - \definesymbol [trophy] [\FontAwesomeSymbol{f091}] - \definesymbol [truck] [\FontAwesomeSymbol{f0d1}] - \definesymbol [try] [\FontAwesomeSymbol{f195}] - \definesymbol [tty] [\FontAwesomeSymbol{f1e4}] - \definesymbol [tumblr] [\FontAwesomeSymbol{f173}] - \definesymbol [tumblr-square] [\FontAwesomeSymbol{f174}] - \definesymbol [turkish-lira] [\FontAwesomeSymbol{f195}] - \definesymbol [tv] [\FontAwesomeSymbol{f26c}] - \definesymbol [twitch] [\FontAwesomeSymbol{f1e8}] - \definesymbol [twitter] [\FontAwesomeSymbol{f099}] - \definesymbol [twitter-square] [\FontAwesomeSymbol{f081}] - \definesymbol [umbrella] [\FontAwesomeSymbol{f0e9}] - \definesymbol [underline] [\FontAwesomeSymbol{f0cd}] - \definesymbol [undo] [\FontAwesomeSymbol{f0e2}] - \definesymbol [universal-access] [\FontAwesomeSymbol{f29a}] - \definesymbol [university] [\FontAwesomeSymbol{f19c}] - \definesymbol [unlink] [\FontAwesomeSymbol{f127}] - \definesymbol [unlock] [\FontAwesomeSymbol{f09c}] - \definesymbol [unlock-alt] [\FontAwesomeSymbol{f13e}] - \definesymbol [unsorted] [\FontAwesomeSymbol{f0dc}] - \definesymbol [upload] [\FontAwesomeSymbol{f093}] - \definesymbol [usb] [\FontAwesomeSymbol{f287}] - \definesymbol [usd] [\FontAwesomeSymbol{f155}] - \definesymbol [user] [\FontAwesomeSymbol{f007}] - \definesymbol [user-md] [\FontAwesomeSymbol{f0f0}] - \definesymbol [user-plus] [\FontAwesomeSymbol{f234}] - \definesymbol [user-secret] [\FontAwesomeSymbol{f21b}] - \definesymbol [user-times] [\FontAwesomeSymbol{f235}] - \definesymbol [users] [\FontAwesomeSymbol{f0c0}] - \definesymbol [venus] [\FontAwesomeSymbol{f221}] - \definesymbol [venus-double] [\FontAwesomeSymbol{f226}] - \definesymbol [venus-mars] [\FontAwesomeSymbol{f228}] - \definesymbol [viacoin] [\FontAwesomeSymbol{f237}] - \definesymbol [viadeo] [\FontAwesomeSymbol{f2a9}] - \definesymbol [viadeo-square] [\FontAwesomeSymbol{f2aa}] - \definesymbol [video-camera] [\FontAwesomeSymbol{f03d}] - \definesymbol [vimeo] [\FontAwesomeSymbol{f27d}] - \definesymbol [vimeo-square] [\FontAwesomeSymbol{f194}] - \definesymbol [vine] [\FontAwesomeSymbol{f1ca}] - \definesymbol [vk] [\FontAwesomeSymbol{f189}] - \definesymbol [volume-control-phone] [\FontAwesomeSymbol{f2a0}] - \definesymbol [volume-down] [\FontAwesomeSymbol{f027}] - \definesymbol [volume-off] [\FontAwesomeSymbol{f026}] - \definesymbol [volume-up] [\FontAwesomeSymbol{f028}] - \definesymbol [warning] [\FontAwesomeSymbol{f071}] - \definesymbol [wechat] [\FontAwesomeSymbol{f1d7}] - \definesymbol [weibo] [\FontAwesomeSymbol{f18a}] - \definesymbol [weixin] [\FontAwesomeSymbol{f1d7}] - \definesymbol [whatsapp] [\FontAwesomeSymbol{f232}] - \definesymbol [wheelchair] [\FontAwesomeSymbol{f193}] - \definesymbol [wheelchair-alt] [\FontAwesomeSymbol{f29b}] - \definesymbol [wifi] [\FontAwesomeSymbol{f1eb}] - \definesymbol [wikipedia-w] [\FontAwesomeSymbol{f266}] - \definesymbol [windows] [\FontAwesomeSymbol{f17a}] - \definesymbol [won] [\FontAwesomeSymbol{f159}] - \definesymbol [wordpress] [\FontAwesomeSymbol{f19a}] - \definesymbol [wpbeginner] [\FontAwesomeSymbol{f297}] - \definesymbol [wpforms] [\FontAwesomeSymbol{f298}] - \definesymbol [wrench] [\FontAwesomeSymbol{f0ad}] - \definesymbol [xing] [\FontAwesomeSymbol{f168}] - \definesymbol [xing-square] [\FontAwesomeSymbol{f169}] - \definesymbol [y-combinator] [\FontAwesomeSymbol{f23b}] - \definesymbol [y-combinator-square] [\FontAwesomeSymbol{f1d4}] - \definesymbol [yahoo] [\FontAwesomeSymbol{f19e}] - \definesymbol [yc] [\FontAwesomeSymbol{f23b}] - \definesymbol [yc-square] [\FontAwesomeSymbol{f1d4}] - \definesymbol [yelp] [\FontAwesomeSymbol{f1e9}] - \definesymbol [yen] [\FontAwesomeSymbol{f157}] - \definesymbol [yoast] [\FontAwesomeSymbol{f2b1}] - \definesymbol [youtube] [\FontAwesomeSymbol{f167}] - \definesymbol [youtube-play] [\FontAwesomeSymbol{f16a}] - \definesymbol [youtube-square] [\FontAwesomeSymbol{f166}] + \definesymbol [wheelchair] [\FontAwesomeSymbol{_378}] +% \definesymbol [500px] [\FontAwesomeSymbol{f26e}] +% \definesymbol [adjust] [\FontAwesomeSymbol{f042}] +% \definesymbol [adn] [\FontAwesomeSymbol{f170}] +% \definesymbol [align-center] [\FontAwesomeSymbol{f037}] +% \definesymbol [align-justify] [\FontAwesomeSymbol{f039}] +% \definesymbol [align-left] [\FontAwesomeSymbol{f036}] +% \definesymbol [align-right] [\FontAwesomeSymbol{f038}] +% \definesymbol [amazon] [\FontAwesomeSymbol{f270}] +% \definesymbol [ambulance] [\FontAwesomeSymbol{f0f9}] +% \definesymbol [american-sign-language-interpreting] [\FontAwesomeSymbol{f2a3}] +% \definesymbol [anchor] [\FontAwesomeSymbol{f13d}] +% \definesymbol [android] [\FontAwesomeSymbol{f17b}] +% \definesymbol [angellist] [\FontAwesomeSymbol{f209}] +% \definesymbol [angle-double-down] [\FontAwesomeSymbol{f103}] +% \definesymbol [angle-double-left] [\FontAwesomeSymbol{f100}] +% \definesymbol [angle-double-right] [\FontAwesomeSymbol{f101}] +% \definesymbol [angle-double-up] [\FontAwesomeSymbol{f102}] +% \definesymbol [angle-down] [\FontAwesomeSymbol{f107}] +% \definesymbol [angle-left] [\FontAwesomeSymbol{f104}] +% \definesymbol [angle-right] [\FontAwesomeSymbol{f105}] +% \definesymbol [angle-up] [\FontAwesomeSymbol{f106}] +% \definesymbol [apple] [\FontAwesomeSymbol{f179}] +% \definesymbol [archive] [\FontAwesomeSymbol{f187}] +% \definesymbol [area-chart] [\FontAwesomeSymbol{f1fe}] +% \definesymbol [arrow-circle-down] [\FontAwesomeSymbol{f0ab}] +% \definesymbol [arrow-circle-left] [\FontAwesomeSymbol{f0a8}] +% \definesymbol [arrow-circle-o-down] [\FontAwesomeSymbol{f01a}] +% \definesymbol [arrow-circle-o-left] [\FontAwesomeSymbol{f190}] +% \definesymbol [arrow-circle-o-right] [\FontAwesomeSymbol{f18e}] +% \definesymbol [arrow-circle-o-up] [\FontAwesomeSymbol{f01b}] +% \definesymbol [arrow-circle-right] [\FontAwesomeSymbol{f0a9}] +% \definesymbol [arrow-circle-up] [\FontAwesomeSymbol{f0aa}] +% \definesymbol [arrow-down] [\FontAwesomeSymbol{f063}] +% \definesymbol [arrow-left] [\FontAwesomeSymbol{f060}] +% \definesymbol [arrow-right] [\FontAwesomeSymbol{f061}] +% \definesymbol [arrow-up] [\FontAwesomeSymbol{f062}] +% \definesymbol [arrows] [\FontAwesomeSymbol{f047}] +% \definesymbol [arrows-alt] [\FontAwesomeSymbol{f0b2}] +% \definesymbol [arrows-h] [\FontAwesomeSymbol{f07e}] +% \definesymbol [arrows-v] [\FontAwesomeSymbol{f07d}] +% \definesymbol [asl-interpreting] [\FontAwesomeSymbol{f2a3}] +% \definesymbol [assistive-listening-systems] [\FontAwesomeSymbol{f2a2}] +% \definesymbol [asterisk] [\FontAwesomeSymbol{f069}] +% \definesymbol [at] [\FontAwesomeSymbol{f1fa}] +% \definesymbol [audio-description] [\FontAwesomeSymbol{f29e}] +% \definesymbol [automobile] [\FontAwesomeSymbol{f1b9}] +% \definesymbol [backward] [\FontAwesomeSymbol{f04a}] +% \definesymbol [balance-scale] [\FontAwesomeSymbol{f24e}] +% \definesymbol [ban] [\FontAwesomeSymbol{f05e}] +% \definesymbol [bank] [\FontAwesomeSymbol{f19c}] +% \definesymbol [bar-chart] [\FontAwesomeSymbol{f080}] +% \definesymbol [bar-chart-o] [\FontAwesomeSymbol{f080}] +% \definesymbol [barcode] [\FontAwesomeSymbol{f02a}] +% \definesymbol [bars] [\FontAwesomeSymbol{f0c9}] +% \definesymbol [battery-0] [\FontAwesomeSymbol{f244}] +% \definesymbol [battery-1] [\FontAwesomeSymbol{f243}] +% \definesymbol [battery-2] [\FontAwesomeSymbol{f242}] +% \definesymbol [battery-3] [\FontAwesomeSymbol{f241}] +% \definesymbol [battery-4] [\FontAwesomeSymbol{f240}] +% \definesymbol [battery-empty] [\FontAwesomeSymbol{f244}] +% \definesymbol [battery-full] [\FontAwesomeSymbol{f240}] +% \definesymbol [battery-half] [\FontAwesomeSymbol{f242}] +% \definesymbol [battery-quarter] [\FontAwesomeSymbol{f243}] +% \definesymbol [battery-three-quarters] [\FontAwesomeSymbol{f241}] +% \definesymbol [bed] [\FontAwesomeSymbol{f236}] +% \definesymbol [beer] [\FontAwesomeSymbol{f0fc}] +% \definesymbol [behance] [\FontAwesomeSymbol{f1b4}] +% \definesymbol [behance-square] [\FontAwesomeSymbol{f1b5}] +% \definesymbol [bell] [\FontAwesomeSymbol{f0f3}] +% \definesymbol [bell-o] [\FontAwesomeSymbol{f0a2}] +% \definesymbol [bell-slash] [\FontAwesomeSymbol{f1f6}] +% \definesymbol [bell-slash-o] [\FontAwesomeSymbol{f1f7}] +% \definesymbol [bicycle] [\FontAwesomeSymbol{f206}] +% \definesymbol [binoculars] [\FontAwesomeSymbol{f1e5}] +% \definesymbol [birthday-cake] [\FontAwesomeSymbol{f1fd}] +% \definesymbol [bitbucket] [\FontAwesomeSymbol{f171}] +% \definesymbol [bitbucket-square] [\FontAwesomeSymbol{f172}] +% \definesymbol [bitcoin] [\FontAwesomeSymbol{f15a}] +% \definesymbol [black-tie] [\FontAwesomeSymbol{f27e}] +% \definesymbol [blind] [\FontAwesomeSymbol{f29d}] +% \definesymbol [bluetooth] [\FontAwesomeSymbol{f293}] +% \definesymbol [bluetooth-b] [\FontAwesomeSymbol{f294}] +% \definesymbol [bold] [\FontAwesomeSymbol{f032}] +% \definesymbol [bolt] [\FontAwesomeSymbol{f0e7}] +% \definesymbol [bomb] [\FontAwesomeSymbol{f1e2}] +% \definesymbol [book] [\FontAwesomeSymbol{f02d}] +% \definesymbol [bookmark] [\FontAwesomeSymbol{f02e}] +% \definesymbol [bookmark-o] [\FontAwesomeSymbol{f097}] +% \definesymbol [braille] [\FontAwesomeSymbol{f2a1}] +% \definesymbol [briefcase] [\FontAwesomeSymbol{f0b1}] +% \definesymbol [btc] [\FontAwesomeSymbol{f15a}] +% \definesymbol [bug] [\FontAwesomeSymbol{f188}] +% \definesymbol [building] [\FontAwesomeSymbol{f1ad}] +% \definesymbol [building-o] [\FontAwesomeSymbol{f0f7}] +% \definesymbol [bullhorn] [\FontAwesomeSymbol{f0a1}] +% \definesymbol [bullseye] [\FontAwesomeSymbol{f140}] +% \definesymbol [bus] [\FontAwesomeSymbol{f207}] +% \definesymbol [buysellads] [\FontAwesomeSymbol{f20d}] +% \definesymbol [cab] [\FontAwesomeSymbol{f1ba}] +% \definesymbol [calculator] [\FontAwesomeSymbol{f1ec}] +% \definesymbol [calendar] [\FontAwesomeSymbol{f073}] +% \definesymbol [calendar-check-o] [\FontAwesomeSymbol{f274}] +% \definesymbol [calendar-minus-o] [\FontAwesomeSymbol{f272}] +% \definesymbol [calendar-o] [\FontAwesomeSymbol{f133}] +% \definesymbol [calendar-plus-o] [\FontAwesomeSymbol{f271}] +% \definesymbol [calendar-times-o] [\FontAwesomeSymbol{f273}] +% \definesymbol [camera] [\FontAwesomeSymbol{f030}] +% \definesymbol [camera-retro] [\FontAwesomeSymbol{f083}] +% \definesymbol [car] [\FontAwesomeSymbol{f1b9}] +% \definesymbol [caret-down] [\FontAwesomeSymbol{f0d7}] +% \definesymbol [caret-left] [\FontAwesomeSymbol{f0d9}] +% \definesymbol [caret-right] [\FontAwesomeSymbol{f0da}] +% \definesymbol [caret-square-o-down] [\FontAwesomeSymbol{f150}] +% \definesymbol [caret-square-o-left] [\FontAwesomeSymbol{f191}] +% \definesymbol [caret-square-o-right] [\FontAwesomeSymbol{f152}] +% \definesymbol [caret-square-o-up] [\FontAwesomeSymbol{f151}] +% \definesymbol [caret-up] [\FontAwesomeSymbol{f0d8}] +% \definesymbol [cart-arrow-down] [\FontAwesomeSymbol{f218}] +% \definesymbol [cart-plus] [\FontAwesomeSymbol{f217}] +% \definesymbol [cc] [\FontAwesomeSymbol{f20a}] +% \definesymbol [cc-amex] [\FontAwesomeSymbol{f1f3}] +% \definesymbol [cc-diners-club] [\FontAwesomeSymbol{f24c}] +% \definesymbol [cc-discover] [\FontAwesomeSymbol{f1f2}] +% \definesymbol [cc-jcb] [\FontAwesomeSymbol{f24b}] +% \definesymbol [cc-mastercard] [\FontAwesomeSymbol{f1f1}] +% \definesymbol [cc-paypal] [\FontAwesomeSymbol{f1f4}] +% \definesymbol [cc-stripe] [\FontAwesomeSymbol{f1f5}] +% \definesymbol [cc-visa] [\FontAwesomeSymbol{f1f0}] +% \definesymbol [certificate] [\FontAwesomeSymbol{f0a3}] +% \definesymbol [chain] [\FontAwesomeSymbol{f0c1}] +% \definesymbol [chain-broken] [\FontAwesomeSymbol{f127}] +% \definesymbol [check] [\FontAwesomeSymbol{f00c}] +% \definesymbol [check-circle] [\FontAwesomeSymbol{f058}] +% \definesymbol [check-circle-o] [\FontAwesomeSymbol{f05d}] +% \definesymbol [check-square] [\FontAwesomeSymbol{f14a}] +% \definesymbol [check-square-o] [\FontAwesomeSymbol{f046}] +% \definesymbol [chevron-circle-down] [\FontAwesomeSymbol{f13a}] +% \definesymbol [chevron-circle-left] [\FontAwesomeSymbol{f137}] +% \definesymbol [chevron-circle-right] [\FontAwesomeSymbol{f138}] +% \definesymbol [chevron-circle-up] [\FontAwesomeSymbol{f139}] +% \definesymbol [chevron-down] [\FontAwesomeSymbol{f078}] +% \definesymbol [chevron-left] [\FontAwesomeSymbol{f053}] +% \definesymbol [chevron-right] [\FontAwesomeSymbol{f054}] +% \definesymbol [chevron-up] [\FontAwesomeSymbol{f077}] +% \definesymbol [child] [\FontAwesomeSymbol{f1ae}] +% \definesymbol [chrome] [\FontAwesomeSymbol{f268}] +% \definesymbol [circle] [\FontAwesomeSymbol{f111}] +% \definesymbol [circle-o] [\FontAwesomeSymbol{f10c}] +% \definesymbol [circle-o-notch] [\FontAwesomeSymbol{f1ce}] +% \definesymbol [circle-thin] [\FontAwesomeSymbol{f1db}] +% \definesymbol [clipboard] [\FontAwesomeSymbol{f0ea}] +% \definesymbol [clock-o] [\FontAwesomeSymbol{f017}] +% \definesymbol [clone] [\FontAwesomeSymbol{f24d}] +% \definesymbol [close] [\FontAwesomeSymbol{f00d}] +% \definesymbol [cloud] [\FontAwesomeSymbol{f0c2}] +% \definesymbol [cloud-download] [\FontAwesomeSymbol{f0ed}] +% \definesymbol [cloud-upload] [\FontAwesomeSymbol{f0ee}] +% \definesymbol [cny] [\FontAwesomeSymbol{f157}] +% \definesymbol [code] [\FontAwesomeSymbol{f121}] +% \definesymbol [code-fork] [\FontAwesomeSymbol{f126}] +% \definesymbol [codepen] [\FontAwesomeSymbol{f1cb}] +% \definesymbol [codiepie] [\FontAwesomeSymbol{f284}] +% \definesymbol [coffee] [\FontAwesomeSymbol{f0f4}] +% \definesymbol [cog] [\FontAwesomeSymbol{f013}] +% \definesymbol [cogs] [\FontAwesomeSymbol{f085}] +% \definesymbol [columns] [\FontAwesomeSymbol{f0db}] +% \definesymbol [comment] [\FontAwesomeSymbol{f075}] +% \definesymbol [comment-o] [\FontAwesomeSymbol{f0e5}] +% \definesymbol [commenting] [\FontAwesomeSymbol{f27a}] +% \definesymbol [commenting-o] [\FontAwesomeSymbol{f27b}] +% \definesymbol [comments] [\FontAwesomeSymbol{f086}] +% \definesymbol [comments-o] [\FontAwesomeSymbol{f0e6}] +% \definesymbol [compass] [\FontAwesomeSymbol{f14e}] +% \definesymbol [compress] [\FontAwesomeSymbol{f066}] +% \definesymbol [connectdevelop] [\FontAwesomeSymbol{f20e}] +% \definesymbol [contao] [\FontAwesomeSymbol{f26d}] +% \definesymbol [copy] [\FontAwesomeSymbol{f0c5}] +% \definesymbol [copyright] [\FontAwesomeSymbol{f1f9}] +% \definesymbol [creative-commons] [\FontAwesomeSymbol{f25e}] +% \definesymbol [credit-card] [\FontAwesomeSymbol{f09d}] +% \definesymbol [credit-card-alt] [\FontAwesomeSymbol{f283}] +% \definesymbol [crop] [\FontAwesomeSymbol{f125}] +% \definesymbol [crosshairs] [\FontAwesomeSymbol{f05b}] +% \definesymbol [css3] [\FontAwesomeSymbol{f13c}] +% \definesymbol [cube] [\FontAwesomeSymbol{f1b2}] +% \definesymbol [cubes] [\FontAwesomeSymbol{f1b3}] +% \definesymbol [cut] [\FontAwesomeSymbol{f0c4}] +% \definesymbol [cutlery] [\FontAwesomeSymbol{f0f5}] +% \definesymbol [dashboard] [\FontAwesomeSymbol{f0e4}] +% \definesymbol [dashcube] [\FontAwesomeSymbol{f210}] +% \definesymbol [database] [\FontAwesomeSymbol{f1c0}] +% \definesymbol [deaf] [\FontAwesomeSymbol{f2a4}] +% \definesymbol [deafness] [\FontAwesomeSymbol{f2a4}] +% \definesymbol [dedent] [\FontAwesomeSymbol{f03b}] +% \definesymbol [delicious] [\FontAwesomeSymbol{f1a5}] +% \definesymbol [desktop] [\FontAwesomeSymbol{f108}] +% \definesymbol [deviantart] [\FontAwesomeSymbol{f1bd}] +% \definesymbol [diamond] [\FontAwesomeSymbol{f219}] +% \definesymbol [digg] [\FontAwesomeSymbol{f1a6}] +% \definesymbol [dollar] [\FontAwesomeSymbol{f155}] +% \definesymbol [dot-circle-o] [\FontAwesomeSymbol{f192}] +% \definesymbol [download] [\FontAwesomeSymbol{f019}] +% \definesymbol [dribbble] [\FontAwesomeSymbol{f17d}] +% \definesymbol [dropbox] [\FontAwesomeSymbol{f16b}] +% \definesymbol [drupal] [\FontAwesomeSymbol{f1a9}] +% \definesymbol [edge] [\FontAwesomeSymbol{f282}] +% \definesymbol [edit] [\FontAwesomeSymbol{f044}] +% \definesymbol [eject] [\FontAwesomeSymbol{f052}] +% \definesymbol [ellipsis-h] [\FontAwesomeSymbol{f141}] +% \definesymbol [ellipsis-v] [\FontAwesomeSymbol{f142}] +% \definesymbol [empire] [\FontAwesomeSymbol{f1d1}] +% \definesymbol [envelope] [\FontAwesomeSymbol{f0e0}] +% \definesymbol [envelope-o] [\FontAwesomeSymbol{f003}] +% \definesymbol [envelope-square] [\FontAwesomeSymbol{f199}] +% \definesymbol [envira] [\FontAwesomeSymbol{f299}] +% \definesymbol [eraser] [\FontAwesomeSymbol{f12d}] +% \definesymbol [eur] [\FontAwesomeSymbol{f153}] +% \definesymbol [euro] [\FontAwesomeSymbol{f153}] +% \definesymbol [exchange] [\FontAwesomeSymbol{f0ec}] +% \definesymbol [exclamation] [\FontAwesomeSymbol{f12a}] +% \definesymbol [exclamation-circle] [\FontAwesomeSymbol{f06a}] +% \definesymbol [exclamation-triangle] [\FontAwesomeSymbol{f071}] +% \definesymbol [expand] [\FontAwesomeSymbol{f065}] +% \definesymbol [expeditedssl] [\FontAwesomeSymbol{f23e}] +% \definesymbol [external-link] [\FontAwesomeSymbol{f08e}] +% \definesymbol [external-link-square] [\FontAwesomeSymbol{f14c}] +% \definesymbol [eye] [\FontAwesomeSymbol{f06e}] +% \definesymbol [eye-slash] [\FontAwesomeSymbol{f070}] +% \definesymbol [eyedropper] [\FontAwesomeSymbol{f1fb}] +% \definesymbol [fa] [\FontAwesomeSymbol{f2b4}] +% \definesymbol [facebook] [\FontAwesomeSymbol{f09a}] +% \definesymbol [facebook-f] [\FontAwesomeSymbol{f09a}] +% \definesymbol [facebook-official] [\FontAwesomeSymbol{f230}] +% \definesymbol [facebook-square] [\FontAwesomeSymbol{f082}] +% \definesymbol [fast-backward] [\FontAwesomeSymbol{f049}] +% \definesymbol [fast-forward] [\FontAwesomeSymbol{f050}] +% \definesymbol [fax] [\FontAwesomeSymbol{f1ac}] +% \definesymbol [feed] [\FontAwesomeSymbol{f09e}] +% \definesymbol [female] [\FontAwesomeSymbol{f182}] +% \definesymbol [fighter-jet] [\FontAwesomeSymbol{f0fb}] +% \definesymbol [file] [\FontAwesomeSymbol{f15b}] +% \definesymbol [file-archive-o] [\FontAwesomeSymbol{f1c6}] +% \definesymbol [file-audio-o] [\FontAwesomeSymbol{f1c7}] +% \definesymbol [file-code-o] [\FontAwesomeSymbol{f1c9}] +% \definesymbol [file-excel-o] [\FontAwesomeSymbol{f1c3}] +% \definesymbol [file-image-o] [\FontAwesomeSymbol{f1c5}] +% \definesymbol [file-movie-o] [\FontAwesomeSymbol{f1c8}] +% \definesymbol [file-o] [\FontAwesomeSymbol{f016}] +% \definesymbol [file-pdf-o] [\FontAwesomeSymbol{f1c1}] +% \definesymbol [file-photo-o] [\FontAwesomeSymbol{f1c5}] +% \definesymbol [file-picture-o] [\FontAwesomeSymbol{f1c5}] +% \definesymbol [file-powerpoint-o] [\FontAwesomeSymbol{f1c4}] +% \definesymbol [file-sound-o] [\FontAwesomeSymbol{f1c7}] +% \definesymbol [file-text] [\FontAwesomeSymbol{f15c}] +% \definesymbol [file-text-o] [\FontAwesomeSymbol{f0f6}] +% \definesymbol [file-video-o] [\FontAwesomeSymbol{f1c8}] +% \definesymbol [file-word-o] [\FontAwesomeSymbol{f1c2}] +% \definesymbol [file-zip-o] [\FontAwesomeSymbol{f1c6}] +% \definesymbol [files-o] [\FontAwesomeSymbol{f0c5}] +% \definesymbol [film] [\FontAwesomeSymbol{f008}] +% \definesymbol [filter] [\FontAwesomeSymbol{f0b0}] +% \definesymbol [fire] [\FontAwesomeSymbol{f06d}] +% \definesymbol [fire-extinguisher] [\FontAwesomeSymbol{f134}] +% \definesymbol [firefox] [\FontAwesomeSymbol{f269}] +% \definesymbol [first-order] [\FontAwesomeSymbol{f2b0}] +% \definesymbol [flag] [\FontAwesomeSymbol{f024}] +% \definesymbol [flag-checkered] [\FontAwesomeSymbol{f11e}] +% \definesymbol [flag-o] [\FontAwesomeSymbol{f11d}] +% \definesymbol [flash] [\FontAwesomeSymbol{f0e7}] +% \definesymbol [flask] [\FontAwesomeSymbol{f0c3}] +% \definesymbol [flickr] [\FontAwesomeSymbol{f16e}] +% \definesymbol [floppy-o] [\FontAwesomeSymbol{f0c7}] +% \definesymbol [folder] [\FontAwesomeSymbol{f07b}] +% \definesymbol [folder-o] [\FontAwesomeSymbol{f114}] +% \definesymbol [folder-open] [\FontAwesomeSymbol{f07c}] +% \definesymbol [folder-open-o] [\FontAwesomeSymbol{f115}] +% \definesymbol [font] [\FontAwesomeSymbol{f031}] +% \definesymbol [font-awesome] [\FontAwesomeSymbol{f2b4}] +% \definesymbol [fonticons] [\FontAwesomeSymbol{f280}] +% \definesymbol [fort-awesome] [\FontAwesomeSymbol{f286}] +% \definesymbol [forumbee] [\FontAwesomeSymbol{f211}] +% \definesymbol [forward] [\FontAwesomeSymbol{f04e}] +% \definesymbol [foursquare] [\FontAwesomeSymbol{f180}] +% \definesymbol [frown-o] [\FontAwesomeSymbol{f119}] +% \definesymbol [futbol-o] [\FontAwesomeSymbol{f1e3}] +% \definesymbol [gamepad] [\FontAwesomeSymbol{f11b}] +% \definesymbol [gavel] [\FontAwesomeSymbol{f0e3}] +% \definesymbol [gbp] [\FontAwesomeSymbol{f154}] +% \definesymbol [ge] [\FontAwesomeSymbol{f1d1}] +% \definesymbol [gear] [\FontAwesomeSymbol{f013}] +% \definesymbol [gears] [\FontAwesomeSymbol{f085}] +% \definesymbol [genderless] [\FontAwesomeSymbol{f22d}] +% \definesymbol [get-pocket] [\FontAwesomeSymbol{f265}] +% \definesymbol [gg] [\FontAwesomeSymbol{f260}] +% \definesymbol [gg-circle] [\FontAwesomeSymbol{f261}] +% \definesymbol [gift] [\FontAwesomeSymbol{f06b}] +% \definesymbol [git] [\FontAwesomeSymbol{f1d3}] +% \definesymbol [git-square] [\FontAwesomeSymbol{f1d2}] +% \definesymbol [github] [\FontAwesomeSymbol{f09b}] +% \definesymbol [github-alt] [\FontAwesomeSymbol{f113}] +% \definesymbol [github-square] [\FontAwesomeSymbol{f092}] +% \definesymbol [gitlab] [\FontAwesomeSymbol{f296}] +% \definesymbol [gittip] [\FontAwesomeSymbol{f184}] +% \definesymbol [glass] [\FontAwesomeSymbol{f000}] +% \definesymbol [glide] [\FontAwesomeSymbol{f2a5}] +% \definesymbol [glide-g] [\FontAwesomeSymbol{f2a6}] +% \definesymbol [globe] [\FontAwesomeSymbol{f0ac}] +% \definesymbol [google] [\FontAwesomeSymbol{f1a0}] +% \definesymbol [google-plus] [\FontAwesomeSymbol{f0d5}] +% \definesymbol [google-plus-circle] [\FontAwesomeSymbol{f2b3}] +% \definesymbol [google-plus-official] [\FontAwesomeSymbol{f2b3}] +% \definesymbol [google-plus-square] [\FontAwesomeSymbol{f0d4}] +% \definesymbol [google-wallet] [\FontAwesomeSymbol{f1ee}] +% \definesymbol [graduation-cap] [\FontAwesomeSymbol{f19d}] +% \definesymbol [gratipay] [\FontAwesomeSymbol{f184}] +% \definesymbol [group] [\FontAwesomeSymbol{f0c0}] +% \definesymbol [h-square] [\FontAwesomeSymbol{f0fd}] +% \definesymbol [hacker-news] [\FontAwesomeSymbol{f1d4}] +% \definesymbol [hand-grab-o] [\FontAwesomeSymbol{f255}] +% \definesymbol [hand-lizard-o] [\FontAwesomeSymbol{f258}] +% \definesymbol [hand-o-down] [\FontAwesomeSymbol{f0a7}] +% \definesymbol [hand-o-left] [\FontAwesomeSymbol{f0a5}] +% \definesymbol [hand-o-right] [\FontAwesomeSymbol{f0a4}] +% \definesymbol [hand-o-up] [\FontAwesomeSymbol{f0a6}] +% \definesymbol [hand-paper-o] [\FontAwesomeSymbol{f256}] +% \definesymbol [hand-peace-o] [\FontAwesomeSymbol{f25b}] +% \definesymbol [hand-pointer-o] [\FontAwesomeSymbol{f25a}] +% \definesymbol [hand-rock-o] [\FontAwesomeSymbol{f255}] +% \definesymbol [hand-scissors-o] [\FontAwesomeSymbol{f257}] +% \definesymbol [hand-spock-o] [\FontAwesomeSymbol{f259}] +% \definesymbol [hand-stop-o] [\FontAwesomeSymbol{f256}] +% \definesymbol [hard-of-hearing] [\FontAwesomeSymbol{f2a4}] +% \definesymbol [hashtag] [\FontAwesomeSymbol{f292}] +% \definesymbol [hdd-o] [\FontAwesomeSymbol{f0a0}] +% \definesymbol [header] [\FontAwesomeSymbol{f1dc}] +% \definesymbol [headphones] [\FontAwesomeSymbol{f025}] +% \definesymbol [heart] [\FontAwesomeSymbol{f004}] +% \definesymbol [heart-o] [\FontAwesomeSymbol{f08a}] +% \definesymbol [heartbeat] [\FontAwesomeSymbol{f21e}] +% \definesymbol [history] [\FontAwesomeSymbol{f1da}] +% \definesymbol [home] [\FontAwesomeSymbol{f015}] +% \definesymbol [hospital-o] [\FontAwesomeSymbol{f0f8}] +% \definesymbol [hotel] [\FontAwesomeSymbol{f236}] +% \definesymbol [hourglass] [\FontAwesomeSymbol{f254}] +% \definesymbol [hourglass-1] [\FontAwesomeSymbol{f251}] +% \definesymbol [hourglass-2] [\FontAwesomeSymbol{f252}] +% \definesymbol [hourglass-3] [\FontAwesomeSymbol{f253}] +% \definesymbol [hourglass-end] [\FontAwesomeSymbol{f253}] +% \definesymbol [hourglass-half] [\FontAwesomeSymbol{f252}] +% \definesymbol [hourglass-o] [\FontAwesomeSymbol{f250}] +% \definesymbol [hourglass-start] [\FontAwesomeSymbol{f251}] +% \definesymbol [houzz] [\FontAwesomeSymbol{f27c}] +% \definesymbol [html5] [\FontAwesomeSymbol{f13b}] +% \definesymbol [i-cursor] [\FontAwesomeSymbol{f246}] +% \definesymbol [ils] [\FontAwesomeSymbol{f20b}] +% \definesymbol [image] [\FontAwesomeSymbol{f03e}] +% \definesymbol [inbox] [\FontAwesomeSymbol{f01c}] +% \definesymbol [indent] [\FontAwesomeSymbol{f03c}] +% \definesymbol [industry] [\FontAwesomeSymbol{f275}] +% \definesymbol [info] [\FontAwesomeSymbol{f129}] +% \definesymbol [info-circle] [\FontAwesomeSymbol{f05a}] +% \definesymbol [inr] [\FontAwesomeSymbol{f156}] +% \definesymbol [instagram] [\FontAwesomeSymbol{f16d}] +% \definesymbol [institution] [\FontAwesomeSymbol{f19c}] +% \definesymbol [internet-explorer] [\FontAwesomeSymbol{f26b}] +% \definesymbol [intersex] [\FontAwesomeSymbol{f224}] +% \definesymbol [ioxhost] [\FontAwesomeSymbol{f208}] +% \definesymbol [italic] [\FontAwesomeSymbol{f033}] +% \definesymbol [joomla] [\FontAwesomeSymbol{f1aa}] +% \definesymbol [jpy] [\FontAwesomeSymbol{f157}] +% \definesymbol [jsfiddle] [\FontAwesomeSymbol{f1cc}] +% \definesymbol [key] [\FontAwesomeSymbol{f084}] +% \definesymbol [keyboard-o] [\FontAwesomeSymbol{f11c}] +% \definesymbol [krw] [\FontAwesomeSymbol{f159}] +% \definesymbol [language] [\FontAwesomeSymbol{f1ab}] +% \definesymbol [laptop] [\FontAwesomeSymbol{f109}] +% \definesymbol [lastfm] [\FontAwesomeSymbol{f202}] +% \definesymbol [lastfm-square] [\FontAwesomeSymbol{f203}] +% \definesymbol [leaf] [\FontAwesomeSymbol{f06c}] +% \definesymbol [leanpub] [\FontAwesomeSymbol{f212}] +% \definesymbol [legal] [\FontAwesomeSymbol{f0e3}] +% \definesymbol [lemon-o] [\FontAwesomeSymbol{f094}] +% \definesymbol [level-down] [\FontAwesomeSymbol{f149}] +% \definesymbol [level-up] [\FontAwesomeSymbol{f148}] +% \definesymbol [life-bouy] [\FontAwesomeSymbol{f1cd}] +% \definesymbol [life-buoy] [\FontAwesomeSymbol{f1cd}] +% \definesymbol [life-ring] [\FontAwesomeSymbol{f1cd}] +% \definesymbol [life-saver] [\FontAwesomeSymbol{f1cd}] +% \definesymbol [lightbulb-o] [\FontAwesomeSymbol{f0eb}] +% \definesymbol [line-chart] [\FontAwesomeSymbol{f201}] +% \definesymbol [link] [\FontAwesomeSymbol{f0c1}] +% \definesymbol [linkedin] [\FontAwesomeSymbol{f0e1}] +% \definesymbol [linkedin-square] [\FontAwesomeSymbol{f08c}] +% \definesymbol [linux] [\FontAwesomeSymbol{f17c}] +% \definesymbol [list] [\FontAwesomeSymbol{f03a}] +% \definesymbol [list-alt] [\FontAwesomeSymbol{f022}] +% \definesymbol [list-ol] [\FontAwesomeSymbol{f0cb}] +% \definesymbol [list-ul] [\FontAwesomeSymbol{f0ca}] +% \definesymbol [location-arrow] [\FontAwesomeSymbol{f124}] +% \definesymbol [lock] [\FontAwesomeSymbol{f023}] +% \definesymbol [long-arrow-down] [\FontAwesomeSymbol{f175}] +% \definesymbol [long-arrow-left] [\FontAwesomeSymbol{f177}] +% \definesymbol [long-arrow-right] [\FontAwesomeSymbol{f178}] +% \definesymbol [long-arrow-up] [\FontAwesomeSymbol{f176}] +% \definesymbol [low-vision] [\FontAwesomeSymbol{f2a8}] +% \definesymbol [magic] [\FontAwesomeSymbol{f0d0}] +% \definesymbol [magnet] [\FontAwesomeSymbol{f076}] +% \definesymbol [mail-forward] [\FontAwesomeSymbol{f064}] +% \definesymbol [mail-reply] [\FontAwesomeSymbol{f112}] +% \definesymbol [mail-reply-all] [\FontAwesomeSymbol{f122}] +% \definesymbol [male] [\FontAwesomeSymbol{f183}] +% \definesymbol [map] [\FontAwesomeSymbol{f279}] +% \definesymbol [map-marker] [\FontAwesomeSymbol{f041}] +% \definesymbol [map-o] [\FontAwesomeSymbol{f278}] +% \definesymbol [map-pin] [\FontAwesomeSymbol{f276}] +% \definesymbol [map-signs] [\FontAwesomeSymbol{f277}] +% \definesymbol [mars] [\FontAwesomeSymbol{f222}] +% \definesymbol [mars-double] [\FontAwesomeSymbol{f227}] +% \definesymbol [mars-stroke] [\FontAwesomeSymbol{f229}] +% \definesymbol [mars-stroke-h] [\FontAwesomeSymbol{f22b}] +% \definesymbol [mars-stroke-v] [\FontAwesomeSymbol{f22a}] +% \definesymbol [maxcdn] [\FontAwesomeSymbol{f136}] +% \definesymbol [meanpath] [\FontAwesomeSymbol{f20c}] +% \definesymbol [medium] [\FontAwesomeSymbol{f23a}] +% \definesymbol [medkit] [\FontAwesomeSymbol{f0fa}] +% \definesymbol [meh-o] [\FontAwesomeSymbol{f11a}] +% \definesymbol [mercury] [\FontAwesomeSymbol{f223}] +% \definesymbol [microphone] [\FontAwesomeSymbol{f130}] +% \definesymbol [microphone-slash] [\FontAwesomeSymbol{f131}] +% \definesymbol [minus] [\FontAwesomeSymbol{f068}] +% \definesymbol [minus-circle] [\FontAwesomeSymbol{f056}] +% \definesymbol [minus-square] [\FontAwesomeSymbol{f146}] +% \definesymbol [minus-square-o] [\FontAwesomeSymbol{f147}] +% \definesymbol [mixcloud] [\FontAwesomeSymbol{f289}] +% \definesymbol [mobile] [\FontAwesomeSymbol{f10b}] +% \definesymbol [mobile-phone] [\FontAwesomeSymbol{f10b}] +% \definesymbol [modx] [\FontAwesomeSymbol{f285}] +% \definesymbol [money] [\FontAwesomeSymbol{f0d6}] +% \definesymbol [moon-o] [\FontAwesomeSymbol{f186}] +% \definesymbol [mortar-board] [\FontAwesomeSymbol{f19d}] +% \definesymbol [motorcycle] [\FontAwesomeSymbol{f21c}] +% \definesymbol [mouse-pointer] [\FontAwesomeSymbol{f245}] +% \definesymbol [music] [\FontAwesomeSymbol{f001}] +% \definesymbol [navicon] [\FontAwesomeSymbol{f0c9}] +% \definesymbol [neuter] [\FontAwesomeSymbol{f22c}] +% \definesymbol [newspaper-o] [\FontAwesomeSymbol{f1ea}] +% \definesymbol [object-group] [\FontAwesomeSymbol{f247}] +% \definesymbol [object-ungroup] [\FontAwesomeSymbol{f248}] +% \definesymbol [odnoklassniki] [\FontAwesomeSymbol{f263}] +% \definesymbol [odnoklassniki-square] [\FontAwesomeSymbol{f264}] +% \definesymbol [opencart] [\FontAwesomeSymbol{f23d}] +% \definesymbol [openid] [\FontAwesomeSymbol{f19b}] +% \definesymbol [opera] [\FontAwesomeSymbol{f26a}] +% \definesymbol [optin-monster] [\FontAwesomeSymbol{f23c}] +% \definesymbol [outdent] [\FontAwesomeSymbol{f03b}] +% \definesymbol [pagelines] [\FontAwesomeSymbol{f18c}] +% \definesymbol [paint-brush] [\FontAwesomeSymbol{f1fc}] +% \definesymbol [paper-plane] [\FontAwesomeSymbol{f1d8}] +% \definesymbol [paper-plane-o] [\FontAwesomeSymbol{f1d9}] +% \definesymbol [paperclip] [\FontAwesomeSymbol{f0c6}] +% \definesymbol [paragraph] [\FontAwesomeSymbol{f1dd}] +% \definesymbol [paste] [\FontAwesomeSymbol{f0ea}] +% \definesymbol [pause] [\FontAwesomeSymbol{f04c}] +% \definesymbol [pause-circle] [\FontAwesomeSymbol{f28b}] +% \definesymbol [pause-circle-o] [\FontAwesomeSymbol{f28c}] +% \definesymbol [paw] [\FontAwesomeSymbol{f1b0}] +% \definesymbol [paypal] [\FontAwesomeSymbol{f1ed}] +% \definesymbol [pencil] [\FontAwesomeSymbol{f040}] +% \definesymbol [pencil-square] [\FontAwesomeSymbol{f14b}] +% \definesymbol [pencil-square-o] [\FontAwesomeSymbol{f044}] +% \definesymbol [percent] [\FontAwesomeSymbol{f295}] +% \definesymbol [phone] [\FontAwesomeSymbol{f095}] +% \definesymbol [phone-square] [\FontAwesomeSymbol{f098}] +% \definesymbol [photo] [\FontAwesomeSymbol{f03e}] +% \definesymbol [picture-o] [\FontAwesomeSymbol{f03e}] +% \definesymbol [pie-chart] [\FontAwesomeSymbol{f200}] +% \definesymbol [pied-piper] [\FontAwesomeSymbol{f2ae}] +% \definesymbol [pied-piper-alt] [\FontAwesomeSymbol{f1a8}] +% \definesymbol [pied-piper-pp] [\FontAwesomeSymbol{f1a7}] +% \definesymbol [pinterest] [\FontAwesomeSymbol{f0d2}] +% \definesymbol [pinterest-p] [\FontAwesomeSymbol{f231}] +% \definesymbol [pinterest-square] [\FontAwesomeSymbol{f0d3}] +% \definesymbol [plane] [\FontAwesomeSymbol{f072}] +% \definesymbol [play] [\FontAwesomeSymbol{f04b}] +% \definesymbol [play-circle] [\FontAwesomeSymbol{f144}] +% \definesymbol [play-circle-o] [\FontAwesomeSymbol{f01d}] +% \definesymbol [plug] [\FontAwesomeSymbol{f1e6}] +% \definesymbol [plus] [\FontAwesomeSymbol{f067}] +% \definesymbol [plus-circle] [\FontAwesomeSymbol{f055}] +% \definesymbol [plus-square] [\FontAwesomeSymbol{f0fe}] +% \definesymbol [plus-square-o] [\FontAwesomeSymbol{f196}] +% \definesymbol [power-off] [\FontAwesomeSymbol{f011}] +% \definesymbol [print] [\FontAwesomeSymbol{f02f}] +% \definesymbol [product-hunt] [\FontAwesomeSymbol{f288}] +% \definesymbol [puzzle-piece] [\FontAwesomeSymbol{f12e}] +% \definesymbol [qq] [\FontAwesomeSymbol{f1d6}] +% \definesymbol [qrcode] [\FontAwesomeSymbol{f029}] +% \definesymbol [question] [\FontAwesomeSymbol{f128}] +% \definesymbol [question-circle] [\FontAwesomeSymbol{f059}] +% \definesymbol [question-circle-o] [\FontAwesomeSymbol{f29c}] +% \definesymbol [quote-left] [\FontAwesomeSymbol{f10d}] +% \definesymbol [quote-right] [\FontAwesomeSymbol{f10e}] +% \definesymbol [ra] [\FontAwesomeSymbol{f1d0}] +% \definesymbol [random] [\FontAwesomeSymbol{f074}] +% \definesymbol [rebel] [\FontAwesomeSymbol{f1d0}] +% \definesymbol [recycle] [\FontAwesomeSymbol{f1b8}] +% \definesymbol [reddit] [\FontAwesomeSymbol{f1a1}] +% \definesymbol [reddit-alien] [\FontAwesomeSymbol{f281}] +% \definesymbol [reddit-square] [\FontAwesomeSymbol{f1a2}] +% \definesymbol [refresh] [\FontAwesomeSymbol{f021}] +% \definesymbol [registered] [\FontAwesomeSymbol{f25d}] +% \definesymbol [remove] [\FontAwesomeSymbol{f00d}] +% \definesymbol [renren] [\FontAwesomeSymbol{f18b}] +% \definesymbol [reorder] [\FontAwesomeSymbol{f0c9}] +% \definesymbol [repeat] [\FontAwesomeSymbol{f01e}] +% \definesymbol [reply] [\FontAwesomeSymbol{f112}] +% \definesymbol [reply-all] [\FontAwesomeSymbol{f122}] +% \definesymbol [resistance] [\FontAwesomeSymbol{f1d0}] +% \definesymbol [retweet] [\FontAwesomeSymbol{f079}] +% \definesymbol [rmb] [\FontAwesomeSymbol{f157}] +% \definesymbol [road] [\FontAwesomeSymbol{f018}] +% \definesymbol [rocket] [\FontAwesomeSymbol{f135}] +% \definesymbol [rotate-left] [\FontAwesomeSymbol{f0e2}] +% \definesymbol [rotate-right] [\FontAwesomeSymbol{f01e}] +% \definesymbol [rouble] [\FontAwesomeSymbol{f158}] +% \definesymbol [rss] [\FontAwesomeSymbol{f09e}] +% \definesymbol [rss-square] [\FontAwesomeSymbol{f143}] +% \definesymbol [rub] [\FontAwesomeSymbol{f158}] +% \definesymbol [ruble] [\FontAwesomeSymbol{f158}] +% \definesymbol [rupee] [\FontAwesomeSymbol{f156}] +% \definesymbol [safari] [\FontAwesomeSymbol{f267}] +% \definesymbol [save] [\FontAwesomeSymbol{f0c7}] +% \definesymbol [scissors] [\FontAwesomeSymbol{f0c4}] +% \definesymbol [scribd] [\FontAwesomeSymbol{f28a}] +% \definesymbol [search] [\FontAwesomeSymbol{f002}] +% \definesymbol [search-minus] [\FontAwesomeSymbol{f010}] +% \definesymbol [search-plus] [\FontAwesomeSymbol{f00e}] +% \definesymbol [sellsy] [\FontAwesomeSymbol{f213}] +% \definesymbol [send] [\FontAwesomeSymbol{f1d8}] +% \definesymbol [send-o] [\FontAwesomeSymbol{f1d9}] +% \definesymbol [server] [\FontAwesomeSymbol{f233}] +% \definesymbol [share] [\FontAwesomeSymbol{f064}] +% \definesymbol [share-alt] [\FontAwesomeSymbol{f1e0}] +% \definesymbol [share-alt-square] [\FontAwesomeSymbol{f1e1}] +% \definesymbol [share-square] [\FontAwesomeSymbol{f14d}] +% \definesymbol [share-square-o] [\FontAwesomeSymbol{f045}] +% \definesymbol [shekel] [\FontAwesomeSymbol{f20b}] +% \definesymbol [sheqel] [\FontAwesomeSymbol{f20b}] +% \definesymbol [shield] [\FontAwesomeSymbol{f132}] +% \definesymbol [ship] [\FontAwesomeSymbol{f21a}] +% \definesymbol [shirtsinbulk] [\FontAwesomeSymbol{f214}] +% \definesymbol [shopping-bag] [\FontAwesomeSymbol{f290}] +% \definesymbol [shopping-basket] [\FontAwesomeSymbol{f291}] +% \definesymbol [shopping-cart] [\FontAwesomeSymbol{f07a}] +% \definesymbol [sign-in] [\FontAwesomeSymbol{f090}] +% \definesymbol [sign-language] [\FontAwesomeSymbol{f2a7}] +% \definesymbol [sign-out] [\FontAwesomeSymbol{f08b}] +% \definesymbol [signal] [\FontAwesomeSymbol{f012}] +% \definesymbol [signing] [\FontAwesomeSymbol{f2a7}] +% \definesymbol [simplybuilt] [\FontAwesomeSymbol{f215}] +% \definesymbol [sitemap] [\FontAwesomeSymbol{f0e8}] +% \definesymbol [skyatlas] [\FontAwesomeSymbol{f216}] +% \definesymbol [skype] [\FontAwesomeSymbol{f17e}] +% \definesymbol [slack] [\FontAwesomeSymbol{f198}] +% \definesymbol [sliders] [\FontAwesomeSymbol{f1de}] +% \definesymbol [slideshare] [\FontAwesomeSymbol{f1e7}] +% \definesymbol [smile-o] [\FontAwesomeSymbol{f118}] +% \definesymbol [snapchat] [\FontAwesomeSymbol{f2ab}] +% \definesymbol [snapchat-ghost] [\FontAwesomeSymbol{f2ac}] +% \definesymbol [snapchat-square] [\FontAwesomeSymbol{f2ad}] +% \definesymbol [soccer-ball-o] [\FontAwesomeSymbol{f1e3}] +% \definesymbol [sort] [\FontAwesomeSymbol{f0dc}] +% \definesymbol [sort-alpha-asc] [\FontAwesomeSymbol{f15d}] +% \definesymbol [sort-alpha-desc] [\FontAwesomeSymbol{f15e}] +% \definesymbol [sort-amount-asc] [\FontAwesomeSymbol{f160}] +% \definesymbol [sort-amount-desc] [\FontAwesomeSymbol{f161}] +% \definesymbol [sort-asc] [\FontAwesomeSymbol{f0de}] +% \definesymbol [sort-desc] [\FontAwesomeSymbol{f0dd}] +% \definesymbol [sort-down] [\FontAwesomeSymbol{f0dd}] +% \definesymbol [sort-numeric-asc] [\FontAwesomeSymbol{f162}] +% \definesymbol [sort-numeric-desc] [\FontAwesomeSymbol{f163}] +% \definesymbol [sort-up] [\FontAwesomeSymbol{f0de}] +% \definesymbol [soundcloud] [\FontAwesomeSymbol{f1be}] +% \definesymbol [space-shuttle] [\FontAwesomeSymbol{f197}] +% \definesymbol [spinner] [\FontAwesomeSymbol{f110}] +% \definesymbol [spoon] [\FontAwesomeSymbol{f1b1}] +% \definesymbol [spotify] [\FontAwesomeSymbol{f1bc}] +% \definesymbol [square] [\FontAwesomeSymbol{f0c8}] +% \definesymbol [square-o] [\FontAwesomeSymbol{f096}] +% \definesymbol [stack-exchange] [\FontAwesomeSymbol{f18d}] +% \definesymbol [stack-overflow] [\FontAwesomeSymbol{f16c}] +% \definesymbol [star] [\FontAwesomeSymbol{f005}] +% \definesymbol [star-half] [\FontAwesomeSymbol{f089}] +% \definesymbol [star-half-empty] [\FontAwesomeSymbol{f123}] +% \definesymbol [star-half-full] [\FontAwesomeSymbol{f123}] +% \definesymbol [star-half-o] [\FontAwesomeSymbol{f123}] +% \definesymbol [star-o] [\FontAwesomeSymbol{f006}] +% \definesymbol [steam] [\FontAwesomeSymbol{f1b6}] +% \definesymbol [steam-square] [\FontAwesomeSymbol{f1b7}] +% \definesymbol [step-backward] [\FontAwesomeSymbol{f048}] +% \definesymbol [step-forward] [\FontAwesomeSymbol{f051}] +% \definesymbol [stethoscope] [\FontAwesomeSymbol{f0f1}] +% \definesymbol [sticky-note] [\FontAwesomeSymbol{f249}] +% \definesymbol [sticky-note-o] [\FontAwesomeSymbol{f24a}] +% \definesymbol [stop] [\FontAwesomeSymbol{f04d}] +% \definesymbol [stop-circle] [\FontAwesomeSymbol{f28d}] +% \definesymbol [stop-circle-o] [\FontAwesomeSymbol{f28e}] +% \definesymbol [street-view] [\FontAwesomeSymbol{f21d}] +% \definesymbol [strikethrough] [\FontAwesomeSymbol{f0cc}] +% \definesymbol [stumbleupon] [\FontAwesomeSymbol{f1a4}] +% \definesymbol [stumbleupon-circle] [\FontAwesomeSymbol{f1a3}] +% \definesymbol [subscript] [\FontAwesomeSymbol{f12c}] +% \definesymbol [subway] [\FontAwesomeSymbol{f239}] +% \definesymbol [suitcase] [\FontAwesomeSymbol{f0f2}] +% \definesymbol [sun-o] [\FontAwesomeSymbol{f185}] +% \definesymbol [superscript] [\FontAwesomeSymbol{f12b}] +% \definesymbol [support] [\FontAwesomeSymbol{f1cd}] +% \definesymbol [table] [\FontAwesomeSymbol{f0ce}] +% \definesymbol [tablet] [\FontAwesomeSymbol{f10a}] +% \definesymbol [tachometer] [\FontAwesomeSymbol{f0e4}] +% \definesymbol [tag] [\FontAwesomeSymbol{f02b}] +% \definesymbol [tags] [\FontAwesomeSymbol{f02c}] +% \definesymbol [tasks] [\FontAwesomeSymbol{f0ae}] +% \definesymbol [taxi] [\FontAwesomeSymbol{f1ba}] +% \definesymbol [television] [\FontAwesomeSymbol{f26c}] +% \definesymbol [tencent-weibo] [\FontAwesomeSymbol{f1d5}] +% \definesymbol [terminal] [\FontAwesomeSymbol{f120}] +% \definesymbol [text-height] [\FontAwesomeSymbol{f034}] +% \definesymbol [text-width] [\FontAwesomeSymbol{f035}] +% \definesymbol [th] [\FontAwesomeSymbol{f00a}] +% \definesymbol [th-large] [\FontAwesomeSymbol{f009}] +% \definesymbol [th-list] [\FontAwesomeSymbol{f00b}] +% \definesymbol [themeisle] [\FontAwesomeSymbol{f2b2}] +% \definesymbol [thumb-tack] [\FontAwesomeSymbol{f08d}] +% \definesymbol [thumbs-down] [\FontAwesomeSymbol{f165}] +% \definesymbol [thumbs-o-down] [\FontAwesomeSymbol{f088}] +% \definesymbol [thumbs-o-up] [\FontAwesomeSymbol{f087}] +% \definesymbol [thumbs-up] [\FontAwesomeSymbol{f164}] +% \definesymbol [ticket] [\FontAwesomeSymbol{f145}] +% \definesymbol [times] [\FontAwesomeSymbol{f00d}] +% \definesymbol [times-circle] [\FontAwesomeSymbol{f057}] +% \definesymbol [times-circle-o] [\FontAwesomeSymbol{f05c}] +% \definesymbol [tint] [\FontAwesomeSymbol{f043}] +% \definesymbol [toggle-down] [\FontAwesomeSymbol{f150}] +% \definesymbol [toggle-left] [\FontAwesomeSymbol{f191}] +% \definesymbol [toggle-off] [\FontAwesomeSymbol{f204}] +% \definesymbol [toggle-on] [\FontAwesomeSymbol{f205}] +% \definesymbol [toggle-right] [\FontAwesomeSymbol{f152}] +% \definesymbol [toggle-up] [\FontAwesomeSymbol{f151}] +% \definesymbol [trademark] [\FontAwesomeSymbol{f25c}] +% \definesymbol [train] [\FontAwesomeSymbol{f238}] +% \definesymbol [transgender] [\FontAwesomeSymbol{f224}] +% \definesymbol [transgender-alt] [\FontAwesomeSymbol{f225}] +% \definesymbol [trash] [\FontAwesomeSymbol{f1f8}] +% \definesymbol [trash-o] [\FontAwesomeSymbol{f014}] +% \definesymbol [tree] [\FontAwesomeSymbol{f1bb}] +% \definesymbol [trello] [\FontAwesomeSymbol{f181}] +% \definesymbol [tripadvisor] [\FontAwesomeSymbol{f262}] +% \definesymbol [trophy] [\FontAwesomeSymbol{f091}] +% \definesymbol [truck] [\FontAwesomeSymbol{f0d1}] +% \definesymbol [try] [\FontAwesomeSymbol{f195}] +% \definesymbol [tty] [\FontAwesomeSymbol{f1e4}] +% \definesymbol [tumblr] [\FontAwesomeSymbol{f173}] +% \definesymbol [tumblr-square] [\FontAwesomeSymbol{f174}] +% \definesymbol [turkish-lira] [\FontAwesomeSymbol{f195}] +% \definesymbol [tv] [\FontAwesomeSymbol{f26c}] +% \definesymbol [twitch] [\FontAwesomeSymbol{f1e8}] +% \definesymbol [twitter] [\FontAwesomeSymbol{f099}] +% \definesymbol [twitter-square] [\FontAwesomeSymbol{f081}] +% \definesymbol [umbrella] [\FontAwesomeSymbol{f0e9}] +% \definesymbol [underline] [\FontAwesomeSymbol{f0cd}] +% \definesymbol [undo] [\FontAwesomeSymbol{f0e2}] +% \definesymbol [universal-access] [\FontAwesomeSymbol{f29a}] +% \definesymbol [university] [\FontAwesomeSymbol{f19c}] +% \definesymbol [unlink] [\FontAwesomeSymbol{f127}] +% \definesymbol [unlock] [\FontAwesomeSymbol{f09c}] +% \definesymbol [unlock-alt] [\FontAwesomeSymbol{f13e}] +% \definesymbol [unsorted] [\FontAwesomeSymbol{f0dc}] +% \definesymbol [upload] [\FontAwesomeSymbol{f093}] +% \definesymbol [usb] [\FontAwesomeSymbol{f287}] +% \definesymbol [usd] [\FontAwesomeSymbol{f155}] +% \definesymbol [user] [\FontAwesomeSymbol{f007}] +% \definesymbol [user-md] [\FontAwesomeSymbol{f0f0}] +% \definesymbol [user-plus] [\FontAwesomeSymbol{f234}] +% \definesymbol [user-secret] [\FontAwesomeSymbol{f21b}] +% \definesymbol [user-times] [\FontAwesomeSymbol{f235}] +% \definesymbol [users] [\FontAwesomeSymbol{f0c0}] +% \definesymbol [venus] [\FontAwesomeSymbol{f221}] +% \definesymbol [venus-double] [\FontAwesomeSymbol{f226}] +% \definesymbol [venus-mars] [\FontAwesomeSymbol{f228}] +% \definesymbol [viacoin] [\FontAwesomeSymbol{f237}] +% \definesymbol [viadeo] [\FontAwesomeSymbol{f2a9}] +% \definesymbol [viadeo-square] [\FontAwesomeSymbol{f2aa}] +% \definesymbol [video-camera] [\FontAwesomeSymbol{f03d}] +% \definesymbol [vimeo] [\FontAwesomeSymbol{f27d}] +% \definesymbol [vimeo-square] [\FontAwesomeSymbol{f194}] +% \definesymbol [vine] [\FontAwesomeSymbol{f1ca}] +% \definesymbol [vk] [\FontAwesomeSymbol{f189}] +% \definesymbol [volume-control-phone] [\FontAwesomeSymbol{f2a0}] +% \definesymbol [volume-down] [\FontAwesomeSymbol{f027}] +% \definesymbol [volume-off] [\FontAwesomeSymbol{f026}] +% \definesymbol [volume-up] [\FontAwesomeSymbol{f028}] +% \definesymbol [warning] [\FontAwesomeSymbol{f071}] +% \definesymbol [wechat] [\FontAwesomeSymbol{f1d7}] +% \definesymbol [weibo] [\FontAwesomeSymbol{f18a}] +% \definesymbol [weixin] [\FontAwesomeSymbol{f1d7}] +% \definesymbol [whatsapp] [\FontAwesomeSymbol{f232}] +% \definesymbol [wheelchair] [\FontAwesomeSymbol{f193}] +% \definesymbol [wheelchair-alt] [\FontAwesomeSymbol{f29b}] +% \definesymbol [wifi] [\FontAwesomeSymbol{f1eb}] +% \definesymbol [wikipedia-w] [\FontAwesomeSymbol{f266}] +% \definesymbol [windows] [\FontAwesomeSymbol{f17a}] +% \definesymbol [won] [\FontAwesomeSymbol{f159}] +% \definesymbol [wordpress] [\FontAwesomeSymbol{f19a}] +% \definesymbol [wpbeginner] [\FontAwesomeSymbol{f297}] +% \definesymbol [wpforms] [\FontAwesomeSymbol{f298}] +% \definesymbol [wrench] [\FontAwesomeSymbol{f0ad}] +% \definesymbol [xing] [\FontAwesomeSymbol{f168}] +% \definesymbol [xing-square] [\FontAwesomeSymbol{f169}] +% \definesymbol [y-combinator] [\FontAwesomeSymbol{f23b}] +% \definesymbol [y-combinator-square] [\FontAwesomeSymbol{f1d4}] +% \definesymbol [yahoo] [\FontAwesomeSymbol{f19e}] +% \definesymbol [yc] [\FontAwesomeSymbol{f23b}] +% \definesymbol [yc-square] [\FontAwesomeSymbol{f1d4}] +% \definesymbol [yelp] [\FontAwesomeSymbol{f1e9}] +% \definesymbol [yen] [\FontAwesomeSymbol{f157}] +% \definesymbol [yoast] [\FontAwesomeSymbol{f2b1}] +% \definesymbol [youtube] [\FontAwesomeSymbol{f167}] +% \definesymbol [youtube-play] [\FontAwesomeSymbol{f16a}] +% \definesymbol [youtube-square] [\FontAwesomeSymbol{f166}] + +\stopsymbolset + +\definefontsynonym [FontAwesomeBrands] [file:fontawesome5brandsregular400.otf] +\definefontsynonym [FontAwesomeRegular] [file:fontawesome5freeregular400.otf] +\definefontsynonym [FontAwesomeSolid] [file:fontawesome5freesolid900.otf] + +\startsymbolset [fontawesome-brands] [font=FontAwesomeBrands] + % Font Awesome Brands +\stopsymbolset + +\startsymbolset [fontawesome-regular] [font=FontAwesomeRegular] + % Font Awesome Regular +\stopsymbolset + +\startsymbolset [fontawesome-solid] [font=FontAwesomeSolid] + % Font Awesome Solid \stopsymbolset \continueifinputfile{symb-imp-fontawesome.mkiv} -% \usesymbols[fontawesome] +\usemodule[article-basic] \starttext - \showsymbolset[fontawesome] + % \usesymbols[fontawesome] + % + % \symbol[fontawesome][wheelchair] + % \symbol[fontawesome][angle-right] + % \symbol[fontawesome][angle right] + % \symbol[fontawesome][angle_right] + + % \showsymbolset[fontawesome] + + \startnamedsection [title] [title={Font Awesome Brands}] + \showsymbolset [fontawesome-brands] + \stopnamedsection + + \startnamedsection [title] [title={Font Awesome Regular}] + \showsymbolset [fontawesome-regular] + \stopnamedsection + + \startnamedsection [title] [title={Font Awesome Solid}] + \showsymbolset [fontawesome-solid] + \stopnamedsection \stoptext diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv index d2657512f3f..2320ea59ae0 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mis.mkiv @@ -21,34 +21,36 @@ \definesymbol [\v!none] [] -\definesymbol [bullet] [\textmath\bullet] -\definesymbol [dash] [\textmath-] -\definesymbol [star] [\textmath\star] -\definesymbol [triangle] [\textmath\triangleright] -\definesymbol [circle] [\textmath\circ] -\definesymbol [square] [\textmath\square] -\definesymbol [diamond] [\textmath\diamond] +% \definesymbol [bullet] [\textmath\bullet] +% \definesymbol [dash] [\textmath-] +% \definesymbol [star] [\textmath\star] +% \definesymbol [triangle] [\textmath\triangleright] +% \definesymbol [circle] [\textmath\circ] +% \definesymbol [square] [\textmath\square] +% \definesymbol [diamond] [\textmath\diamond] +% \definesymbol [asterisk] [\textmath\ast] % I'm not sure about this ... I dislike the small bullet. So we provide % it as variant: \type {\setupsymbolset[text]}. Also, we want to be % backward compatible. -\startsymbolset[text] +% \startsymbolset[text] \definesymbol [bullet] [\textormathchar{"2022}] % • \bullet \definesymbol [dash] [\textormathchar{"2013}] % – - \definesymbol [star] [\textormathchar{"22C6}] % ✴ \star + \definesymbol [star] [\textormathchar{"22C6}] % ⋆ \star \definesymbol [triangle] [\textormathchar{"22B3}] % ⊳ \triangleright \definesymbol [circle] [\textormathchar{"2218}] % ∘ \circ \definesymbol [square] [\textormathchar{"25A1}] % □ \square \definesymbol [diamond] [\textormathchar{"22C4}] % ⋄ \diamond \definesymbol [checkmark] [\textormathchar{"2713}] % ✓ \checkmark + \definesymbol [asterisk] [\textormathchar{"2217}] % ∗ \asterisk \definesymbol [blacktriangle] [\textormathchar{"25B6}] % ▶ \definesymbol [blacksquare] [\textormathchar{"25A0}] % ■ \definesymbol [blackdiamond] [\textormathchar{"25C6}] % ◆ -\stopsymbolset +% \stopsymbolset \definesymbol [smallcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptscriptstyle\bigcirc}}}] \definesymbol [medcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptstyle \bigcirc}}}] @@ -62,6 +64,7 @@ \definesymbol [6] [\symbol{medcircle}] \definesymbol [7] [\symbol{bigcircle}] \definesymbol [8] [\symbol{square}] +\definesymbol [9] [\symbol{checkmark}] \definesymbol [S] [\sectionmark] \definesymbol [P] [\paragraphmark] diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv index 9902fc9e8a3..f6a38214f62 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-imp-mvs.mkiv @@ -254,10 +254,16 @@ \stopsymbolset -%D \showsymbolset[astronomic] -%D \showsymbolset[zodiac] -%D \showsymbolset[europe] -%D \showsymbolset[martinvogel 1] -%D \showsymbolset[martinvogel 2] +\continueifinputfile{symb-imp-mvs.mkiv} -\endinput +\usemodule[article-basic] + +\starttext + +\startsubject[title={Astronomic}] \showsymbolset[astronomic] \stopsubject +\startsubject[title={Zodiac}] \showsymbolset[zodiac] \stopsubject +\startsubject[title={Europe}] \showsymbolset[europe] \stopsubject +\startsubject[title={Martinvogel 1}] \showsymbolset[martinvogel 1] \stopsubject +\startsubject[title={Martinvogel 2}] \showsymbolset[martinvogel 2] \stopsubject + +\stoptext diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv index e4950e09d73..abf85767576 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-ini.mkiv @@ -45,6 +45,7 @@ \installcorenamespace{symbol} \installcorenamespace{symbolset} +\installcorenamespace{symboldefault} \let\currentsymbol \empty \let\currentsymbolset\empty @@ -95,8 +96,9 @@ % Test test \symbol[whatever]\ test \symbol[whatever]. % Test test \symbol{whatever} test \symbol{whatever}. -\unexpanded\def\symbol % This one always gobbles spaces, - {\dodoubleempty\symb_place} % so never change it again! +\unexpanded\def\symbol + {\dontleavehmode % so we can start a paragraph with it + \dodoubleempty\symb_place} \def\symb_place % so we also handle \symbol{name} {\iffirstargument % which is nicer with following spaces @@ -112,13 +114,23 @@ \expandafter\symb_place_normal_b \fi} +% \def\symb_place_normal_a[#1][#2]% +% {\edef\currentsymbol{#2}% +% \ifcsname\??symbol#1:#2\endcsname +% \symb_place_indeed{#1:#2}% +% \else +% \symb_place_normal_c +% \fi} + \def\symb_place_normal_a[#1][#2]% {\edef\currentsymbol{#2}% \ifcsname\??symbol#1:#2\endcsname - \symb_place_indeed{#1:#2}% + \symb_place_indeed{#1:#2}% maybe use \lastnamescs + \else\ifcsname\??symboldefault#1\endcsname + \symb_place_named{#1}% maybe use \lastnamescs \else \symb_place_normal_c - \fi} + \fi\fi} \def\symb_place_normal_b[#1][#2]% {\edef\currentsymbol{#1}% @@ -160,11 +172,47 @@ \expandafter\symb_fetch_indeed \fi} +% \def\symb_fetch_indeed#1% +% {\ifcsname\??symbol#1:\currentsymbol\endcsname +% \symb_place_indeed{#1:\currentsymbol}% +% \fi} + \def\symb_fetch_indeed#1% {\ifcsname\??symbol#1:\currentsymbol\endcsname \symb_place_indeed{#1:\currentsymbol}% + \else\ifcsname\??symboldefault#1\endcsname + \symb_place_named{#1}% + \fi\fi} + +\def\symb_place_named#1% \relax's prevent lookahead problems + {\begingroup + \setbox\scratchbox\hbox\bgroup + \the\everysymbol + \getglyphstyled + {\csname\??symboldefault#1\endcsname}% + {\tochar{n:\currentsymbol}}% + \relax + \egroup + \ifdim\wd\scratchbox>\zeropoint + \unhbox\scratchbox + \endgroup + \setxvalue{\??symbol#1:\currentsymbol}% + {\symb_place_named_indeed{#1}{\currentsymbol}}% + \settrue\c_symb_found + \else + \endgroup \fi} +\unexpanded\def\symb_place_named_indeed#1#2% \relax's prevent lookahead problems + {\settrue\c_symb_found + \begingroup + \the\everysymbol + \getglyphstyled + {\csname\??symboldefault#1\endcsname}% + {\tochar{n:#2}}% + \relax + \endgroup} + \def\symb_place_retry#1% {\ifcsname\??symbol:#1\endcsname \symb_place_indeed{:#1}% @@ -273,9 +321,25 @@ \installcorenamespace{symbolsets} -\unexpanded\def\startsymbolset[#1]% +% \unexpanded\def\startsymbolset[#1]% +% {\pushmacro\m_symb_current_set +% \def\m_symb_current_set{#1}} + +% maybe a parameterhandler: + +\unexpanded\def\startsymbolset + {\dodoubleargument\symb_start_set} + +\def\symb_start_set[#1][#2]% {\pushmacro\m_symb_current_set - \def\m_symb_current_set{#1}} + \def\m_symb_current_set{#1}% + \ifsecondargument + \getdummyparameters[\s!font=,#2]% + \edef\p_font{\dummyparameter\s!font}% + \ifx\p_font\empty\else + \letvalue{\??symboldefault#1}\p_font + \fi + \fi} \unexpanded\def\stopsymbolset {\popmacro\m_symb_current_set} diff --git a/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv b/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv index ed4d90861ec..c25d13d48bf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/symb-run.mkiv @@ -12,23 +12,55 @@ %C details. \startluacode - function commands.showsymbolset(collection,symbols) + function commands.showsymbolset(collection,symbols,fontid) if type(symbols) == "string" then symbols = utilities.parsers.settings_to_array(symbols) end + local options = { framecolor = "orange", rulethickness = ".8pt", offset = interfaces.variables.overlay } + local list = table.tohash(symbols) + local alsofont = fontid > 0 + local defined = #symbols > 0 + local byname = false + if alsofont then + local is_symbol = characters.is_symbol + local chardata = characters.data + local resources = fonts.hashes.resources [fontid] + local characters = fonts.hashes.characters[fontid] + if resources and characters then + local unicodes = resources.unicodes + if unicodes then + for name, unicode in next, unicodes do + if not list[name] and name ~= ".notdef" then + local c = rawget(chardata,unicode) + if not c or is_symbol[c.category] then + list[name] = false + byname = true + end + end + end + end + end + end + local detail = defined and byname context.start() context.forcesymbolset { collection } - context.starttabulate { "|lT|l|l|" } - local options = { framecolor = "orange", rulethickness = ".8pt", offset = interfaces.variables.overlay } - for i=1,#symbols do - local symbol = symbols[i] + context.starttabulate { detail and "|lT|l|l|lT|" or "|lT|l|l|"} + for symbol, how in table.sortedhash(list) do context.NC() - context(symbol) + if detail and how then + context.bold(symbol) + else + context(symbol) + end context.NC() context.symbol(symbol) context.NC() context.framed(options,context.nested.symbol(symbol)) context.NC() + if detail and how then + context.bold("defined") + context.NC() + end context.NR() end context.stoptabulate() @@ -42,7 +74,23 @@ {\dosingleargument\symb_show_set} \gdef\symb_show_set[#1]% - {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}} + {\begingroup + \edef\p_font{\begincsname\??symboldefault#1\endcsname}% + \begingroup + \ifx\p_font\empty + \global\globalscratchcounter\zerocount + \else + \definedfont[\p_font]% + \global\globalscratchcounter\fontid\font\relax + \fi + \endgroup + \ctxcommand { + showsymbolset ( + "#1", + "\symbolset{#1}", + \the\globalscratchcounter + ) }% + \endgroup} \protect diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua index f9d8505f1d4..9b0ca82c430 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.lua @@ -323,9 +323,47 @@ end implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" } implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" } -implement { name = "upper", arguments = "string", actions = { utf.upper, context } } -implement { name = "lower", arguments = "string", actions = { utf.lower, context } } -implement { name = "strip", arguments = "string", actions = { string.strip, context } } -- or utf.strip +do + + -- Quite probably we don't yet have characters loaded so we delay some + -- aliases. + + local _lower_, _upper_, _strip_ + + _lower_ = function(s) + if characters and characters.lower then + _lower_ = characters.lower + return _lower_(s) + end + return string.lower(s) + end + + _upper_ = function(s) + if characters and characters.upper then + _upper_ = characters.upper + return _upper_(s) + end + return string.upper(s) + end + + _strip_ = function(s) + -- or utf.strip + if string.strip then + _strip_ = string.strip + return _strip_(s) + end + return s + end + + local function lower(s) context(_lower_(s)) end + local function upper(s) context(_upper_(s)) end + local function strip(s) context(_strip_(s)) end + + implement { name = "upper", arguments = "string", actions = upper } + implement { name = "lower", arguments = "string", actions = lower } + implement { name = "strip", arguments = "string", actions = strip } + +end implement { name = "converteddimen", @@ -373,10 +411,17 @@ implement { -- not faster but just less tracing: -local firstoftwoarguments = context.firstoftwoarguments -local secondoftwoarguments = context.secondoftwoarguments -local firstofoneargument = context.firstofoneargument -local gobbleoneargument = context.gobbleoneargument +local ctx_protected_cs = context.protected.cs -- more efficient + +local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments +local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments +local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument +local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument + +context.firstoftwoarguments = ctx_firstoftwoarguments +context.secondoftwoarguments = ctx_secondoftwoarguments +context.firstofoneargument = ctx_firstofoneargument +context.gobbleoneargument = ctx_gobbleoneargument local hash = utilities.parsers.hashes.settings_to_set @@ -384,9 +429,9 @@ local function doifelsecommon(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - secondoftwoarguments() + ctx_secondoftwoarguments() else - firstoftwoarguments() + ctx_firstoftwoarguments() end return end @@ -400,7 +445,7 @@ local function doifelsecommon(a,b) for k in next, ha do if hb[k] then setmacro("commalistelement",k) - firstoftwoarguments() + ctx_firstoftwoarguments() return end end @@ -408,28 +453,28 @@ local function doifelsecommon(a,b) if hash[a][b] then -- if settings_to_set(a)[b] then setmacro("commalistelement",b) - firstoftwoarguments() + ctx_firstoftwoarguments() return end elseif bb then if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - firstoftwoarguments() + ctx_firstoftwoarguments() return end end setmacro("commalistelement","") - secondoftwoarguments() + ctx_secondoftwoarguments() end local function doifcommon(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - gobbleoneargument() + ctx_gobbleoneargument() else - firstofoneargument() + ctx_firstofoneargument() end return end @@ -443,7 +488,7 @@ local function doifcommon(a,b) for k in next, ha do if hb[k] then setmacro("commalistelement",k) - firstofoneargument() + ctx_firstofoneargument() return end end @@ -451,28 +496,28 @@ local function doifcommon(a,b) if hash[a][b] then -- if settings_to_set(a)[b] then setmacro("commalistelement",b) - firstofoneargument() + ctx_firstofoneargument() return end elseif bb then if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - firstofoneargument() + ctx_firstofoneargument() return end end setmacro("commalistelement","") - gobbleoneargument() + ctx_gobbleoneargument() end local function doifnotcommon(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - firstofoneargument() + ctx_firstofoneargument() else - gobbleoneargument() + ctx_gobbleoneargument() end return end @@ -486,7 +531,7 @@ local function doifnotcommon(a,b) for k in next, ha do if hb[k] then setmacro("commalistelement",k) - gobbleoneargument() + ctx_gobbleoneargument() return end end @@ -494,28 +539,28 @@ local function doifnotcommon(a,b) if hash[a][b] then -- if settings_to_set(a)[b] then setmacro("commalistelement",b) - gobbleoneargument() + ctx_gobbleoneargument() return end elseif bb then if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - gobbleoneargument() + ctx_gobbleoneargument() return end end setmacro("commalistelement","") - firstofoneargument() + ctx_firstofoneargument() end local function doifelseinset(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - secondoftwoarguments() + ctx_secondoftwoarguments() else - firstoftwoarguments() + ctx_firstoftwoarguments() end return end @@ -524,21 +569,21 @@ local function doifelseinset(a,b) if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - firstoftwoarguments() + ctx_firstoftwoarguments() return end end setmacro("commalistelement","") - secondoftwoarguments() + ctx_secondoftwoarguments() end local function doifinset(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - gobbleoneargument() + ctx_gobbleoneargument() else - firstofoneargument() + ctx_firstofoneargument() end return end @@ -547,21 +592,21 @@ local function doifinset(a,b) if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - firstofoneargument() + ctx_firstofoneargument() return end end setmacro("commalistelement","") - gobbleoneargument() + ctx_gobbleoneargument() end local function doifnotinset(a,b) if a == b then setmacro("commalistelement",a) if a == "" then - firstofoneargument() + ctx_firstofoneargument() else - gobbleoneargument() + ctx_gobbleoneargument() end return end @@ -570,12 +615,12 @@ local function doifnotinset(a,b) if hash[b][a] then -- if settings_to_set(b)[a] then setmacro("commalistelement",a) - gobbleoneargument() + ctx_gobbleoneargument() return end end setmacro("commalistelement","") - firstofoneargument() + ctx_firstofoneargument() end implement { @@ -614,6 +659,20 @@ implement { arguments = "2 strings", } +-- done elsewhere: +-- +-- local function firstinset(a) +-- local aa = hash[a] +-- context(aa and aa[1] or a) +-- end +-- +-- implement { +-- name = "firstinset", +-- actions = firstinset, +-- arguments = "string", +-- private = false, +-- } + -- implement { -- name = "stringcompare", -- arguments = "2 strings", diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv index 77f947753ec..3004c08b805 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-aux.mkiv @@ -181,12 +181,9 @@ %D These are not needed any more now that we have wide screens (and bytes come %D cheap). -\let\@EA \singleexpandafter -\let\@EAEAEA \doubleexpandafter -\let\@EAEAEAEAEAEA\tripleexpandafter - -\let\@NX \noexpand -\def\@EAEA {\expandafter\expandafter} % can often be avoided +\let\@EA \singleexpandafter % obsolete +\let\@EAEAEA \doubleexpandafter % obsolete +\let\@EAEAEAEAEAEA\tripleexpandafter % obsolete %D Sometimes we pass macros as arguments to commands that don't expand them %D before interpretation. Such commands can be enclosed with \type {\expanded}, @@ -345,6 +342,18 @@ \let\doifnextoptionalelse \doifelsenextoptional \let\doifnextoptionalcselse\doifelsenextoptionalcs +% fails on assignments +% +% \unexpanded\def\doifelsenextoptional {\afterassignment\doifelsenextoptional_n \def\m_syst_action_yes} +% \def\doifelsenextoptional_n {\afterassignment\doifelsenextoptional_n_n\def\m_syst_action_nop} +% \def\doifelsenextoptional_n_n {\let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} +% +% \unexpanded\def\doifelsenextoptionalcs {\afterassignment\doifelsenextoptionalcs_n \let\m_syst_action_yes} +% \def\doifelsenextoptionalcs_n {\afterassignment\doifelsenextoptionalcs_n_n\let\m_syst_action_nop} +% \def\doifelsenextoptionalcs_n_n{\let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} + \def\syst_helpers_inspect_next_optional_character {\ifx\nexttoken\blankspace \expandafter\syst_helpers_reinspect_next_optional_character @@ -491,8 +500,6 @@ %D \type {\def} comes into action. This way the space after \type {\:} becomes a %D delimiter of the longer named \type {\reinspectnextcharacter}. -% try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...} - \let\next\: \def\:{\let\blankspace= } \: @@ -514,6 +521,31 @@ \let\:\next +%D This is much nicer and works too: + +% \def\firstofoneargument#1{#1} +% +% \expandafter\let\firstofoneargument{\blankspace= } +% +% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character +% } {\let\if_next_blank_space_token\iftrue +% \futurelet\nexttoken\syst_helpers_inspect_next_character} +% +% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_optional_character +% } {\let\if_next_blank_space_token\iftrue +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} +% +% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_bgroup_character +% } {\let\if_next_blank_space_token\iftrue +% \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character} +% +% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_parenthesis_character +% } {\let\if_next_blank_space_token\iftrue +% \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character} +% +% \expandafter\def\firstofoneargument{\syst_helpers_ignore_spacing_blankspace +% } {\futurelet\nexttoken\syst_helpers_ignore_spacing} + %D \macros %D {setvalue,setgvalue,setevalue,setxvalue, %D letvalue,letgvalue,getvalue,resetvalue, @@ -529,7 +561,7 @@ %D \setevalue {name}{...} = \edef\name{...} %D \setxvalue {name}{...} = \xdef\name{...} %D \letvalue {name}=\... = \let\name=\... -%D \letgvalue {name}=\... = \global\let\name=\... +%D \letgvalue {name}=\... = \glet\name=\... %D \getvalue {name} = \name %D \resetvalue {name} = \def\name{} %D \stoptyping @@ -537,16 +569,16 @@ %D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to %D its object oriented and parameter driven character. -\def\setvalue #1{\expandafter \def\csname#1\endcsname} +\def\setvalue #1{\expandafter\def \csname#1\endcsname} \def\setgvalue #1{\expandafter\gdef\csname#1\endcsname} \def\setevalue #1{\expandafter\edef\csname#1\endcsname} \def\setxvalue #1{\expandafter\xdef\csname#1\endcsname} -\def\getvalue #1{\csname#1\endcsname} -\def\letvalue #1{\expandafter\let\csname#1\endcsname} -\def\letgvalue #1{\global\expandafter\let\csname#1\endcsname} -\def\resetvalue #1{\expandafter\let\csname#1\endcsname\empty} -\def\undefinevalue#1{\expandafter\let\csname#1\endcsname\undefined} -\def\ignorevalue#1#2{\expandafter\let\csname#1\endcsname\empty} +\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname +\def\letvalue #1{\expandafter\let \csname#1\endcsname} +\def\letgvalue #1{\expandafter\glet\csname#1\endcsname} +\def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty} +\def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined} +\def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty} \def\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname} \def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname} @@ -562,7 +594,7 @@ %D tokens will save us some $300\times4=1200$ bytes of format file on a 32~bit %D system. Not that it matters much today. This shortcut is already defined: -\unexpanded\def\glet{\global\let} \let\globallet\glet +\let\globallet\glet %D \macros %D {doifundefined,doifdefined, @@ -635,7 +667,7 @@ {\ifcsname#1\endcsname\expandafter\let\csname#1\endcsname\undefined\fi} \def\globalundefine#1% conditional - {\ifcsname#1\endcsname\expandafter\global\let\csname#1\endcsname\undefined\fi} + {\ifcsname#1\endcsname\expandafter\glet\csname#1\endcsname\undefined\fi} %D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined! %D @@ -705,6 +737,23 @@ \expandafter\secondoftwoarguments \fi} +%D Slightly faster on longer arguments (0.179 downto 0.141): +%D +%D \testfeatureonce{100000}{\doifelse{aaaaaaaaaaaaaaa}{bbbbbbbbbbbbbbb}\relax\relax} + +% \unexpanded\def\doifelse +% {\afterassignment\doifelse_n\edef\m_syst_string_one} +% +% \unexpanded\def\doifelse_n +% {\afterassignment\doifelse_n_n\edef\m_syst_string_two} +% +% \unexpanded\def\doifelse_n_n +% {\ifx\m_syst_string_one\m_syst_string_two +% \expandafter\firstoftwoarguments +% \else +% \expandafter\secondoftwoarguments +% \fi} + %D \macros %D {doifempty,doifemptyelse,doifnotempty} %D @@ -912,6 +961,7 @@ \unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}} \unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}} \unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}} + % \let\firstinset \clf_firstinset \let\doifinsetelse\doifelseinset @@ -1348,7 +1398,7 @@ %D %D Sometimes the action to be undertaken depends on the %D next character. This macro get this character and puts it in -%D \type{\firstcharacter}. +%D \type {\firstcharacter}. %D %D \starttyping %D \getfirstcharacter {string} @@ -2243,202 +2293,517 @@ % \dotripleempty\test[] xxx\par % \dotripleempty\test xxx\par +%D Common: + +\newtoks\t_syst_aux + +% \def\syst_helpers_empty_spaced_six {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][][] } +% \def\syst_helpers_empty_normal_six {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][][]} +% \def\syst_helpers_empty_spaced_five {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][] } +% \def\syst_helpers_empty_normal_five {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][]} +% \def\syst_helpers_empty_spaced_four {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][] } +% \def\syst_helpers_empty_normal_four {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][]} +% \def\syst_helpers_empty_spaced_three{\expandafter\m_syst_aux_do\the\t_syst_aux[][][] } +% \def\syst_helpers_empty_normal_three{\expandafter\m_syst_aux_do\the\t_syst_aux[][][]} +% \def\syst_helpers_empty_spaced_two {\expandafter\m_syst_aux_do\the\t_syst_aux[][] } +% \def\syst_helpers_empty_normal_two {\expandafter\m_syst_aux_do\the\t_syst_aux[][]} +% \def\syst_helpers_empty_spaced_one {\expandafter\m_syst_aux_do\the\t_syst_aux[] } +% \def\syst_helpers_empty_normal_one {\expandafter\m_syst_aux_do\the\t_syst_aux[]} +% +% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \m_syst_aux_do} +% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux} +% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux} +% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux} +% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux} +% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux} +% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\expandafter\m_syst_aux_do\the\t_syst_aux} +% +% with +% +% \unexpanded\def\dodoubleempty#1% +% {\syst_helpers_argument_reset +% \let\m_syst_aux_do#1% alias +% \let\m_syst_action_yes\syst_helpers_double_empty_one_yes +% \let\m_syst_action_nop\syst_helpers_double_empty_one_nop +% \let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} +% +% \def\syst_helpers_double_empty_one_yes[#1]% +% {\firstargumenttrue +% \t_syst_aux{[{#1}]}% assignment +% \let\m_syst_action_yes\syst_helpers_double_empty_two_yes +% \let\m_syst_action_nop\syst_helpers_double_empty_two_nop +% \let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} +% +% But we use this as it keeps the original name visible: + +\def\syst_helpers_empty_spaced_six {\the\t_syst_aux[][][][][][] } +\def\syst_helpers_empty_normal_six {\the\t_syst_aux[][][][][][]} +\def\syst_helpers_empty_spaced_five {\the\t_syst_aux[][][][][] } +\def\syst_helpers_empty_normal_five {\the\t_syst_aux[][][][][]} +\def\syst_helpers_empty_spaced_four {\the\t_syst_aux[][][][] } +\def\syst_helpers_empty_normal_four {\the\t_syst_aux[][][][]} +\def\syst_helpers_empty_spaced_three{\the\t_syst_aux[][][] } +\def\syst_helpers_empty_normal_three{\the\t_syst_aux[][][]} +\def\syst_helpers_empty_spaced_two {\the\t_syst_aux[][] } +\def\syst_helpers_empty_normal_two {\the\t_syst_aux[][]} +\def\syst_helpers_empty_spaced_one {\the\t_syst_aux[] } +\def\syst_helpers_empty_normal_one {\the\t_syst_aux[]} + +\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux} +\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux} +\def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux} +\def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux} +\def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux} +\def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux} +\def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux} + %D Single: +% \unexpanded\def\dosingleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\firstargumenttrue#1}% +% {\syst_helpers_single_empty_one_nop#1}} +% +% \def\syst_helpers_single_empty_one_nop#1% +% {\firstargumentfalse +% #1[]} + \unexpanded\def\dosingleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\firstargumenttrue#1}% - {\syst_helpers_single_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_single_empty_one_yes + \let\m_syst_action_nop\syst_helpers_single_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_single_empty_one_nop#1% +\def\syst_helpers_single_empty_one_nop {\firstargumentfalse - #1[]} + \the\t_syst_aux[]} %D Double +% \unexpanded\def\dodoubleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_double_empty_one_yes#1}% +% {\syst_helpers_double_empty_one_nop#1}} +% +% \def\syst_helpers_double_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\secondargumenttrue#1[{#2}]}% +% {\syst_helpers_double_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_double_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% #1[][]} +% +% \def\syst_helpers_double_empty_two_nop +% {\secondargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_double_empty_one_spaced +% \else +% \expandafter\syst_helpers_double_empty_one_normal +% \fi} +% +% \def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] } +% \def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]} + \unexpanded\def\dodoubleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_double_empty_one_yes#1}% - {\syst_helpers_double_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_double_empty_one_yes + \let\m_syst_action_nop\syst_helpers_double_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_double_empty_one_yes#1[#2]% +\def\syst_helpers_double_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\secondargumenttrue#1[{#2}]}% - {\syst_helpers_double_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_double_empty_two_yes + \let\m_syst_action_nop\syst_helpers_double_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_double_empty_one_nop#1% +\def\syst_helpers_double_empty_one_nop {\firstargumentfalse \secondargumentfalse - #1[][]} + \the\t_syst_aux[][]} \def\syst_helpers_double_empty_two_nop {\secondargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_double_empty_one_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_double_empty_one_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] } -\def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]} +% Triple -% Three +% \unexpanded\def\dotripleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_triple_empty_one_yes#1}% +% {\syst_helpers_triple_empty_one_nop#1}} +% +% \def\syst_helpers_triple_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_triple_empty_two_yes#1{#2}}% +% {\syst_helpers_triple_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_triple_empty_two_yes#1#2[#3]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\thirdargumenttrue#1[{#2}][{#3}]}% +% {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}} +% +% \def\syst_helpers_triple_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% #1[][][]} +% +% \def\syst_helpers_triple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_triple_empty_two_spaced +% \else +% \expandafter\syst_helpers_triple_empty_two_normal +% \fi} +% +% \def\syst_helpers_triple_empty_three_nop +% {\thirdargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_triple_empty_three_spaced +% \else +% \expandafter\syst_helpers_triple_empty_three_normal +% \fi} +% +% \def\syst_helpers_triple_empty_two_spaced #1#2{#1[{#2}][][] } +% \def\syst_helpers_triple_empty_two_normal #1#2{#1[{#2}][][]} +% \def\syst_helpers_triple_empty_three_spaced#1#2#3{#1[{#2}][{#3}][] } +% \def\syst_helpers_triple_empty_three_normal#1#2#3{#1[{#2}][{#3}][]} \unexpanded\def\dotripleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_triple_empty_one_yes#1}% - {\syst_helpers_triple_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_triple_empty_one_yes + \let\m_syst_action_nop\syst_helpers_triple_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_triple_empty_one_yes#1[#2]% +\def\syst_helpers_triple_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_triple_empty_two_yes#1{#2}}% - {\syst_helpers_triple_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_triple_empty_two_yes + \let\m_syst_action_nop\syst_helpers_triple_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_triple_empty_two_yes#1#2[#3]% +\def\syst_helpers_triple_empty_two_yes[#1]% {\secondargumenttrue - \doifelsenextoptional - {\thirdargumenttrue#1[{#2}][{#3}]}% - {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_triple_empty_three_yes + \let\m_syst_action_nop\syst_helpers_triple_empty_three_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_triple_empty_one_nop#1% +\def\syst_helpers_triple_empty_one_nop {\firstargumentfalse \secondargumentfalse \thirdargumentfalse - #1[][][]} + \the\t_syst_aux[][][]} \def\syst_helpers_triple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_triple_empty_two_spaced + \expandafter\syst_helpers_empty_spaced_two \else - \expandafter\syst_helpers_triple_empty_two_normal + \expandafter\syst_helpers_empty_normal_two \fi} \def\syst_helpers_triple_empty_three_nop {\thirdargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_triple_empty_three_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_triple_empty_three_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_triple_empty_two_spaced #1#2{#1[{#2}][][] } -\def\syst_helpers_triple_empty_two_normal #1#2{#1[{#2}][][]} -\def\syst_helpers_triple_empty_three_spaced#1#2#3{#1[{#2}][{#3}][] } -\def\syst_helpers_triple_empty_three_normal#1#2#3{#1[{#2}][{#3}][]} +%D Quadruple: -%D Four: +% \unexpanded\def\doquadrupleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_quadruple_empty_one_yes#1}% +% {\syst_helpers_quadruple_empty_one_nop#1}} +% +% \def\syst_helpers_quadruple_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_quadruple_empty_two_yes#1{#2}}% +% {\syst_helpers_quadruple_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_quadruple_empty_two_yes#1#2[#3]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}% +% {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}} +% +% \def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]% +% {\thirdargumenttrue +% \doifelsenextoptional +% {\fourthargumenttrue#1[{#2}][{#3}][{#4}]}% +% {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}} +% +% \def\syst_helpers_quadruple_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% #1[][][][]} +% +% \def\syst_helpers_quadruple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quadruple_empty_two_spaced +% \else +% \expandafter\syst_helpers_quadruple_empty_two_normal +% \fi} +% +% \def\syst_helpers_quadruple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quadruple_empty_three_spaced +% \else +% \expandafter\syst_helpers_quadruple_empty_three_normal +% \fi} +% +% \def\syst_helpers_quadruple_empty_four_nop +% {\fourthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quadruple_empty_four_spaced +% \else +% \expandafter\syst_helpers_quadruple_empty_four_normal +% \fi} +% +% \def\syst_helpers_quadruple_empty_two_spaced #1#2{#1[{#2}][][][] } +% \def\syst_helpers_quadruple_empty_two_normal #1#2{#1[{#2}][][][]} +% \def\syst_helpers_quadruple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][] } +% \def\syst_helpers_quadruple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][]} +% \def\syst_helpers_quadruple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] } +% \def\syst_helpers_quadruple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][]} \unexpanded\def\doquadrupleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_quadruple_empty_one_yes#1}% - {\syst_helpers_quadruple_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_quadruple_empty_one_yes + \let\m_syst_action_nop\syst_helpers_quadruple_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quadruple_empty_one_yes#1[#2]% +\def\syst_helpers_quadruple_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_quadruple_empty_two_yes#1{#2}}% - {\syst_helpers_quadruple_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quadruple_empty_two_yes + \let\m_syst_action_nop\syst_helpers_quadruple_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quadruple_empty_two_yes#1#2[#3]% +\def\syst_helpers_quadruple_empty_two_yes[#1]% {\secondargumenttrue - \doifelsenextoptional - {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}% - {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quadruple_empty_three_yes + \let\m_syst_action_nop\syst_helpers_quadruple_empty_three_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]% +\def\syst_helpers_quadruple_empty_three_yes[#1]% {\thirdargumenttrue - \doifelsenextoptional - {\fourthargumenttrue#1[{#2}][{#3}][{#4}]}% - {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quadruple_empty_four_yes + \let\m_syst_action_nop\syst_helpers_quadruple_empty_four_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quadruple_empty_one_nop#1% +\def\syst_helpers_quadruple_empty_one_nop {\firstargumentfalse \secondargumentfalse \thirdargumentfalse \fourthargumentfalse - #1[][][][]} + \the\t_syst_aux[][][][]} \def\syst_helpers_quadruple_empty_two_nop {\secondargumentfalse \thirdargumentfalse \fourthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quadruple_empty_two_spaced + \expandafter\syst_helpers_empty_spaced_three \else - \expandafter\syst_helpers_quadruple_empty_two_normal + \expandafter\syst_helpers_empty_normal_three \fi} \def\syst_helpers_quadruple_empty_three_nop {\thirdargumentfalse \fourthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quadruple_empty_three_spaced + \expandafter\syst_helpers_empty_spaced_two \else - \expandafter\syst_helpers_quadruple_empty_three_normal + \expandafter\syst_helpers_empty_normal_two \fi} \def\syst_helpers_quadruple_empty_four_nop {\fourthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quadruple_empty_four_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_quadruple_empty_four_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_quadruple_empty_two_spaced #1#2{#1[{#2}][][][] } -\def\syst_helpers_quadruple_empty_two_normal #1#2{#1[{#2}][][][]} -\def\syst_helpers_quadruple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][] } -\def\syst_helpers_quadruple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][]} -\def\syst_helpers_quadruple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] } -\def\syst_helpers_quadruple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][]} +%D Quintuple: -%D Five: +% \unexpanded\def\doquintupleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_quintuple_empty_one_yes#1}% +% {\syst_helpers_quintuple_empty_one_nop#1}} +% +% \def\syst_helpers_quintuple_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_quintuple_empty_two_yes#1{#2}}% +% {\syst_helpers_quintuple_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_quintuple_empty_two_yes#1#2[#3]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}% +% {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}} +% +% \def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]% +% {\thirdargumenttrue +% \doifelsenextoptional +% {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}% +% {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}} +% +% \def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]% +% {\fourthargumenttrue +% \doifelsenextoptional +% {\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}% +% {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} +% +% \def\syst_helpers_quintuple_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% #1[][][][][]} +% +% \def\syst_helpers_quintuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quintuple_empty_two_spaced +% \else +% \expandafter\syst_helpers_quintuple_empty_two_normal +% \fi} +% +% \def\syst_helpers_quintuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quintuple_empty_three_spaced +% \else +% \expandafter\syst_helpers_quintuple_empty_three_normal +% \fi} +% +% \def\syst_helpers_quintuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quintuple_empty_four_spaced +% \else +% \expandafter\syst_helpers_quintuple_empty_four_normal +% \fi} +% +% \def\syst_helpers_quintuple_empty_five_nop +% {\fifthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_quintuple_empty_five_spaced +% \else +% \expandafter\syst_helpers_quintuple_empty_five_normal +% \fi} +% +% \def\syst_helpers_quintuple_empty_two_spaced #1#2{#1[{#2}][][][][] } +% \def\syst_helpers_quintuple_empty_two_normal #1#2{#1[{#2}][][][][]} +% \def\syst_helpers_quintuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][] } +% \def\syst_helpers_quintuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][]} +% \def\syst_helpers_quintuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] } +% \def\syst_helpers_quintuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]} +% \def\syst_helpers_quintuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] } +% \def\syst_helpers_quintuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]} \unexpanded\def\doquintupleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_quintuple_empty_one_yes#1}% - {\syst_helpers_quintuple_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_quintuple_empty_one_yes + \let\m_syst_action_nop\syst_helpers_quintuple_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quintuple_empty_one_yes#1[#2]% +\def\syst_helpers_quintuple_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_quintuple_empty_two_yes#1{#2}}% - {\syst_helpers_quintuple_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quintuple_empty_two_yes + \let\m_syst_action_nop\syst_helpers_quintuple_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quintuple_empty_two_yes#1#2[#3]% +\def\syst_helpers_quintuple_empty_two_yes[#1]% {\secondargumenttrue - \doifelsenextoptional - {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}% - {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quintuple_empty_three_yes + \let\m_syst_action_nop\syst_helpers_quintuple_empty_three_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]% +\def\syst_helpers_quintuple_empty_three_yes[#1]% {\thirdargumenttrue - \doifelsenextoptional - {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}% - {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quintuple_empty_four_yes + \let\m_syst_action_nop\syst_helpers_quintuple_empty_four_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]% +\def\syst_helpers_quintuple_empty_four_yes[#1]% {\fourthargumenttrue - \doifelsenextoptional - {\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}% - {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_quintuple_empty_five_yes + \let\m_syst_action_nop\syst_helpers_quintuple_empty_five_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_quintuple_empty_one_nop#1% +\def\syst_helpers_quintuple_empty_one_nop {\firstargumentfalse \secondargumentfalse \thirdargumentfalse \fourthargumentfalse \fifthargumentfalse - #1[][][][][]} + \the\t_syst_aux[][][][][]} \def\syst_helpers_quintuple_empty_two_nop {\secondargumentfalse @@ -2446,9 +2811,9 @@ \fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quintuple_empty_two_spaced + \expandafter\syst_helpers_empty_spaced_four \else - \expandafter\syst_helpers_quintuple_empty_two_normal + \expandafter\syst_helpers_empty_normal_four \fi} \def\syst_helpers_quintuple_empty_three_nop @@ -2456,83 +2821,192 @@ \fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quintuple_empty_three_spaced + \expandafter\syst_helpers_empty_spaced_three \else - \expandafter\syst_helpers_quintuple_empty_three_normal + \expandafter\syst_helpers_empty_normal_three \fi} \def\syst_helpers_quintuple_empty_four_nop {\fourthargumentfalse \fifthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quintuple_empty_four_spaced + \expandafter\syst_helpers_empty_spaced_two \else - \expandafter\syst_helpers_quintuple_empty_four_normal + \expandafter\syst_helpers_empty_normal_two \fi} \def\syst_helpers_quintuple_empty_five_nop {\fifthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_quintuple_empty_five_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_quintuple_empty_five_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_quintuple_empty_two_spaced #1#2{#1[{#2}][][][][] } -\def\syst_helpers_quintuple_empty_two_normal #1#2{#1[{#2}][][][][]} -\def\syst_helpers_quintuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][] } -\def\syst_helpers_quintuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][]} -\def\syst_helpers_quintuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] } -\def\syst_helpers_quintuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]} -\def\syst_helpers_quintuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] } -\def\syst_helpers_quintuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]} +%D Sixtuple: -%D Six +% \unexpanded\def\dosixtupleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_sixtuple_empty_one_yes#1} +% {\syst_helpers_sixtuple_empty_one_nop#1}} +% +% \def\syst_helpers_sixtuple_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_sixtuple_empty_two_yes#1{#2}}% +% {\syst_helpers_sixtuple_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}% +% {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}} +% +% \def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]% +% {\thirdargumenttrue +% \doifelsenextoptional +% {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}% +% {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}} +% +% \def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]% +% {\fourthargumenttrue +% \doifelsenextoptional +% {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% +% {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} +% +% \def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]% +% {\fifthargumenttrue +% \doifelsenextoptional +% {\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}% +% {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} +% +% \def\syst_helpers_sixtuple_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% #1[][][][][][]} +% +% \def\syst_helpers_sixtuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_sixtuple_empty_two_spaced +% \else +% \expandafter\syst_helpers_sixtuple_empty_two_normal +% \fi} +% +% \def\syst_helpers_sixtuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_sixtuple_empty_three_spaced +% \else +% \expandafter\syst_helpers_sixtuple_empty_three_normal +% \fi} +% +% \def\syst_helpers_sixtuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_sixtuple_empty_four_spaced +% \else +% \expandafter\syst_helpers_sixtuple_empty_four_normal +% \fi} +% +% \def\syst_helpers_sixtuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_sixtuple_empty_five_spaced +% \else +% \expandafter\syst_helpers_sixtuple_empty_five_normal +% \fi} +% +% \def\syst_helpers_sixtuple_empty_six_nop +% {\sixthargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_sixtuple_empty_six_spaced +% \else +% \expandafter\syst_helpers_sixtuple_empty_six_normal +% \fi} +% +% \def\syst_helpers_sixtuple_empty_two_spaced #1#2{#1[{#2}][][][][][] } +% \def\syst_helpers_sixtuple_empty_two_normal #1#2{#1[{#2}][][][][][]} +% \def\syst_helpers_sixtuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][] } +% \def\syst_helpers_sixtuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][]} +% \def\syst_helpers_sixtuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] } +% \def\syst_helpers_sixtuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]} +% \def\syst_helpers_sixtuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] } +% \def\syst_helpers_sixtuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]} +% \def\syst_helpers_sixtuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] } +% \def\syst_helpers_sixtuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]} \unexpanded\def\dosixtupleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_sixtuple_empty_one_yes#1} - {\syst_helpers_sixtuple_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_one_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_one_yes#1[#2]% +\def\syst_helpers_sixtuple_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_sixtuple_empty_two_yes#1{#2}}% - {\syst_helpers_sixtuple_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_two_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]% +\def\syst_helpers_sixtuple_empty_two_yes[#1]% {\secondargumenttrue - \doifelsenextoptional - {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}% - {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_three_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_three_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]% +\def\syst_helpers_sixtuple_empty_three_yes[#1]% {\thirdargumenttrue - \doifelsenextoptional - {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}% - {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_four_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_four_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]% +\def\syst_helpers_sixtuple_empty_four_yes[#1]% {\fourthargumenttrue - \doifelsenextoptional - {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% - {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_five_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_five_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]% +\def\syst_helpers_sixtuple_empty_five_yes[#1]% {\fifthargumenttrue - \doifelsenextoptional - {\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}% - {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_sixtuple_empty_six_yes + \let\m_syst_action_nop\syst_helpers_sixtuple_empty_six_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_sixtuple_empty_one_nop#1% +\def\syst_helpers_sixtuple_empty_one_nop {\firstargumentfalse \secondargumentfalse \thirdargumentfalse \fourthargumentfalse \fifthargumentfalse \sixthargumentfalse - #1[][][][][][]} + \the\t_syst_aux[][][][][][]} \def\syst_helpers_sixtuple_empty_two_nop {\secondargumentfalse @@ -2541,9 +3015,9 @@ \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_sixtuple_empty_two_spaced + \expandafter\syst_helpers_empty_spaced_five \else - \expandafter\syst_helpers_sixtuple_empty_two_normal + \expandafter\syst_helpers_empty_normal_five \fi} \def\syst_helpers_sixtuple_empty_three_nop @@ -2552,9 +3026,9 @@ \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_sixtuple_empty_three_spaced + \expandafter\syst_helpers_empty_spaced_four \else - \expandafter\syst_helpers_sixtuple_empty_three_normal + \expandafter\syst_helpers_empty_normal_four \fi} \def\syst_helpers_sixtuple_empty_four_nop @@ -2562,84 +3036,215 @@ \fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_sixtuple_empty_four_spaced + \expandafter\syst_helpers_empty_spaced_three \else - \expandafter\syst_helpers_sixtuple_empty_four_normal + \expandafter\syst_helpers_empty_normal_three \fi} \def\syst_helpers_sixtuple_empty_five_nop {\fifthargumentfalse \sixthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_sixtuple_empty_five_spaced + \expandafter\syst_helpers_empty_spaced_two \else - \expandafter\syst_helpers_sixtuple_empty_five_normal + \expandafter\syst_helpers_empty_normal_two \fi} \def\syst_helpers_sixtuple_empty_six_nop {\sixthargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_sixtuple_empty_six_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_sixtuple_empty_six_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_sixtuple_empty_two_spaced #1#2{#1[{#2}][][][][][] } -\def\syst_helpers_sixtuple_empty_two_normal #1#2{#1[{#2}][][][][][]} -\def\syst_helpers_sixtuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][] } -\def\syst_helpers_sixtuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][]} -\def\syst_helpers_sixtuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] } -\def\syst_helpers_sixtuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]} -\def\syst_helpers_sixtuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] } -\def\syst_helpers_sixtuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]} -\def\syst_helpers_sixtuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] } -\def\syst_helpers_sixtuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]} +%D Seventuple: -%D Seven: +% \unexpanded\def\doseventupleempty#1% +% {\syst_helpers_argument_reset +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_one_yes#1}% +% {\syst_helpers_seventuple_empty_one_nop#1}} +% +% \def\syst_helpers_seventuple_empty_one_yes#1[#2]% +% {\firstargumenttrue +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_two_yes#1{#2}}% +% {\syst_helpers_seventuple_empty_two_nop#1{#2}}} +% +% \def\syst_helpers_seventuple_empty_two_yes#1#2[#3]% +% {\secondargumenttrue +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}% +% {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}} +% +% \def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]% +% {\thirdargumenttrue +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}% +% {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}} +% +% \def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]% +% {\fourthargumenttrue +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% +% {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} +% +% \def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]% +% {\fifthargumenttrue +% \doifelsenextoptional +% {\syst_helpers_seventuple_empty_six_yes#1{#2}{#3}{#4}{#5}{#6}}% +% {\syst_helpers_seventuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} +% +% \def\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]% +% {\sixthargumenttrue +% \doifelsenextoptional +% {\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}% +% {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}} +% +% \def\syst_helpers_seventuple_empty_one_nop#1% +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% #1[][][][][][][]} +% +% \def\syst_helpers_seventuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_two_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_two_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_three_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_three_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_four_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_four_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_five_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_five_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_six_nop +% {\sixthargumentfalse +% \seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_six_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_six_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_seven_nop +% {\seventhargumentfalse +% \if_next_blank_space_token +% \expandafter\syst_helpers_seventuple_empty_seven_spaced +% \else +% \expandafter\syst_helpers_seventuple_empty_seven_normal +% \fi} +% +% \def\syst_helpers_seventuple_empty_two_spaced #1#2{#1[{#2}][][][][][][] } +% \def\syst_helpers_seventuple_empty_two_normal #1#2{#1[{#2}][][][][][][]} +% \def\syst_helpers_seventuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][][] } +% \def\syst_helpers_seventuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][][]} +% \def\syst_helpers_seventuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] } +% \def\syst_helpers_seventuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]} +% \def\syst_helpers_seventuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] } +% \def\syst_helpers_seventuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]} +% \def\syst_helpers_seventuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] } +% \def\syst_helpers_seventuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]} +% \def\syst_helpers_seventuple_empty_seven_spaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] } +% \def\syst_helpers_seventuple_empty_seven_normal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]} \unexpanded\def\doseventupleempty#1% {\syst_helpers_argument_reset - \doifelsenextoptional - {\syst_helpers_seventuple_empty_one_yes#1}% - {\syst_helpers_seventuple_empty_one_nop#1}} + \t_syst_aux{#1}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_one_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_one_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_one_yes#1[#2]% +\def\syst_helpers_seventuple_empty_one_yes[#1]% {\firstargumenttrue - \doifelsenextoptional - {\syst_helpers_seventuple_empty_two_yes#1{#2}}% - {\syst_helpers_seventuple_empty_two_nop#1{#2}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_two_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_two_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_two_yes#1#2[#3]% +\def\syst_helpers_seventuple_empty_two_yes[#1]% {\secondargumenttrue - \doifelsenextoptional - {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}% - {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_three_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_three_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]% +\def\syst_helpers_seventuple_empty_three_yes[#1]% {\thirdargumenttrue - \doifelsenextoptional - {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}% - {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_four_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_four_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]% +\def\syst_helpers_seventuple_empty_four_yes[#1]% {\fourthargumenttrue - \doifelsenextoptional - {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}% - {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_five_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_five_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]% +\def\syst_helpers_seventuple_empty_five_yes[#1]% {\fifthargumenttrue - \doifelsenextoptional - {\syst_helpers_seventuple_empty_six_yes#1{#2}{#3}{#4}{#5}{#6}}% - {\syst_helpers_seventuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_six_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_six_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]% +\def\syst_helpers_seventuple_empty_six_yes[#1]% {\sixthargumenttrue - \doifelsenextoptional - {\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}% - {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}} + \toksapp\t_syst_aux{[{#1}]}% + \let\m_syst_action_yes\syst_helpers_seventuple_empty_seven_yes + \let\m_syst_action_nop\syst_helpers_seventuple_empty_seven_nop + \let\if_next_blank_space_token\iffalse + \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} -\def\syst_helpers_seventuple_empty_one_nop#1% +\def\syst_helpers_seventuple_empty_one_nop {\firstargumentfalse \secondargumentfalse \thirdargumentfalse @@ -2647,7 +3252,7 @@ \fifthargumentfalse \sixthargumentfalse \seventhargumentfalse - #1[][][][][][][]} + \the\t_syst_aux[][][][][][][]} \def\syst_helpers_seventuple_empty_two_nop {\secondargumentfalse @@ -2657,9 +3262,9 @@ \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_two_spaced + \expandafter\syst_helpers_empty_spaced_six \else - \expandafter\syst_helpers_seventuple_empty_two_normal + \expandafter\syst_helpers_empty_normal_six \fi} \def\syst_helpers_seventuple_empty_three_nop @@ -2669,9 +3274,9 @@ \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_three_spaced + \expandafter\syst_helpers_empty_spaced_five \else - \expandafter\syst_helpers_seventuple_empty_three_normal + \expandafter\syst_helpers_empty_normal_five \fi} \def\syst_helpers_seventuple_empty_four_nop @@ -2680,9 +3285,9 @@ \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_four_spaced + \expandafter\syst_helpers_empty_spaced_four \else - \expandafter\syst_helpers_seventuple_empty_four_normal + \expandafter\syst_helpers_empty_normal_four \fi} \def\syst_helpers_seventuple_empty_five_nop @@ -2690,40 +3295,29 @@ \sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_five_spaced + \expandafter\syst_helpers_empty_spaced_three \else - \expandafter\syst_helpers_seventuple_empty_five_normal + \expandafter\syst_helpers_empty_normal_three \fi} \def\syst_helpers_seventuple_empty_six_nop {\sixthargumentfalse \seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_six_spaced + \expandafter\syst_helpers_empty_spaced_two \else - \expandafter\syst_helpers_seventuple_empty_six_normal + \expandafter\syst_helpers_empty_normal_two \fi} \def\syst_helpers_seventuple_empty_seven_nop {\seventhargumentfalse \if_next_blank_space_token - \expandafter\syst_helpers_seventuple_empty_seven_spaced + \expandafter\syst_helpers_empty_spaced_one \else - \expandafter\syst_helpers_seventuple_empty_seven_normal + \expandafter\syst_helpers_empty_normal_one \fi} -\def\syst_helpers_seventuple_empty_two_spaced #1#2{#1[{#2}][][][][][][] } -\def\syst_helpers_seventuple_empty_two_normal #1#2{#1[{#2}][][][][][][]} -\def\syst_helpers_seventuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][][] } -\def\syst_helpers_seventuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][][]} -\def\syst_helpers_seventuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] } -\def\syst_helpers_seventuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]} -\def\syst_helpers_seventuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] } -\def\syst_helpers_seventuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]} -\def\syst_helpers_seventuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] } -\def\syst_helpers_seventuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]} -\def\syst_helpers_seventuple_empty_seven_spaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] } -\def\syst_helpers_seventuple_empty_seven_normal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]} +%D Aliases: \let\dosingleargument \dosingleempty \let\dodoubleargument \dodoubleempty @@ -2900,7 +3494,7 @@ \begingroup \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop} - \global\let\syst_helpers_get_grouped_argument_e\\ + \glet\syst_helpers_get_grouped_argument_e\\ \endgroup \def\syst_helpers_get_grouped_argument_f @@ -3031,13 +3625,13 @@ %D %D Trivial: -\unexpanded\def\letempty #1{\let#1\empty} -\unexpanded\def\globalletempty#1{\global\let#1\empty} +\unexpanded\def\letempty #1{\let #1\empty} +\unexpanded\def\globalletempty#1{\glet#1\empty} -\unexpanded\def\letvalueempty #1{\expandafter\let\csname#1\endcsname\empty} -\unexpanded\def\letgvalueempty#1{\global\expandafter\let\csname#1\endcsname\empty} -\unexpanded\def\letvaluerelax #1{\expandafter\let\csname#1\endcsname\relax} -\unexpanded\def\letgvalurelax #1{\global\expandafter\let\csname#1\endcsname\relax} +\unexpanded\def\letvalueempty #1{\expandafter\let \csname#1\endcsname\empty} +\unexpanded\def\letgvalueempty#1{\expandafter\glet\csname#1\endcsname\empty} +\unexpanded\def\letvaluerelax #1{\expandafter\let \csname#1\endcsname\relax} +\unexpanded\def\letgvalurelax #1{\expandafter\glet\csname#1\endcsname\relax} \unexpanded\def\relaxvalueifundefined#1% {\ifcsname#1\endcsname \else @@ -3183,17 +3777,25 @@ %D Apart from the prefixes, a few more \type{\expandafters} %D are needed: -\unexpanded\def\newif#1% - {\privatescratchcounter\escapechar - \escapechar\minusone - \expandafter\expandafter\expandafter - \redoglobal\expandafter\expandafter\expandafter - \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}% - \expandafter\expandafter\expandafter - \redoglobal\expandafter\expandafter\expandafter - \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}% - \dodoglobal\@if#1{false}% - \escapechar\privatescratchcounter} +% \unexpanded\def\newif#1% uses the original plain \@if +% {\privatescratchcounter\escapechar +% \escapechar\minusone +% \expandafter\expandafter\expandafter +% \redoglobal\expandafter\expandafter\expandafter +% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}% +% \expandafter\expandafter\expandafter +% \redoglobal\expandafter\expandafter\expandafter +% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}% +% \dodoglobal\@if#1{false}% +% \escapechar\privatescratchcounter} + +\normalprotected\def\newif#1% see syst-ini.mkiv + {\let\new_if_saved\newif + \let\newif\new_if_check + \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }% + \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}% + \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname + \let\newif\new_if_saved} %D Also new: @@ -3245,7 +3847,7 @@ % \bgroup \obeylines % -% \global\let\stoptexdefinition\relax +% \glet\stoptexdefinition\relax % % \unexpanded\gdef\starttexdefinition% % {\bgroup% @@ -3302,7 +3904,7 @@ % \bgroup \obeylines % -% \global\let\stoptexdefinition\relax +% \glet\stoptexdefinition\relax % % \unexpanded\gdef\starttexdefinition% % {\bgroup% @@ -3321,7 +3923,7 @@ \bgroup \obeylines -\global\let\stoptexdefinition\relax +\glet\stoptexdefinition\relax \unexpanded\gdef\starttexdefinition% {\bgroup% @@ -3538,8 +4140,8 @@ \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname{#4}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#4}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \ifnum#3>\zerocount\relax \ifnum#2<#1\relax \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit @@ -3567,7 +4169,7 @@ \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} \unexpanded\def\syst_helpers_recurse_content - {\csname\??recurseaction\recursedepth\endcsname} + {\csname\??recurseaction\the\outerrecurse\endcsname} \unexpanded\def\syst_helpers_stepwise_recurse_yes {\syst_helpers_recurse_content @@ -3591,11 +4193,11 @@ {\syst_helpers_stepwise_recurse_nop\relax} \unexpanded\def\syst_helpers_stepwise_recurse_nop#1#2#3#4% - {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse\minusone} % \unexpanded\def\nonostepwiserecurse#1#2#3% -% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname +% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname % \global\advance\outerrecurse\minusone} \unexpanded\def\dorecurse#1% @@ -3636,16 +4238,16 @@ \unexpanded\def\syst_helpers_recurse_x#1#2% {\global\advance\outerrecurse \plusone - \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#2}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#2}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}} \unexpanded\def\syst_helpers_recurse_y#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\glet\csname\??recurseindex\the\outerrecurse\endcsname\recurselevel \let\recurselevel\!!plusone #2% - \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse \minusone} \unexpanded\def\syst_helpers_recurse_indeed#1#2% from to @@ -3670,7 +4272,7 @@ \syst_helpers_recurse_indeed} \unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3% - {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse \minusone } %D \macros @@ -3708,8 +4310,8 @@ \unexpanded\def\doloop#1% {\global\advance\outerrecurse \plusone - \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#1}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#1}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \let\endofloop\syst_helpers_loop \syst_helpers_loop1} % no \plusone else \recurselevel wrong @@ -3723,7 +4325,7 @@ \unexpanded\def\syst_helpers_loop_nop#1% {\let\endofloop\syst_helpers_loop % new, permits nested \doloop's - \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse\minusone} \unexpanded\def\exitloop % \exitloop quits at end @@ -3771,59 +4373,61 @@ %D \stoptyping \def\syst_helpers_recurse_content - {\csname\??recurseaction\recursedepth\expandafter\expandafter\expandafter\endcsname - \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}} + {\csname\??recurseaction\the\outerrecurse\expandafter\expandafter\expandafter\endcsname + \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\the\outerrecurse}} \unexpanded\def\syst_helpers_recurse_x#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}} \unexpanded\def\syst_helpers_recurse_y#1#2% {\global\advance\outerrecurse \plusone - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \let\recurselevel\!!plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}% + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}% \syst_helpers_recurse_content - \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname + \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse \minusone} -\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 - {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel - \ifnum#3>\zerocount\relax - \ifnum#2<#1\relax - \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit - \else - \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse - \fi - \else - \ifnum#3<\zerocount\relax - \ifnum#1<#2\relax - \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit - \else - \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse - \fi - \else - \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit - \fi - \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}} - \unexpanded\def\doloop#1% {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#1}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#1}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \let\endofloop\syst_helpers_loop \syst_helpers_loop1} % no \plusone else \recurselevel wrong -% faster - +% for instance: +% +% \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 +% {\global\advance\outerrecurse \plusone +% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}% +% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel +% \ifnum#3>\zerocount\relax +% \ifnum#2<#1\relax +% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit +% \else +% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse +% \fi +% \else +% \ifnum#3<\zerocount\relax +% \ifnum#1<#2\relax +% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit +% \else +% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse +% \fi +% \else +% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit +% \fi +% \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}} +% +% faster: +% % \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 % {\global\advance\outerrecurse \plusone -% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% -% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel +% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}% +% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel % \csname @swr% % \ifnum#3>\zerocount % \ifnum#2<#1\else d\fi @@ -3831,17 +4435,19 @@ % \ifnum#1<#2\else r\fi % \fi\fi % \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}} - +% % \let\@swr \syst_helpers_stepwise_exit % \let\@swrd\syst_helpers_stepwise_recurse % \let\@swrr\syst_helpers_stepwise_reverse +% +% nicer: \installsystemnamespace{recursestepwise} \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 {\global\advance\outerrecurse \plusone - \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% - \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel \csname\??recursestepwise % we need the x in order to avoid the \relax that tex adds \ifnum#3>\zerocount @@ -3860,8 +4466,8 @@ % % \def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 % {\global\advance\outerrecurse \plusone -% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}% -% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel +% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}% +% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel % \normalexpanded % {\ifnum#3>\zerocount % \ifnum#2<#1 @@ -3936,10 +4542,10 @@ \unexpanded\def\doloopoverlist#1#2% {\global\advance\outerrecurse\plusone - \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname##1{\edef\recursestring{##1}#2}% - \expandafter\glet\csname\??recurseindex\recursedepth\endcsname\recursestring - \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\recursedepth\endcsname}}% - \expandafter\let\expandafter\recursestring\csname\??recurseindex\recursedepth\endcsname + \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1{\edef\recursestring{##1}#2}% + \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recursestring + \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\the\outerrecurse\endcsname}}% + \expandafter\let\expandafter\recursestring\csname\??recurseindex\the\outerrecurse\endcsname \global\advance\outerrecurse\minusone} %D \macros @@ -4113,14 +4719,22 @@ \def\syst_helpers_check_if_assignment_else#1=#2#3\_e_o_p_{\if#2@}% -\unexpanded\def\doifelseassignment#1% expandable +\unexpanded\def\doifelseassignment#1% {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_ \expandafter\secondoftwoarguments \else \expandafter\firstoftwoarguments \fi} -\let\doifassignmentelse\doifelseassignment +\unexpanded\def\doifelseassignmentcs#1#2#3% + {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_ + \expandafter#3% + \else + \expandafter#2% + \fi} + +\let\doifassignmentelse \doifelseassignment +\let\doifassignmentelsecs\doifelseassignmentcs \newif\ifassignment @@ -4415,16 +5029,14 @@ %D \def\doezomaarwat#1{....#1....} %D \stoptyping %D -%D A disadvantage of this approach is that the tokens that -%D form \type{#1} are fixed the the moment the argument is read -%D in. Normally this is no problem, but for instance verbatim -%D environments adapt the \CATCODES\ of characters and therefore +%D A disadvantage of this approach is that the tokens that form \type{#1} are fixed +%D the the moment the argument is read in. Normally this is no problem, but for +%D instance verbatim environments adapt the \CATCODES\ of characters and therefore %D are not always happy with already fixed tokens. %D -%D Another problem arises when the argument is grouped not by -%D \type{{}} but by \type{\bgroup} and \type{\egroup}. Such an -%D argument fails, because the \type{\bgroup} is een as the -%D argument (which is quite normal). +%D Another problem arises when the argument is grouped not by \type {{}} but by +%D \type {\bgroup} and \type {\egroup}. Such an argument fails, because the \type +%D {\bgroup} is een as the argument (which is quite normal). %D %D The next macro offers a solution for both unwanted %D situations: @@ -4454,9 +5066,8 @@ %D .......... \rightword{the right way} %D \stoptyping %D -%D Here \TEX\ typesets \type{\bf the right way} unbreakable -%D at the end of the line. The solution mentioned before does -%D not work here. We also handle +%D Here \TEX\ typesets \type {\bf the right way} unbreakable at the end of the line. +%D The solution mentioned before does not work here. We also handle %D %D \starttyping %D to be \bold{bold} or not, that's the question @@ -4485,80 +5096,150 @@ % \afterassignment\m_syst_helpers_handle_group_before % \let\next=} -\unexpanded\def\syst_helpers_handle_group_normal#1#2% +% \unexpanded\def\syst_helpers_handle_group_normal#1#2% +% {\bgroup +% \def\m_syst_helpers_handle_group_before{#1}% +% \def\m_syst_helpers_handle_group_after {#2}% +% \afterassignment\m_syst_helpers_handle_group_normal_before +% \let\next=} +% +% \def\m_syst_helpers_handle_group_normal_before +% {\bgroup +% \m_syst_helpers_handle_group_before +% \bgroup +% \aftergroup\m_syst_helpers_handle_group_normal_after} +% +% \def\m_syst_helpers_handle_group_normal_after +% {\m_syst_helpers_handle_group_after +% \egroup +% \egroup} +% +% \unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference) +% {\bgroup +% \def\m_syst_helpers_handle_group_before{#1}% +% \def\m_syst_helpers_handle_group_after {#2}% +% \afterassignment\m_syst_helpers_handle_group_simple_before +% \let\next=} +% +% \def\m_syst_helpers_handle_group_simple_before +% {\bgroup +% \aftergroup\m_syst_helpers_handle_group_simple_after +% \m_syst_helpers_handle_group_before} +% +% \def\m_syst_helpers_handle_group_simple_after +% {\m_syst_helpers_handle_group_after +% \egroup}% +% +% \unexpanded\def\syst_helpers_handle_group_pickup#1#2#3% no inner group (so no kerning interference) +% {\bgroup +% \def\m_syst_helpers_handle_group_before{#1}% +% \def\m_syst_helpers_handle_group_after {#2\egroup#3}% +% \afterassignment\m_syst_helpers_handle_group_pickup_before +% \let\next=} +% +% \def\m_syst_helpers_handle_group_pickup_before +% {\bgroup +% \aftergroup\m_syst_helpers_handle_group_after +% \m_syst_helpers_handle_group_before} +% +% \unexpanded\def\syst_helpers_handle_group_nop +% {\ifnum\currentgrouptype=\semisimplegroupcode +% \expandafter\syst_helpers_handle_group_nop_a +% \else +% \expandafter\syst_helpers_handle_group_nop_b +% \fi} +% +% \def\syst_helpers_handle_group_nop_a#1#2% +% {\def\m_syst_helpers_handle_group_after{#2\endgroup}% +% \begingroup +% \aftergroup\m_syst_helpers_handle_group_after +% #1} +% +% \def\syst_helpers_handle_group_nop_b#1#2% +% {\def\m_syst_helpers_handle_group_after{#2\egroup}% +% \bgroup +% \aftergroup\m_syst_helpers_handle_group_after +% #1} + +\unexpanded\def\syst_helpers_handle_group_nop + {\ifnum\currentgrouptype=\semisimplegroupcode + \expandafter\syst_helpers_handle_group_nop_a + \else + \expandafter\syst_helpers_handle_group_nop_b + \fi} + +\def\syst_helpers_handle_group_nop_a + {\begingroup + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\endgroup + \m_syst_helpers_handle_group_b} + +\def\syst_helpers_handle_group_nop_b + {\bgroup + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\egroup + \m_syst_helpers_handle_group_b} + +\unexpanded\def\syst_helpers_handle_group_normal {\bgroup - \def\m_syst_helpers_handle_group_before{#1}% - \def\m_syst_helpers_handle_group_after {#2}% \afterassignment\m_syst_helpers_handle_group_normal_before \let\next=} \def\m_syst_helpers_handle_group_normal_before {\bgroup - \m_syst_helpers_handle_group_before + \m_syst_helpers_handle_group_b \bgroup - \aftergroup\m_syst_helpers_handle_group_normal_after} - -\def\m_syst_helpers_handle_group_normal_after - {\m_syst_helpers_handle_group_after - \egroup - \egroup} - -% keep: -% -% \unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference) -% {\bgroup -% %def\m_syst_helpers_handle_group_before{\bgroup#1\aftergroup\m_syst_helpers_handle_group_after}% interferes -% \def\m_syst_helpers_handle_group_before{\bgroup\aftergroup\m_syst_helpers_handle_group_after#1}% -% \def\m_syst_helpers_handle_group_after {#2\egroup}% -% \afterassignment\m_syst_helpers_handle_group_before -% \let\next=} + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\egroup + \aftergroup\egroup} -\unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference) +\unexpanded\def\syst_helpers_handle_group_simple% no inner group (so no kerning interference) {\bgroup - \def\m_syst_helpers_handle_group_before{#1}% - \def\m_syst_helpers_handle_group_after {#2}% \afterassignment\m_syst_helpers_handle_group_simple_before \let\next=} \def\m_syst_helpers_handle_group_simple_before {\bgroup \aftergroup\m_syst_helpers_handle_group_simple_after - \m_syst_helpers_handle_group_before} + \m_syst_helpers_handle_group_b} \def\m_syst_helpers_handle_group_simple_after - {\m_syst_helpers_handle_group_after + {\m_syst_helpers_handle_group_a \egroup}% -\unexpanded\def\syst_helpers_handle_group_pickup#1#2#3% no inner group (so no kerning interference) +\unexpanded\def\syst_helpers_handle_group_pickup% no inner group (so no kerning interference) {\bgroup - \def\m_syst_helpers_handle_group_before{#1}% - \def\m_syst_helpers_handle_group_after {#2\egroup#3}% \afterassignment\m_syst_helpers_handle_group_pickup_before \let\next=} \def\m_syst_helpers_handle_group_pickup_before {\bgroup - \aftergroup\m_syst_helpers_handle_group_after - \m_syst_helpers_handle_group_before} + \aftergroup\m_syst_helpers_handle_group_a + \aftergroup\egroup + \aftergroup\m_syst_helpers_handle_group_p + \m_syst_helpers_handle_group_b} -\unexpanded\def\syst_helpers_handle_group_nop +\unexpanded\def\syst_helpers_handle_group_nop_x {\ifnum\currentgrouptype=\semisimplegroupcode - \expandafter\syst_helpers_handle_group_nop_a + \begingroup + \aftergroup\endgroup \else - \expandafter\syst_helpers_handle_group_nop_b - \fi} + \bgroup + \aftergroup\egroup + \fi + \m_syst_helpers_handle_group_b} -\def\syst_helpers_handle_group_nop_a#1#2% - {\def\m_syst_helpers_handle_group_after{#2\endgroup}% - \begingroup - \aftergroup\m_syst_helpers_handle_group_after - #1} +\unexpanded\def\syst_helpers_handle_group_normal_x + {\bgroup + \afterassignment\m_syst_helpers_handle_group_normal_before_x + \let\next=} -\def\syst_helpers_handle_group_nop_b#1#2% - {\def\m_syst_helpers_handle_group_after{#2\egroup}% +\def\m_syst_helpers_handle_group_normal_before_x + {\bgroup + \m_syst_helpers_handle_group_b \bgroup - \aftergroup\m_syst_helpers_handle_group_after - #1} + \aftergroup\egroup + \aftergroup\egroup} %D I considered it a nuisance that %D @@ -4567,25 +5248,61 @@ %D {as grass} %D \stoptyping %D -%D was not interpreted as one would expect. This is due to the -%D fact that \type{\futurelet} obeys blank spaces, and a -%D line||ending token is treated as a blank space. So the final -%D implementation became: +%D was not interpreted as one would expect. This is due to the fact that \type +%D {\futurelet} obeys blank spaces, and a line||ending token is treated as a blank +%D space. So the final implementation became: + +% \unexpanded\def\groupedcommand#1#2% +% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} +% +% \unexpanded\def\groupedcommandcs#1#2% +% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} +% +% \unexpanded\def\triggergroupedcommand#1% +% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{}}{\syst_helpers_handle_group_nop{#1}{}}} +% +% \unexpanded\def\triggergroupedcommandcs#1% +% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{}}{\syst_helpers_handle_group_nop{#1}{}}} +% +% \unexpanded\def\simplegroupedcommand#1#2% +% {\doifelsenextbgroup{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} +% +% \unexpanded\def\pickupgroupedcommand#1#2#3% +% {\doifelsenextbgroup{\syst_helpers_handle_group_pickup{#1}{#2}{#3}}{\syst_helpers_handle_group_nop{#1}{#2}}} \unexpanded\def\groupedcommand#1#2% - {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} + +\unexpanded\def\groupedcommandcs#1#2% + {\let\m_syst_helpers_handle_group_b#1% + \let\m_syst_helpers_handle_group_a#2% + \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop} \unexpanded\def\simplegroupedcommand#1#2% - {\doifelsenextbgroup{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}} + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \doifelsenextbgroupcs\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop} \unexpanded\def\pickupgroupedcommand#1#2#3% - {\doifelsenextbgroup{\syst_helpers_handle_group_pickup{#1}{#2}{#3}}{\syst_helpers_handle_group_nop{#1}{#2}}} + {\def\m_syst_helpers_handle_group_b{#1}% + \def\m_syst_helpers_handle_group_a{#2}% + \def\m_syst_helpers_handle_group_p{#2}% + \doifelsenextbgroupcs\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop} -%D Users should be aware of the fact that grouping can -%D interfere with ones paragraph settings that are executed -%D after the paragraph is closed. One should therefore -%D explictly close the paragraph with \type{\par}, else the -%D settings will be forgotten and not applied. So it's: +\unexpanded\def\triggergroupedcommand#1% + {\def\m_syst_helpers_handle_group_b{#1}% + \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} + +\unexpanded\def\triggergroupedcommandcs#1% + {\let\m_syst_helpers_handle_group_b#1% + \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x} + +%D Users should be aware of the fact that grouping can interfere with ones paragraph +%D settings that are executed after the paragraph is closed. One should therefore +%D explictly close the paragraph with \type {\par}, else the settings will be +%D forgotten and not applied. So it's: %D %D \starttyping %D \def\BoldRaggedCenter% @@ -5392,7 +6109,7 @@ \fi} \unexpanded\def\globalprocesscommalist[#1]#2% - {\global\let\m_syst_helpers_comma_list_command_global#2% + {\glet\m_syst_helpers_comma_list_command_global#2% \expandafter\syst_helpers_comma_list_command_global_step#1,],} %D \macros @@ -5454,9 +6171,9 @@ \unexpanded\def\swapcounts#1#2{\c_syst_helpers_swapped #1\relax#1#2\relax#2\c_syst_helpers_swapped} \unexpanded\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let #1#2\let #2\m_syst_helpers_swapped} -\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global #1#2\global #2\d_syst_helpers_swapped} -\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global #1#2\global #2\c_syst_helpers_swapped} -\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\global\let#1#2\global\let#2\m_syst_helpers_swapped} +\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global#1#2\global#2\d_syst_helpers_swapped} +\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global#1#2\global#2\c_syst_helpers_swapped} +\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet #1#2\glet #2\m_syst_helpers_swapped} %D \macros %D {pushmacro,popmacro} @@ -5481,11 +6198,11 @@ % \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname % \fi % \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone -% \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} +% \expandafter\glet\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} % % \unexpanded\def\globalpopmacro#1% % {\xdef\m_syst_helpers_push_macro{\string#1}% -% \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname +% \expandafter\glet\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname % \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone} % % \unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup @@ -5494,7 +6211,7 @@ % \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname % \fi % \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \plusone -% \global\expandafter\let\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} +% \expandafter\glet\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1} % % \unexpanded\def\localpopmacro#1% % {\xdef\m_syst_helpers_push_macro{\string#1}% @@ -5505,6 +6222,8 @@ % \let\popmacro \localpopmacro % % slightly faster but more important: less tracing +% +% possible optimization \installmacrostack\foo: \syst_push_foo \syst_pop_foo \let\m_syst_helpers_push_macro\empty @@ -5525,7 +6244,7 @@ \else \syst_helpers_push_macro_new_global \fi - \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1} + \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1} \unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup {\xdef\m_syst_helpers_push_macro{\csstring#1}% @@ -5534,13 +6253,13 @@ \else \syst_helpers_push_macro_new_local \fi - \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1} + \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1} \unexpanded\def\globalpopmacro#1% {\xdef\m_syst_helpers_push_macro{\csstring#1}% \c_syst_helpers_pop_count\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \global\advance\lastnamedcs \minusone - \global\expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname} + \expandafter\glet\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname} \unexpanded\def\localpopmacro#1% {\xdef\m_syst_helpers_push_macro{\csstring#1}% @@ -6060,7 +6779,7 @@ \unexpanded\def\processassignlist#1[#2]#3% {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]% - {\doifnot{##3}\relax{#3{##1}}}% + {\doif{##3}\relax{#3{##1}}}% \def\syst_helpers_process_assign_list_step##1% {\syst_helpers_process_assign_list_assign[##1==\relax]}% \processcommalist[#2]\syst_helpers_process_assign_list_step} @@ -6996,14 +7715,6 @@ {\unprotect \syst_helpers_unprotected} -% awaiting the definitive implementation - -% \ifdefined\resettimer \else -% \let\resettimer \relax -% \newcount\elapsedtime -% \fi -% \def\elapsedseconds{\expandafter\withoutpt\the\dimexpr\elapsedtime sp\relax} - \let\resettimer \clf_resettimer \let\elapsedtime \clf_elapsedtime \let\elapsedseconds \elapsedtime @@ -7172,6 +7883,12 @@ \unexpanded\def\signalcharacter{\char\zerocount} % \zwj +% \unexpanded\def\signalcharacter +% {\scratchcounter\normallanguage +% \normallanguage\zerocount +% \char\zerocount +% \normallanguage\scratchcounter} + %D A few secial variants of commands defined here. Some more will be moved here (e.g. %D from table modules. @@ -7486,3 +8203,23 @@ % \edef\tempstring{\the#1}% % \tx\ttbf\string#1: \tttf\meaning\tempstring % \endgroup} + +%D Not needed now, but more efficient that expanding +% +% \chardef\_E_O_T_0 +% +% \unexpanded\def\doifelsetokens#1% +% {\dodoifelsetokens#1\_E_O_T_\_e_o_t_} +% +% \def\dodoifelsetokens#1#2\_e_o_t_ +% {\ifx#1\_E_O_T_ +% \expandafter\secondoftwoarguments +% \else +% \expandafter\firstoftwoarguments +% \fi} +% +% \def\emptytokscondition#1% +% {\doemptytokscondition#1\_E_O_T_\_e_o_t_} +% +% \def\doemptytokscondition#1#2\_e_o_t_ +% {\ifx#1\_E_O_T_} diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.lua new file mode 100644 index 00000000000..67595d04381 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.lua @@ -0,0 +1,8 @@ +if not modules then modules = { } end modules ['syst-cmp'] = { + version = 1.001, + comment = "companion to syst-cmp.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.mkiv new file mode 100644 index 00000000000..a5ebdd8e33d --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-cmp.mkiv @@ -0,0 +1,22 @@ +%D \module +%D [ file=syst-cmp, +%D version=2018.12.05, +%D title=\CONTEXT\ System Macros, +%D subtitle=Compatibility, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Some code that has been laying around for generic compatibility is (and will be) +%D moved here, for instance because tikz needs it. At some point I will make an +%D indirect interface for generic code (if needed). + +\registerctxluafile{syst-cmp}{} + +\unprotect + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv index 4b5cc616b46..7ce48c79f66 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-ini.mkiv @@ -19,116 +19,124 @@ %D Characters can have special states, that can be triggered by setting their %D category coded. Some are preset, others are to be set as soon as possible, %D otherwise we cannot define any useful macros. - -%catcode`\^^@ = 9 % ascii null is ignored -%catcode`\\ = 0 % backslash is TeX escape character - -\catcode`\{ = 1 % left brace is begin-group character -\catcode`\} = 2 % right brace is end-group character -\catcode`\$ = 3 % dollar sign is math shift -\catcode`\& = 4 % ampersand is alignment tab -\catcode`\# = 6 % hash mark is macro parameter character -\catcode`\^ = 7 % circumflex and uparrow are for superscripts -\catcode`\_ = 8 % underline and downarrow are for subscripts -\catcode`\^^I = 10 % ascii tab is a blank space - -%catcode`\^^M = 5 % ascii return is end-line -%catcode`\% = 14 % percent sign is comment character -%catcode`\ = 10 % ascii space is blank space -%catcode`\^^? = 15 % ascii delete is invalid - -\catcode`\~ = 13 % tilde is active -\catcode`\^^L = 13 % ascii form-feed - -%catcode`\A = 11 -%....... -%catcode`\Z = 11 - -%catcode`\a = 11 -%....... -%catcode`\z = 11 - -\def ^^L{\par} -\def\^^M{\ } % control = control -\def\^^I{\ } % same for - -%D In \CONTEXT, we simply ignore end||of||file tokens: - -\catcode`\^^Z=9 - -%D It makes sense to know what engine we're running so let's try to deduce it. - -\chardef\unknownengine = 0 -\chardef\pdftexengine = 1 -\chardef\xetexengine = 2 -\chardef\luatexengine = 3 - -\chardef\statuswrite = 128 - -\ifx\directlua\undefined - \ifx\XeTeXversion\undefined - \ifx\pdftexversion\undefined - \let\texengine\unknownengine - \else - \let\texengine\pdftexengine - \fi - \else - \let\texengine\xetexengine - \fi -\else - \let\texengine\luatexengine -\fi - -\ifnum\texengine=\luatexengine - % for historic reasons we keep some mkii code around -\else - \immediate\write\statuswrite{>>>} - \immediate\write\statuswrite{>>> only luatex is supported} - \immediate\write\statuswrite{>>>} - \let\dump\relax - \expandafter\end -\fi +%D +%D First we define a bunch of constants. Normally we would \type {\setconstant} +%D but we're prestine and have no macros defined yet. Abstraction also makes it +%D possible to avoid the \type {^^} in the input. + +\chardef\escapecatcode 0 +\chardef\begingroupcatcode 1 +\chardef\endgroupcatcode 2 +\chardef\mathshiftcatcode 3 +\chardef\alignmentcatcode 4 +\chardef\endoflinecatcode 5 +\chardef\parametercatcode 6 +\chardef\superscriptcatcode 7 +\chardef\subscriptcatcode 8 +\chardef\ignorecatcode 9 +\chardef\spacecatcode 10 +\chardef\lettercatcode 11 +\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode +\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode +\chardef\commentcatcode 14 +\chardef\invalidcatcode 15 + +%chardef\zeroasciicode 0 +\chardef\tabasciicode 9 +\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode +\chardef\formfeedasciicode 12 +\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par +\chardef\endoffileasciicode 26 +\chardef\spaceasciicode 32 +\chardef\exclamationmarkasciicode 33 % ! used in namespace protection +\chardef\doublequoteasciicode 34 % " +\chardef\hashasciicode 35 +\chardef\dollarasciicode 36 +\chardef\commentasciicode 37 +\chardef\ampersandasciicode 38 +\chardef\singlequoteasciicode 39 % ' +\chardef\primeasciicode 39 % ' +\chardef\leftparentasciicode 40 +\chardef\rightparentasciicode 41 +\chardef\hyphenasciicode 45 +\chardef\forwardslashasciicode 47 % / +\chardef\colonasciicode 58 +\chardef\lessthanasciicode 60 % < used as alternative verbatim { +\chardef\morethanasciicode 62 % > used as alternative verbatim } +\chardef\questionmarkasciicode 63 % ? used in namespace protection +\chardef\atsignasciicode 64 % @ used in namespace protection +\chardef\backslashasciicode 92 % `\\ +\chardef\circumflexasciicode 94 +\chardef\underscoreasciicode 95 +\chardef\leftbraceasciicode 123 % `\{ +\chardef\barasciicode 124 % `\| +\chardef\rightbraceasciicode 125 % `\} +\chardef\tildeasciicode 126 % `\~ +\chardef\delasciicode 127 + +%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored +\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space +\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later) +%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line +\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt) +%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space +\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character +\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift +%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character +\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab +%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character +\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts +\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts +\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character +\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character +\catcode\tildeasciicode \activecatcode % `\~ tilde is active +%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid + +\chardef\statuswrite 128 %D Initialization of primitives. -\directlua 0 { % this info is stored in the format - lua.name[0] = "main ctx instance" +\directlua { + local baseprimitives = tex.extraprimitives("core","tex") + local moreprimitives = tex.extraprimitives("etex","luatex") - local coreprimitives = tex.extraprimitives("core") - local texprimitives = tex.extraprimitives("tex") - local etexprimitives = tex.extraprimitives("etex") - local luatexprimitives = tex.extraprimitives("luatex") + tex.enableprimitives("",moreprimitives) - tex.enableprimitives("",etexprimitives) - tex.enableprimitives("",luatexprimitives) + tex.enableprimitives("normal",baseprimitives) + tex.enableprimitives("normal",moreprimitives) - tex.enableprimitives("normal",coreprimitives) - tex.enableprimitives("normal",texprimitives) - tex.enableprimitives("normal",etexprimitives) - tex.enableprimitives("normal",luatexprimitives) + function tex.enableprimitives() end } -%D \ETEX\ has a not so handy way of telling you the version number, i.e. the revision -%D number has a period in it: +\def\space{ } +\def\empty{} + +\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed +\letcharcode \tildeasciicode \ % tilde +\letcharcode \spaceasciicode \space % space -\def\gobbleoneargument#1{} % will be defined later on anyway +\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab +\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed +\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return -\mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax +%D For now: + +\def\gobbleoneargument#1{} % will be defined later on anyway %D First we define a simplified version of the \CONTEXT\ protection mechanism. %D Later we will implement a better variant. \def\unprotect {\edef\protect - {\catcode`@=\the\catcode`@\relax - \catcode`?=\the\catcode`?\relax - \catcode`!=\the\catcode`!\relax - \catcode`_=\the\catcode`_\relax + {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax + \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax + \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax + \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax \let\protect\relax}% - \catcode`@=11 - \catcode`?=11 - \catcode`!=11 - \catcode`_=11 } + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\underscoreasciicode \lettercatcode} \let\protect\relax @@ -169,13 +177,13 @@ \countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 16 \countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 \countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 255 -\countdef \c_syst_max_allocated_insert = 58 \c_syst_max_allocated_insert = 254 -\countdef \c_syst_min_allocated_insert = 59 \c_syst_min_allocated_insert = 128 +\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 +\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 \countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 \countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 -\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 127-1023 : private -\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 % luatex >= 0.82 -\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127 % luatex >= 0.82 +\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private +\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 +\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127 \countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register \countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register @@ -212,10 +220,10 @@ % A few traditional allocations (these might go): -\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there -\dimendef \dimen@ = 0 -\dimendef \dimen@i = 1 % global only -\dimendef \dimen@ii = 2 +\countdef \count@ 255 % hm, used in \newif .. todo: replace it there +\dimendef \dimen@ 0 +\dimendef \dimen@i 1 % global only +\dimendef \dimen@ii 2 %D So, effectively we start allocating from 256 and upwards. The inserts sit in the %D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is @@ -258,8 +266,7 @@ % %D The next definitions are really needed (in \CONTEXT): -%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}} -\newlinechar=10 \edef\outputnewlinechar{^^J} +\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J} %D One reason to start high with allocation is that it permits us to allocate %D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a @@ -268,7 +275,8 @@ %D as all engines now provide many registers we removed all traces. \ifdefined\writestatus \else - \normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}} + %\normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}} + \normalprotected\def\writestatus#1#2{\message{#1: #2}} \fi \def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name @@ -304,6 +312,7 @@ %D 128-1023 are private and should not be touched. \let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone + \normalprotected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} %D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force @@ -344,6 +353,10 @@ \newtoks \scratchtoksfour \newtoks \scratchtoksfive \newtoks \scratchtokssix \newbox \scratchboxfour \newbox \scratchboxfive \newbox \scratchboxsix +\newcount\globalscratchcounterone +\newcount\globalscratchcountertwo +\newcount\globalscratchcounterthree + %D \macros %D {tempstring} @@ -395,19 +408,19 @@ %D More allocations: -\newskip \zeroskip \zeroskip = 0pt plus 0pt minus 0pt -\newdimen \zeropoint \zeropoint = 0pt -\newdimen \onepoint \onepoint = 1pt -\newdimen \halfapoint \halfapoint = 0.5pt -\newdimen \maxdimen \maxdimen = 16383.99999pt -\newcount \maxcount \maxcount = 2147483647 -\newdimen \onebasepoint \onebasepoint = 1bp -\newdimen \scaledpoint \scaledpoint = 1sp -\newdimen \thousandpoint \thousandpoint = 1000pt -\newmuskip\zeromuskip \zeromuskip = 0mu -\newmuskip\onemuskip \onemuskip = 1mu +\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt +\newdimen \zeropoint \zeropoint 0pt +\newdimen \onepoint \onepoint 1pt +\newdimen \halfapoint \halfapoint 0.5pt +\newdimen \maxdimen \maxdimen 16383.99999pt +\newcount \maxcount \maxcount 2147483647 +\newdimen \onebasepoint \onebasepoint 1bp +\newdimen \scaledpoint \scaledpoint 1sp +\newdimen \thousandpoint \thousandpoint 1000pt +\newmuskip\zeromuskip \zeromuskip 0mu +\newmuskip\onemuskip \onemuskip 1mu -\newmuskip\muquad \muquad = 18mu +\newmuskip\muquad \muquad 18mu \let\points \onepoint \let\halfpoint\halfapoint @@ -416,32 +429,35 @@ %D And even more: (todo: countdefs 60+) -%newcount \minusone \minusone = -1 -\newcount \minustwo \minustwo = -2 -%chardef \zerocount = 0 -%chardef \plusone = 1 -\chardef \plustwo = 2 -\chardef \plusthree = 3 -\chardef \plusfour = 4 -\chardef \plusfive = 5 -\chardef \plussix = 6 -\chardef \plusseven = 7 -\chardef \pluseight = 8 -\chardef \plusnine = 9 -\chardef \plusten = 10 -\chardef \plussixteen = 16 -\chardef \plushundred = 100 -\chardef \plustwohundred = 200 -\chardef \pluscxxvii = 127 -\chardef \pluscxxviii = 128 -\chardef \pluscclv = 255 -\chardef \pluscclvi = 256 -\chardef \plusthousand = 1000 -\chardef \plustenthousand = 10000 -\chardef \plustwentythousand = 20000 -\chardef \medcard = 32768 -\chardef \maxcard = 65536 % pdftex has less mathchars -\chardef \maxcardminusone = 65535 +%newcount\minusone \minusone -1 +\newcount\minustwo \minustwo -2 +%chardef \zerocount 0 +%chardef \plusone 1 +\chardef \plustwo 2 +\chardef \plusthree 3 +\chardef \plusfour 4 +\chardef \plusfive 5 +\chardef \plussix 6 +\chardef \plusseven 7 +\chardef \pluseight 8 +\chardef \plusnine 9 +\chardef \plusten 10 +\chardef \plussixteen 16 +\chardef \plusfifty 50 +\chardef \plushundred 100 +\chardef \plusonehundred 100 +\chardef \plustwohundred 200 +\chardef \plusfivehundred 500 +\chardef \pluscxxvii 127 +\chardef \pluscxxviii 128 +\chardef \pluscclv 255 +\chardef \pluscclvi 256 +\chardef \plusthousand 1000 +\chardef \plustenthousand 10000 +\chardef \plustwentythousand 20000 +\chardef \medcard 32768 +\chardef \maxcard 65536 % pdftex has less mathchars +\chardef \maxcardminusone 65535 %D \macros %D {doubleexpandafter,tripleexpandafter,expanded,startexpanded} @@ -462,8 +478,8 @@ \def\unvoidbox{\unhbox\voidbox} \def\emptybox {\box \voidbox} % used in initializations so no attributes -\def\emptyvbox{\normalvbox{}} % no copy as we need to set attributes -\def\emptyhbox{\normalhbox{}} % no copy as we need to set attributes +\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes +\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes \let\leavevmode\unvoidbox % we prefer to use \dontleavehmode @@ -506,21 +522,47 @@ %D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}. %D \stopnarrower -\normalprotected\def\newif#1% - {\count@\escapechar - \escapechar\minusone - \expandafter\expandafter\expandafter\def\@if #1{true}{\let#1\iftrue }% - \expandafter\expandafter\expandafter\def\@if#1{false}{\let#1\iffalse}% - \@if#1{false}% the condition starts out false - \escapechar\count@} - -\def\@if#1#2% - {\csname\expandafter\if@\string#1#2\endcsname} +% \normalprotected\def\newif#1% +% {\count@\escapechar +% \escapechar\minusone +% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }% +% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}% +% \new_if#1{false}% the condition starts out false +% \escapechar\count@} +% +% \def\new_if#1#2% +% {\csname\expandafter\if@\string#1#2\endcsname} +% +% \bgroup % `if' is required +% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}} +% \egroup -\bgroup % `if' is required +% We use \csstring so there is no need to push/pop escapechar. +% We use different names so that we get a better error message. +% +% \normalprotected\def\newif#1% +% {\let\new_if_saved\newif +% \let\newif\new_if_check +% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }% +% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}% +% \new_if_cs#1{false}% +% \let\newif\new_if_saved} +% +% \normalprotected\def\new_if_cs#1#2% +% {\csname\expandafter\newif\csstring#1#2\endcsname} +% +% We wrap all into one macro: - \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}} +\normalprotected\def\newif#1% + {\let\new_if_saved\newif + \let\newif\new_if_check + \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }% + \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}% + \csname\expandafter\newif\csstring#1false\endcsname + \let\newif\new_if_saved} +\bgroup + \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}} \egroup %D Let's test this one: @@ -534,32 +576,11 @@ %D A few shortcuts: -\normalprotected\def\glet {\global \let } \normalprotected\def\udef {\normalprotected\def } \normalprotected\def\ugdef{\normalprotected\gdef} \normalprotected\def\uedef{\normalprotected\edef} \normalprotected\def\uxdef{\normalprotected\xdef} -%D The catcode constants will be redefined in later catcode related modules -%D but they can be used in the same way. - -\chardef\escapecatcode = 0 -\chardef\begingroupcatcode = 1 -\chardef\endgroupcatcode = 2 -\chardef\mathshiftcatcode = 3 -\chardef\alignmentcatcode = 4 -\chardef\endoflinecatcode = 5 -\chardef\parametercatcode = 6 -\chardef\superscriptcatcode = 7 -\chardef\subscriptcatcode = 8 -\chardef\ignorecatcode = 9 -\chardef\spacecatcode = 10 -\chardef\lettercatcode = 11 -\chardef\othercatcode = 12 -\chardef\activecatcode = 13 -\chardef\commentcatcode = 14 -\chardef\invalidcatcode = 15 - %D For a while we keep the following, as systems like tikz need it. Best %D not use that one \CONTEXT. @@ -789,7 +810,8 @@ \normalprotected\def\newmacro #1{\let#1\empty} \normalprotected\def\setnewmacro#1{\let#1} -\def\!!plusone{1} +\def\!!zerocount{0} +\def\!!plusone {1} \normalprotected\def\newfraction#1{\let#1\!!plusone} @@ -872,28 +894,28 @@ \let\endgraf\par \let\endline\cr -\def\space{ } -\def\empty{} - \normalprotected\def\null{\hpack{}} %D The following two might be overloaded later on but some modules need then %D earlier. These functionality is reflected in the name and will not change. -\bgroup - \catcode`\^^M=\activecatcode% - \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}% - \global\let^^M\par% -\egroup - -\bgroup - \gdef\obeyspaces{\catcode`\ \activecatcode}% - \obeyspaces\global\let =\space% -\egroup +% \bgroup +% \catcode`\^^M=\activecatcode% +% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}% +% \glet^^M\par% +% \egroup +% +% \bgroup +% \gdef\obeyspaces{\catcode`\ \activecatcode}% +% \obeyspaces\glet =\space% +% \egroup -%D A constant: +\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par} +\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} -\let\endoflinetoken=^^M +% %D A constant: +% +% \let\endoflinetoken=^^M %D Also needed might be a simple loop structure and we borrow plain \TEX's one %D as it is often expected to be present and it is about the fastest you can @@ -948,6 +970,12 @@ \lineskip = 1pt \lineskiplimit = 0pt +%D Sometimes kerns make more sense than glue but we need to be in the +%D right mode: + +\normalprotected\def\vkern{\ifhmode\par \fi\kern} +\normalprotected\def\hkern{\ifvmode\dontleavehmode\fi\kern} + %D Again a few kind-of-extensions the core. These come from plain \TEX\ but %D are probably not used in \CONTEXT. @@ -976,116 +1004,47 @@ %D Backend: -% For the moment we define some \pdf... helpers but this will move to the backend -% module after which the official interfaces have to be used. This is needed for -% modules not made by ctx developers. - -\normalprotected\def\pdfliteral {\pdfextension literal } -\normalprotected\def\pdfcolorstack {\pdfextension colorstack } -\normalprotected\def\pdfsetmatrix {\pdfextension setmatrix } -\normalprotected\def\pdfsave {\pdfextension save\relax} -\normalprotected\def\pdfrestore {\pdfextension restore\relax} -\normalprotected\def\pdfobj {\pdfextension obj } -\normalprotected\def\pdfrefobj {\pdfextension refobj } -\normalprotected\def\pdfannot {\pdfextension annot } -\normalprotected\def\pdfstartlink {\pdfextension startlink } -\normalprotected\def\pdfendlink {\pdfextension endlink\relax} -\normalprotected\def\pdfoutline {\pdfextension outline } -\normalprotected\def\pdfdest {\pdfextension dest } -\normalprotected\def\pdfthread {\pdfextension thread } -\normalprotected\def\pdfstartthread {\pdfextension startthread } -\normalprotected\def\pdfendthread {\pdfextension endthread\relax} -\normalprotected\def\pdfinfo {\pdfextension info } -\normalprotected\def\pdfcatalog {\pdfextension catalog } -\normalprotected\def\pdfnames {\pdfextension names } -\normalprotected\def\pdfincludechars {\pdfextension includechars } -\normalprotected\def\pdffontattr {\pdfextension fontattr } -\normalprotected\def\pdfmapfile {\pdfextension mapfile } -\normalprotected\def\pdfmapline {\pdfextension mapline } -\normalprotected\def\pdftrailer {\pdfextension trailer } -\normalprotected\def\pdfglyphtounicode {\pdfextension glyphtounicode } - -% \chardef\pdfnofullbanner = 1 -% \chardef\pdfnofilename = 2 -% \chardef\pdfnopagenumber = 4 -% \chardef\pdfnoinfodict = 8 -% \chardef\pdfnocreator = 16 -% \chardef\pdfnocreationdate = 32 -% \chardef\pdfnomoddate = 64 -% \chardef\pdfnoproducer = 128 -% \chardef\pdfnotrapped = 256 -% \chardef\pdfnoid = 512 - -\def\pdftexversion {\numexpr\pdffeedback version\relax} -\def\pdftexrevision {\pdffeedback revision} -\def\pdflastlink {\numexpr\pdffeedback lastlink\relax} -\def\pdfretval {\numexpr\pdffeedback retval\relax} -\def\pdflastobj {\numexpr\pdffeedback lastobj\relax} -\def\pdflastannot {\numexpr\pdffeedback lastannot\relax} -\def\pdfxformname {\numexpr\pdffeedback xformname\relax} -\def\pdfcreationdate {\pdffeedback creationdate} -\def\pdffontname {\numexpr\pdffeedback fontname\relax} -\def\pdffontobjnum {\numexpr\pdffeedback fontobjnum\relax} -\def\pdffontsize {\dimexpr\pdffeedback fontsize\relax} -\def\pdfpageref {\numexpr\pdffeedback pageref\relax} -\def\pdfcolorstackinit {\pdffeedback colorstackinit} - -\let\pdfxform \saveboxresource -\let\pdflastxform \lastsavedboxresourceindex -\let\pdfrefxform \useboxresource -\let\pdfximage \saveimageresource -\let\pdflastximage \lastsavedimageresourceindex -\let\pdflastximagepages \lastsavedimageresourcepages -\let\pdfrefximage \useimageresource -\let\pdfsavepos \savepos -\let\pdflastxpos \lastxpos -\let\pdflastypos \lastypos - -\edef\pdfcompresslevel {\pdfvariable compresslevel} \pdfcompresslevel \plusnine -\edef\pdfobjcompresslevel {\pdfvariable objcompresslevel} \pdfobjcompresslevel \plusone -\edef\pdfdecimaldigits {\pdfvariable decimaldigits} \pdfdecimaldigits \plusfive -\edef\pdfgamma {\pdfvariable gamma} \pdfgamma \plusthousand -\edef\pdfimageresolution {\pdfvariable imageresolution} \pdfimageresolution 300 -\edef\pdfimageapplygamma {\pdfvariable imageapplygamma} \pdfimageapplygamma \zerocount -\edef\pdfimagegamma {\pdfvariable imagegamma} \pdfimagegamma 2200 -\edef\pdfimagehicolor {\pdfvariable imagehicolor} \pdfimagehicolor \plusone -\edef\pdfimageaddfilename {\pdfvariable imageaddfilename} \pdfimageaddfilename \plusone -\edef\pdfpkresolution {\pdfvariable pkresolution} \pdfpkresolution 1200 -\edef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts} \pdfinclusioncopyfonts \plusone -\edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} \pdfinclusionerrorlevel \zerocount -\edef\pdfgentounicode {\pdfvariable gentounicode} \pdfgentounicode \plusone -\edef\pdfpagebox {\pdfvariable pagebox} \pdfpagebox \zerocount -\edef\pdfmajorversion {\pdfvariable majorversion} % \pdfmajorversion \plusone -\edef\pdfminorversion {\pdfvariable minorversion} \pdfminorversion \plusseven -\edef\pdfuniqueresname {\pdfvariable uniqueresname} \pdfuniqueresname \zerocount -\edef\pdfhorigin {\pdfvariable horigin} \pdfhorigin 1in -\edef\pdfvorigin {\pdfvariable vorigin} \pdfvorigin \pdfhorigin -\edef\pdflinkmargin {\pdfvariable linkmargin} \pdflinkmargin \zeropoint -\edef\pdfdestmargin {\pdfvariable destmargin} \pdfdestmargin \zeropoint -\edef\pdfthreadmargin {\pdfvariable threadmargin} \pdfthreadmargin \zeropoint -\edef\pdfxformmargin {\pdfvariable xformmargin} \pdfxformmargin \zeropoint -\edef\pdfpkfixeddpi {\pdfvariable pkfixeddpi} \pdfpkfixeddpi \plusone -\edef\pdfignoreunknownimages {\pdfvariable ignoreunknownimages} \pdfignoreunknownimages \zerocount - -\edef\pdfpagesattr {\pdfvariable pagesattr} -\edef\pdfpageattr {\pdfvariable pageattr} -\edef\pdfpageresources {\pdfvariable pageresources} -\edef\pdfxformattr {\pdfvariable xformattr} -\edef\pdfxformresources {\pdfvariable xformresources} -\edef\pdfpkmode {\pdfvariable pkmode} - -\edef\pdfsuppressoptionalinfo{\pdfvariable suppressoptionalinfo } -\let \pdfsuppressptexinfo \pdfsuppressoptionalinfo -\edef\pdftrailerid {\pdfvariable trailerid } -\edef\pdfinfoomitdate {\pdfvariable suppressoptionalinfo \numexpr32+64\relax} - -\normalprotected\def\nopdfcompression {\pdfobjcompresslevel\zerocount \pdfcompresslevel\zerocount} -\normalprotected\def\maximumpdfcompression{\pdfobjcompresslevel\plusnine \pdfcompresslevel\plusnine } -\normalprotected\def\normalpdfcompression {\pdfobjcompresslevel\plusthree \pdfcompresslevel\plusthree} - -\normalpdfcompression - -\outputmode \zerocount % we generate the format in this mode +\ifdefined\pdfvariable + + \pdfvariable compresslevel \plusthree + \pdfvariable objcompresslevel \plusone + % \pdfvariable recompress \zerocount + \pdfvariable decimaldigits \plussix + \pdfvariable gamma \plusthousand + \pdfvariable imageresolution 300 + \pdfvariable imageapplygamma \zerocount + \pdfvariable imagegamma 2200 + \pdfvariable imagehicolor \plusone + \pdfvariable imageaddfilename \plusone + \pdfvariable pkresolution 1200 + \pdfvariable inclusioncopyfonts \plusone + \pdfvariable inclusionerrorlevel \zerocount + \pdfvariable gentounicode \plusone + \pdfvariable omitcidset \plusone + \pdfvariable omitcharset \plusone + \pdfvariable pagebox \zerocount + % \pdfvariable majorversion % \plusone + \pdfvariable minorversion \plusseven + \pdfvariable uniqueresname \zerocount + \pdfvariable horigin 1in + \pdfvariable vorigin 1in + % \pdfvariable linkmargin \zeropoint + % \pdfvariable destmargin \zeropoint + % \pdfvariable threadmargin \zeropoint + % \pdfvariable xformmargin \zeropoint + \pdfvariable pkfixeddpi \plusone + \pdfvariable ignoreunknownimages \zerocount + +\fi + +\let\nopdfcompression \relax +\let\onlypdfobjectcompression\relax +\let\maximumpdfcompression \relax +\let\normalpdfcompression \relax + +\ifdefined\outputmode + \outputmode \zerocount % we generate the format in this mode +\fi %D Basic status stuff. @@ -1102,12 +1061,10 @@ \def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax} \ifdefined\texenginename \else - %edef\texenginename{luatex} \edef\texenginename{\directlua{tex.print(LUATEXENGINE)}} \fi \ifdefined\texengineversion \else - %edef\texengineversion{\dividenumber{100}\luatexversion.\modulonumber{100}\luatexversion.\luatexrevision} \edef\texengineversion{\directlua{tex.print(LUATEXVERSION)}} \fi @@ -1120,43 +1077,39 @@ \savingvdiscards\plusone %D We only can set this one via directives (system.synctex) and we only support -%D the context variant. +%D the context variant. This will go away completely. \let\synctex\undefined \newcount\synctex \let\normalsynctex\synctex %D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero. -\voffset\zeropoint \let\voffset\relax \newdimen\voffset % prevent messing up -\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset % prevent messing up +\voffset\zeropoint \let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset +\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset + +\ifdefined\pageleftoffset + \let\pageleftoffset \hoffset \let\normalpageleftoffset \hoffset + \let\pagerightoffset \hoffset \let\normalpagerightoffset \hoffset + \let\pagetopoffset \voffset \let\normalpagetopoffset \voffset + \let\pagebottomoffset\voffset \let\normalpagebottomoffset\voffset +\fi %D Handy. -\suppresslongerror \plusone % \let\suppresslongerror \relax -\suppressoutererror \plusone % \let\suppressoutererror \relax -\suppressmathparerror \plusone % \let\suppressmathparerror \relax -\suppressifcsnameerror\plusone % \let\suppressifcsnameerror\relax +\suppresslongerror \plusone +\suppressoutererror \plusone +\suppressmathparerror \plusone +\suppressifcsnameerror\plusone -\matheqnogapstep \zerocount % fr now +\let \suppresslongerror \relax +\newcount\suppresslongerror \let\normalsuppresslongerror \suppresslongerror +\let \suppressoutererror \suppresslongerror \let\normalsuppressoutererror \suppresslongerror +\let \suppressmathparerror \suppresslongerror \let\normalsuppressmathparerror \suppresslongerror +\let \suppressifcsnameerror\suppresslongerror \let\normalsuppressifcsnameerror\suppresslongerror -%D While cleaning this code up a bit I was listening to Heather Nova's \CD\ Redbird. -%D The first song on that \CD\ ends with a few lines suitable for ending this -%D initialization module: -%D -%D \startlines -%D And there's so much I can do for you -%D Given time I know that I can prove -%D Now my world is opened up to you -%D Come inside -%D -%D Welcome to my life -%D Welcome to my world -%D Come inside -%D \stoplines -%D -%D So let's see what \TEX\ can do now that we've opened up the basic machinery. +\matheqnogapstep\zerocount % for now -%D Now we define a few helpers that we need in a very early stage. We hav eno message system -%D yet but redundant definitions are fatal anyway. +%D Now we define a few helpers that we need in a very early stage. We have no +%D message system yet but redundant definitions are fatal anyway. \newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes @@ -1183,30 +1136,4 @@ \let\normalstartdmath \Ustartdisplaymath \let\normalstopdmath \Ustopdisplaymath -%D For now: - -\ifdefined\protrusionboundary \else \let\protrusionboundary\boundary \fi -\ifdefined\wordboundary \else \let\wordboundary \noboundary \fi - -\ifdefined\mathrulesfam \else \newcount\mathrulesfam \fi -\ifdefined\mathrulesmode \else \newcount\mathrulesmode \fi -\ifdefined\mathsurroundmode \else \newcount\mathsurroundmode \fi -\ifdefined\mathitalicsmode \else \newcount\mathitalicsmode \fi -\ifdefined\mathdelimitersmode \else \newcount\mathdelimitersmode \fi -\ifdefined\mathscriptboxmode \else \newcount\mathscriptboxmode \fi - -\ifdefined\hyphenpenaltymode \else \newcount\hyphenpenaltymode \fi -\ifdefined\automatichyphenpenalty \else \newcount\automatichyphenpenalty \fi -\ifdefined\automatichyphenmode \else \newcount\automatichyphenmode \fi -\ifdefined\explicithyphenpenalty \else \newcount\explicithyphenpenalty \fi - -\ifdefined\explicitdiscretionary \else \let\explicitdiscretionary \- \fi -\ifdefined\automaticdiscretionary \else \def\automaticdiscretionary{\Uchar\exhyphenchar} \fi - -\ifdefined\mathpenaltiesmode \else \newcount\mathpenaltiesmode \fi -\ifdefined\prebinoppenalty \else \newcount\prebinoppenalty \fi -\ifdefined\prerelpenalty \else \newcount\prerelpenalty \fi - -\ifdefined\breakafterdirmode \else \newcount\breakafterdirmode \fi - \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua index 35cd221238f..a63c49e8faf 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.lua @@ -15,10 +15,10 @@ local context = context local implement = interfaces.implement local ctx_protected_cs = context.protected.cs -- more efficient -local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments -local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments -local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument -local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument +local ctx_firstoftwoarguments = context.firstoftwoarguments +local ctx_secondoftwoarguments = context.secondoftwoarguments +local ctx_firstofoneargument = context.firstofoneargument +local ctx_gobbleoneargument = context.gobbleoneargument local two_strings = interfaces.strings[2] @@ -105,7 +105,8 @@ local p_first = C((1-P(",")-P(-1))^0) implement { name = "firstinset", arguments = "string", - actions = function(str) context(lpegmatch(p_first,str or "")) end + actions = function(str) context(lpegmatch(p_first,str or "")) end, + public = true, } implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv index ca5f9679ff8..3600dac3460 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-lua.mkiv @@ -19,6 +19,42 @@ \def\expdoif #1#2{\clf_doifsame {#1}{#2}} \def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} +%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road +%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type +%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see +%D other useful applications. + +\ifdefined\immediateassignment + + \def\expandeddoif#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + + \def\expandeddoifnot#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + + \def\expandeddoifelse#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\fi + % \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3 % \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5 diff --git a/Master/texmf-dist/tex/context/base/mkiv/syst-rtp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/syst-rtp.mkiv new file mode 100644 index 00000000000..82c0778b43f --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/syst-rtp.mkiv @@ -0,0 +1,18 @@ +%D \module +%D [ file=syst-rtp, +%D version=2006.10.13, +%D title=\CONTEXT\ Core Macros, +%D subtitle=Run Time Processes, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +\let\executesystemcommand\clf_execute + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv index e9008636886..01a55e313f7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-com.mkiv @@ -15,39 +15,51 @@ \unprotect -\let\VL\relax - -\let\NC\relax -\let\RC\relax -\let\HC\relax -\let\EQ\relax - -\let\RQ\relax -\let\HQ\relax - -\let\NG\relax -\let\NN\relax -\let\ND\relax -\let\NR\relax -\let\NB\relax - +\let\AR\relax +\let\BA\relax +\let\BC\relax +\let\BL\relax \let\CC\relax \let\CL\relax \let\CM\relax \let\CR\relax - -\let\SR\relax +\let\DB\relax +\let\EQ\relax +\let\FB\relax +\let\FL\relax \let\FR\relax -\let\MR\relax +\let\HC\relax +\let\HL\relax +\let\HQ\relax +\let\HR\relax +\let\LB\relax +\let\LL\relax \let\LR\relax -\let\AR\relax - -\let\FL\relax \let\ML\relax -\let\LL\relax +\let\MR\relax +\let\NA\relax +\let\NB\relax +\let\NC\relax +\let\ND\relax +\let\NF\relax +\let\NG\relax +\let\NI\relax +\let\NL\relax +\let\NN\relax +\let\NP\relax +\let\NR\relax +\let\PB\relax +\let\RC\relax +\let\RQ\relax +\let\SR\relax \let\TL\relax -\let\BL\relax -\let\HL\relax -\let\HR\relax +\let\VL\relax + +\installmacrostack\BC +\installmacrostack\EC +\installmacrostack\EQ +\installmacrostack\NC +\installmacrostack\NN +\installmacrostack\NR \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv index 3147fa1cc1a..20ae8bf5a2b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-ltb.mkiv @@ -705,14 +705,14 @@ \else \t_tabl_lines_head\emptytoks \fi - \pushmacro\BC - \pushmacro\EC + \push_macro_BC + \push_macro_EC \def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}% \let\EC\relax} % signal \unexpanded\def\tabl_lines_EH - {\popmacro\EC - \popmacro\BC + {\pop_macro_EC + \pop_macro_BC \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead} \let\startlinetablebody\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv index 9acf2ef363a..ca3d78800ac 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-ntb.mkiv @@ -271,10 +271,10 @@ \letvalue{\??naturaltablesqueeze\v!broad}\donetrue \letvalue{\??naturaltablesqueeze\v!local}\donetrue -\def\tabl_ntb_let_gal{\global\expandafter\let\csname\??naturaltablegal\m_tabl_tbl_level\endcsname} +\def\tabl_ntb_let_gal{\expandafter\glet\csname\??naturaltablegal\m_tabl_tbl_level\endcsname} \def\tabl_ntb_get_gal{\csname\??naturaltablegal\m_tabl_tbl_level\endcsname} -\def\tabl_ntb_let_tal#1{\global\expandafter\let\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname} +\def\tabl_ntb_let_tal#1{\expandafter\glet\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname} \def\tabl_ntb_get_tal#1{\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname} \def\tabl_ntb_set_nob#1{\expandafter\let\csname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone} @@ -291,8 +291,8 @@ %def\tabl_ntb_set_wd#1#2{\expandafter\xdef\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! \def\tabl_ntb_set_ht#1#2{\expandafter\xdef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! -%def\tabl_ntb_let_wd#1#2{\global\expandafter\let\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! -\def\tabl_ntb_let_ht#1#2{\global\expandafter\let\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +%def\tabl_ntb_let_wd#1#2{\expandafter\glet\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! +\def\tabl_ntb_let_ht#1#2{\expandafter\glet\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! \def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} @@ -306,10 +306,10 @@ \def\tabl_ntb_set_dis#1{\expandafter\xdef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_set_aut#1{\expandafter\xdef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_wid#1{\global\expandafter\let\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_hei#1{\global\expandafter\let\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_dis#1{\global\expandafter\let\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! -\def\tabl_ntb_let_aut#1{\global\expandafter\let\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_wid#1{\expandafter\glet\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_hei#1{\expandafter\glet\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_dis#1{\expandafter\glet\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! +\def\tabl_ntb_let_aut#1{\expandafter\glet\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi} \def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi} @@ -1161,13 +1161,11 @@ \def\tabl_ntb_row_stop_boxed {% \noindent % no, else double leftskip in narrower - \normalexpanded - {\t_tabl_ntb - {\the\t_tabl_ntb - % no need for init - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}}} + \etoksapp\t_tabl_ntb + {% no need for init + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} \def\tabl_ntb_row_stop_split {\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname @@ -1177,13 +1175,11 @@ \fi} \def\tabl_ntb_row_stop_split_nop - {\normalexpanded - {\t_tabl_ntb - {\the\t_tabl_ntb - \tabl_ntb_row_align_reset - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}}} + {\etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_reset + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} \def\tabl_ntb_row_stop_split_yes {\begingroup @@ -1192,13 +1188,11 @@ \xdef\m_tabl_ntb_after_split {\naturaltablelocalparameter\c!after}% to be checked \xdef\m_tabl_ntb_same_page {\naturaltablelocalparameter\c!samepage}% \endgroup - \normalexpanded - {\t_tabl_ntb - {\the\t_tabl_ntb - \tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}% - \tabl_ntb_row_align_start - \the\t_tabl_ntb_row - \tabl_ntb_row_align_stop}}} + \etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}% + \tabl_ntb_row_align_start + \the\t_tabl_ntb_row + \tabl_ntb_row_align_stop}} \unexpanded\def\tabl_ntb_row_align_set#1#2#3% {\xdef\m_tabl_ntb_before_split{#1}% @@ -1206,9 +1200,9 @@ \xdef\m_tabl_ntb_same_page {#3}} \unexpanded\def\tabl_ntb_row_align_reset - {\global\let\m_tabl_ntb_before_split\empty - \global\let\m_tabl_ntb_after_split \empty - \global\let\m_tabl_ntb_same_page \empty} + {\glet\m_tabl_ntb_before_split\empty + \glet\m_tabl_ntb_after_split \empty + \glet\m_tabl_ntb_same_page \empty} \def\tabl_ntb_prelocate_error {\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}} @@ -1225,12 +1219,10 @@ \tabl_ntb_prelocate_error \fi}% \def\tabl_ntb_row_stop - {\normalexpanded - {\t_tabl_ntb - {\the\t_tabl_ntb - \tabl_ntb_row_align_start - \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname - \tabl_ntb_row_align_stop}}}% + {\etoksapp\t_tabl_ntb + {\tabl_ntb_row_align_start + \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname + \tabl_ntb_row_align_stop}}% \global\c_tabl_prelocated_rows#1\relax} \def\tabl_ntb_prelocate_okay @@ -1344,37 +1336,23 @@ {\global\advance\c_tabl_ntb_col\plusone \kern\d_tabl_ntb_columndistance} -% \setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2% -% {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax -% \ifnum\scratchcounter>\zerocount -% \normalexpanded -% {\t_tabl_ntb_row -% {\the\t_tabl_ntb_row -% \tabl_ntb_span{\the\scratchcounter}% -% \tabl_ntb_plus}}% -% \fi} - \setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2% {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax \ifnum\scratchcounter>\zerocount - \normalexpanded - {\t_tabl_ntb_row - {\the\t_tabl_ntb_row - \tabl_ntb_span{\the\scratchcounter}}}% + \etoksapp\t_tabl_ntb_row + {\tabl_ntb_span{\the\scratchcounter}}% \fi} \setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2% - {\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_pass #1 #2 }% space delimited -> less tokens + {\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 - \normalexpanded - {\t_tabl_ntb_row - {\the\t_tabl_ntb_row - \ifnum\scratchcounter=\plusone - \tabl_ntb_plus - \else - \tabl_ntb_skip{\the\scratchcounter}% - \fi}}% + \etoksapp\t_tabl_ntb_row + {\ifnum\scratchcounter=\plusone + \tabl_ntb_plus + \else + \tabl_ntb_skip{\the\scratchcounter}% + \fi}% \fi} \unexpanded\def\tabl_ntb_cell#1#2% diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv index 54b18a38590..631f29bc084 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tab.mkiv @@ -417,7 +417,7 @@ % Key "a": a{TOKENS} adds TOKENS to the right of (after) the template \newtableformatkey a#1% - {\!taDataColumnTemplate\expandafter{\the\!taDataColumnTemplate #1}% + {\toksapp\!taDataColumnTemplate{#1}% \doreadtableformatkeys} % Key "\{": Enclose template in braces. @@ -435,7 +435,7 @@ \scratchtoks\emptytoks \!thLoop \ifnum\scratchcounter>\zerocount - \scratchtoks\expandafter{\the\scratchtoks#2}% + \toksapp\scratchtoks{#2}% \advance\scratchcounter\minusone \repeat \expandafter\doreadtableformatkeys\the\scratchtoks} @@ -688,7 +688,7 @@ % extensions \newtableformatkey q% - {\letempty\!tqStyle + {\let\!tqStyle\empty \futurelet\!tnext\!tqTestForBracket} \newtableformatkey Q% @@ -928,7 +928,7 @@ \global\c_tabl_table_n_of_vrules\plusone \unskip \fi - \global\let\m_tabl_table_vrule_color\empty + \glet\m_tabl_table_vrule_color\empty \hfil \aligntab} @@ -1370,8 +1370,8 @@ {\tabl_tables_chuck_auto_row % before the tail, else noalign problem \tabl_table_insert_tail \starttablenoalign - \global\let\tabl_table_head\empty - \global\let\tabl_table_tail\empty + \glet\tabl_table_head\empty + \glet\tabl_table_tail\empty \stoptablenoalign \tabl_table_finish \ifx\p_tabl_table_frame\empty @@ -1481,7 +1481,7 @@ \tabl_table_restart % \starttablenoalign % \globalpushmacro\simpletableHL -% \global\let\simpletableHL\doverysimpletableHL +% \glet\simpletableHL\doverysimpletableHL % \stoptablenoalign \tabl_table_insert_head \ifsplittables \ifconditional \c_tabl_table_repeat_tail @@ -1593,8 +1593,8 @@ \egroup \dontcomplain \tabl_table_split_box\tablecontentbox - \global\let\tabl_table_head\empty % new here - \global\let\tabl_table_tail\empty % new here + \glet\tabl_table_head\empty % new here + \glet\tabl_table_tail\empty % new here \flushnotes \egroup} @@ -1691,8 +1691,8 @@ \starttablenoalign \nobreak \tabl_table_set_action\tableunknownstate - \globalletempty\tabl_tables_check_auto_row - \globalletempty\tabl_tables_chuck_auto_row + \glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty \global\currenttablecolumn\zerocount \stoptablenoalign} @@ -1816,21 +1816,21 @@ %D the last row. \unexpanded\def\tabl_table_AR - {\globallet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed - \globallet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} + {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed + \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} \let\tabl_tables_check_auto_row\empty \let\tabl_tables_chuck_auto_row\empty \def\tabl_tables_check_auto_row_indeed - {\globallet\tabl_tables_check_auto_row\empty + {\glet\tabl_tables_check_auto_row\empty \ifnum\tableactionstate=\tablerulestate \FR\else \ifnum\tableactionstate=\tableunknownstate\FR\else \MR\fi\fi} \def\tabl_tables_chuck_auto_row_indeed - {\globalletempty\tabl_tables_check_auto_row - \globalletempty\tabl_tables_chuck_auto_row + {\glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty \ifnum\tableactionstate=\tablerulestate \SR\else \ifnum\tableactionstate=\tableunknownstate\SR\else \LR\fi\fi} @@ -1914,7 +1914,7 @@ \dosingleempty\table_tabl_VL_indeed} \def\table_tabl_VL_indeed[#1]% - {\global\let\m_tabl_table_vrule_color\empty + {\glet\m_tabl_table_vrule_color\empty \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax \iffirstargument \rawprocesscommalist[#1]\tabl_table_vrulecommand @@ -1961,7 +1961,7 @@ \bgroup \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax \iffirstargument - \global\let\m_tabl_table_hrule_color\empty + \glet\m_tabl_table_hrule_color\empty \rawprocesscommalist[#1]\tabl_table_hrulecommand \ifx\m_tabl_table_hrule_color\empty\else \switchtocolor[\m_tabl_table_hrule_color]% @@ -2083,7 +2083,7 @@ \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax \global\c_tabl_table_drule_span\zerocount \iffirstargument - \global\let\m_tabl_table_hrule_color\empty + \glet\m_tabl_table_hrule_color\empty \rawprocesscommalist[#1]\tabl_table_drulecommand % \ifx\m_tabl_table_hrule_color\empty\else % \switchtocolor[\m_tabl_table_hrule_color]% see *DL* diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv index 7a0d2c8a81c..75839caed16 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tbl.mkiv @@ -158,6 +158,7 @@ \newtoks \t_tabl_tabulate_dummy \newtoks \t_tabl_tabulate_every_row \newtoks \t_tabl_tabulate_every_after_row +\newtoks \t_tabl_tabulate_every_real_row \newtoks \t_tabl_tabulate_initializers_first \newtoks \t_tabl_tabulate_initializers_second @@ -174,6 +175,8 @@ \newcount \c_tabl_tabulate_totalnoflines \newcount \c_tabl_tabulate_minusnoflines \newcount \c_tabl_tabulate_align +\newcount \c_tabl_tabulate_nofrealrows +\newcount \c_tabl_tabulate_autocolor \newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser \newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count) @@ -250,6 +253,18 @@ \installcorenamespace{tabulatefoot} \installcorenamespace{tabulatenext} +\prependtoks + \global\c_tabl_tabulate_nofrealrows\zerocount +\to \t_tabl_tabulate_initializers_first + +\prependtoks + \global\c_tabl_tabulate_nofrealrows\zerocount +\to \t_tabl_tabulate_initializers_second + +\prependtoks + \global\advance\c_tabl_tabulate_nofrealrows\plusone +\to \t_tabl_tabulate_every_real_row + \def\b_tabl_tabulate_current#1% {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym @@ -354,8 +369,8 @@ \ifx\m_tabl_tabulate_color_local\empty \xdef\m_tabl_tabulate_color{#1}% \else - \global\let\m_tabl_tabulate_color\m_tabl_tabulate_color_local - \global\let\m_tabl_tabulate_color_local\empty + \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local + \glet\m_tabl_tabulate_color_local\empty \fi \ifcase\c_tabl_tabulate_localcolorspan \global\c_tabl_tabulate_colorspan#2\relax @@ -381,8 +396,8 @@ \ifx\m_tabl_tabulate_vrule_color_local\empty \xdef\m_tabl_tabulate_vrule_color{#1}% \else - \global\let\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local - \global\let\m_tabl_tabulate_vrule_color_local\empty + \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local + \glet\m_tabl_tabulate_vrule_color_local\empty \fi} \let\tabl_tabulate_check_local_color \gobbletwoarguments @@ -553,13 +568,13 @@ \installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip} \installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip} \installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip} -\installtabulatepreambleoption{e}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\global\settrue\c_tabl_tabulate_equal}% +\installtabulatepreambleoption{e}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}% \tabl_tabulate_set_preamble} \installtabulatepreambleoption{g}{\tabl_tabulate_set_align} \installtabulatepreambleoption{.}{\tabl_tabulate_set_align.} \installtabulatepreambleoption{,}{\tabl_tabulate_set_align,} \installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span} -\installtabulatepreambleoption{d}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\fixedspaces}% +\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}% \tabl_tabulate_set_preamble} \installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble} \installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment} @@ -607,18 +622,18 @@ \tabl_tabulate_set_preamble} \def\tabl_tabulate_set_preskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_posskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_preposskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_setups#1% @@ -704,6 +719,28 @@ \fi \tabl_tabulate_set_preamble} +% faster but seldom used +% +% \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} +% +% \def\tabl_tabulate_set_width_step#1% +% {\ifcsname\??tabulatewidth#1\endcsname +% \lastnamedcs +% \else +% \d_tabl_tabulate_width#1\relax +% \fi} +% +% \def\tabl_tabulate_set_width_indeed(#1)% +% {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step +% \ifconditional\c_tabl_tabulate_pwidth_set +% \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth +% \fi +% \tabl_tabulate_set_preamble} +% \def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi} \def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi} \def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi} @@ -772,10 +809,10 @@ \t_tabl_tabulate_emath\emptytoks \t_tabl_tabulate_font\emptytoks \t_tabl_tabulate_settings\emptytoks - \global\let\m_tabl_tabulate_alignment\empty - \global\let\m_tabl_tabulate_color\empty - \global\let\m_tabl_tabulate_text_color\empty - \global\let\m_tabl_tabulate_vrule_color\empty + \glet\m_tabl_tabulate_alignment\empty + \glet\m_tabl_tabulate_color\empty + \glet\m_tabl_tabulate_text_color\empty + \glet\m_tabl_tabulate_vrule_color\empty \global\c_tabl_tabulate_colorspan\zerocount \global\setfalse\c_tabl_auto_align_mode \global\advance\c_tabl_tabulate_columns\plusone @@ -799,8 +836,8 @@ \fi} \def\tabl_tabulate_set_last_entry#1% rulespec - {\global\let\m_tabl_tabulate_color\empty - \global\let\m_tabl_tabulate_vrule_color\empty + {\glet\m_tabl_tabulate_color\empty + \glet\m_tabl_tabulate_vrule_color\empty \edef\currenttabulationtrulespec{#1}% \ifx\currenttabulationtrulespec\empty \global\d_tabl_tabulate_vrulethickness\zeropoint @@ -1176,9 +1213,12 @@ \expandafter\tabl_start_regular_one \fi} +\def\tabl_default_format{|l|p|} + \def\tabl_start_regular_one[#1][#2]% {\doifelseassignment{#1} - {\setupcurrenttabulation[\c!format={|l|p|},#1]} + {\lettabulationparameter\c!format\tabl_default_format + \setupcurrenttabulation[#1]} {\def\p_format{#1}% \ifx\p_format\empty \def\p_format{|l|p|}% @@ -1189,7 +1229,7 @@ \def\tabl_start_regular_two[#1][#2]% {\def\p_format{#1}% \ifx\p_format\empty - \def\p_format{|l|p|}% + \let\p_format\tabl_default_format \fi \lettabulationparameter\c!format\p_format \setupcurrenttabulation[#2]% @@ -1278,7 +1318,7 @@ \fi\fi} \def\tabl_tabulate_outside_after_indeed - {\tabulationparameter\c!after}% + {\tabulationparameter\c!after} \def\tabl_tabulate_outside_inbetween_indeed {\doifempty{\tabulationparameter\c!after} @@ -1313,6 +1353,7 @@ \edef\p_bodyfont {\tabulationparameter\c!bodyfont} \edef\p_indenting {\tabulationparameter\c!indenting}% \edef\p_keeptogether {\tabulationparameter\c!keeptogether}% + \edef\p_blank {\tabulationparameter\c!blank}% % \ifx\p_keeptogether\v!no \settrue \c_tabl_tabulate_tolerant_break @@ -1325,6 +1366,8 @@ \settrue\c_tabl_tabulate_split \csname\??tabulatesplit\tabulationparameter\c!split\endcsname % + \let\m_tabl_tabulate_blank_default\p_blank + % \d_tabl_tabulate_unit\tabulationparameter\c!unit \d_tabl_tabulate_margin\tabulationparameter\c!margin \let\m_tabl_tabulate_vrule_color_default\p_rulecolor @@ -1371,14 +1414,15 @@ \let\m_tabl_tabulate_vrule_color_local \empty \let\m_tabl_tabulate_vrule_color_default\empty % used local \let\m_tabl_tabulate_hrule_color_default\empty % used local +\let\m_tabl_tabulate_blank_default \empty \appendtoks - \global\let\m_tabl_tabulate_color_previous \empty - \global\let\m_tabl_tabulate_color \empty - \global\let\m_tabl_tabulate_text_color \empty - \global\let\m_tabl_tabulate_color_local \empty - \global\let\m_tabl_tabulate_vrule_color \empty - \global\let\m_tabl_tabulate_vrule_color_local \empty + \glet\m_tabl_tabulate_color_previous \empty + \glet\m_tabl_tabulate_color \empty + \glet\m_tabl_tabulate_text_color \empty + \glet\m_tabl_tabulate_color_local \empty + \glet\m_tabl_tabulate_vrule_color \empty + \glet\m_tabl_tabulate_vrule_color_local \empty \global \d_tabl_tabulate_vrulethickness_local\zeropoint \to \t_tabl_tabulate_every_row @@ -1470,7 +1514,7 @@ % ruled columns \def\tabl_tabulate_column_vruled_preset - {\global\let\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default + {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default} \def\tabl_tabulate_column_vruled#1#2% @@ -1513,7 +1557,7 @@ \global\c_tabl_tabulate_max_vrulecolumn\zerocount} \def\tabl_tabulate_vrule_reset_step % undefined or relax - {\global\expandafter\let\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined} + {\expandafter\glet\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined} \appendtoks \tabl_tabulate_vrule_reset @@ -1606,12 +1650,12 @@ \egroup} \def\tabl_tabulate_hrule_spec_ignore#1% - {%\global\let\currenttabulationlocalhrulecolor\empty + {%\glet\currenttabulationlocalhrulecolor\empty %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default \doifelsefastoptionalcheck#1#1} \def\tabl_tabulate_hrule_spec_pickup#1% - {\global\let\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default + {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1} @@ -1625,10 +1669,11 @@ #1} \def\tabl_tabulate_hrule_inject_normal - {\hrule - \s!height.5\d_tabl_tabulate_hrulethickness_local - \s!depth .5\d_tabl_tabulate_hrulethickness_local - \relax} + {\autorule + \s!height .5\d_tabl_tabulate_hrulethickness_local + \s!depth .5\d_tabl_tabulate_hrulethickness_local + \s!left \d_tabl_tabulate_indent + \relax} \def\tabl_tabulate_hrule_inject_colored {\dousecolorparameter\currenttabulationlocalhrulecolor @@ -1686,21 +1731,21 @@ \unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call {\begingroup \clf_enablebackgroundalign % was \node_backgrounds_align_initialize - \global\let\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second + \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second \global\settrue\c_tabl_tabulate_has_colors \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column \fi - \global\expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}% - \hbox \thealignbackgroundcolorattr{#1}{}% pack ? + \expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}% + \hpack \thealignbackgroundcolorattr{#1}{}% pack ? \endgroup} \def\tabl_tabulate_color_repeat_second % for split off lines {\begingroup \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly ! \ifcsname\??tabulatecolor\the\scratchcounter\endcsname - %\hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ? - \hbox \thealignbackgroundcolorattr{\lastnamedcs}{}% pack ? + % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ? + \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\lastnamedcs}{}% pack ? \fi \endgroup} @@ -1722,7 +1767,7 @@ {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step} \def\tabl_tabulate_color_reset_step % undefined or empty? - {\global\expandafter\let\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined} + {\expandafter\glet\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined} \appendtoks \tabl_tabulate_color_reset @@ -1771,17 +1816,20 @@ \tabl_tabulate_register_par_options \to \t_tabl_tabulate_every_row +\def\tabl_tabulate_flush_indent_indeed + {\hbox to \d_tabl_tabulate_indent % pack ? + {% we now have a local hsize, and since we want to + % register positional info (i.e. real hsizes) we + % need to reconstitute the original hsize + \advance\hsize\d_tabl_tabulate_indent + % this is indeed rather messy and took a few hours + % to dis/uncover + \the\t_tabl_tabulate_every_row + \hss}} + \def\tabl_tabulate_flush_indent {\ifnum\c_tabl_tabulate_column=\zerocount - \hbox to \d_tabl_tabulate_indent % pack ? - {% we now have a local hsize, and since we want to - % register positional info (i.e. real hsizes) we - % need to reconstitute the original hsize - \advance\hsize\d_tabl_tabulate_indent - % this is indeed rather messy and took a few hours - % to dis/uncover - \the\t_tabl_tabulate_every_row - \hss}% + \tabl_tabulate_flush_indent_indeed \fi} \def\tabl_tabulate_digits{\digits} @@ -1800,7 +1848,7 @@ \unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} \unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} -\unexpanded\def\tabl_tabulate_xbskip_first{\hbox\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} +\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} \unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} \let\tabl_tabulate_bbskip\relax @@ -1831,12 +1879,12 @@ % \def\tabl_tabulate_break_state_set % {%\writestatus{SET}{\the\c_tabl_tabulate_noflines}% -% \global\expandafter\let\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\conditionaltrue} +% \expandafter\glet\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\conditionaltrue} % % \def\tabl_tabulate_break_state_reset % {\ifcsname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname % %\writestatus{RESET}{\the\c_tabl_tabulate_noflines}% -% \global\expandafter\let\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\undefined +% \expandafter\glet\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\undefined % \fi} % % \def\tabl_tabulate_break_state_allowbreak @@ -1912,8 +1960,6 @@ %D %D \typebuffer \getbuffer -\let\NI\relax - \unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop} \def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC} @@ -2189,7 +2235,7 @@ % \def\tabulatedoHRfive % horizontal rule line (break untested) % {\starttabulatenoalign -% \globallet\dotabulateautoline\dotabulatelinerule +% \glet\dotabulateautoline\dotabulatelinerule % %\ifcase#1\or % todo: check what this does % \ifnum\noftabulatelines=\zerocount % \glet\dotabulateautoline\donothing @@ -2204,9 +2250,9 @@ % \tabl_tabulate_break_no % \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi % \ifnum\noftabulatelines=\totalnoftabulatelines -% \@EA\dotabulatenobreak +% \expandafter\dotabulatenobreak % \else -% \@EA\tabl_tabulate_break_allow +% \expandafter\tabl_tabulate_break_allow % \fi % \stoptabulatenoalign % \dotabulateautoline @@ -2403,8 +2449,8 @@ \dostarttaggedchained\t!tabulate\empty\??tabulation \dostarttagged\t!tabulaterow\empty \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed - \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}% - % \toksapp\everycr{\dostoptagged\dostarttagged\t!tabulaterow\empty}% + % \everycr\expandafter{\the\everycr\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}% + \toksapp\everycr{\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}% \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}% \dostoptagged \dostoptagged @@ -2504,9 +2550,11 @@ \def\tabl_tabulate_TB_indeed[#1]% {\iffirstargument \blank[#1] - \else + \else\ifx\m_tabl_tabulate_blank_default\empty \blank - \fi + \else + \blank[\m_tabl_tabulate_blank_default]% + \fi\fi \stoptabulatenoalign} % to be tested: @@ -2729,4 +2777,295 @@ \unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type} \unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ} +%D Here we plug in a row background feature. As we only have support for +%D \type {frame=name} we can use these variables. +%D +%D \starttyping +%D \startuseMPgraphic{foo} +%D fill unitsquare +%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8) +%D randomized ExHeight +%D shifted (-ExHeight/8,ExHeight/16) +%D withcolor RuleColor ; +%D \stopuseMPgraphic +%D +%D \setuptabulate % wel only have frame=name so we can use these: +%D [background=foo, +%D backgroundcolor=darkred, +%D foregroundcolor=white] +%D +%D \definelinefiller[foo][mp=foo,color=darkgreen] +%D \definelinefiller[bar][mp=foo,color=darkred] +%D +%D \starttabulate[|||] +%D \DB foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate[|||] +%D \PB foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate[|||] +%D \FB[bar] foo \BC bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \startnarrower +%D \starttabulate[|||] +%D \DB foo \DB bar \BC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \stoptabulate +%D \stopnarrower +%D +%D \starttabulate[|||] +%D \BC foo \BC bar \BC \NR +%D \NL[magenta] foo \NC bar \NC \NR +%D \NL[yellow] foo \NC bar \NC \NR +%D \NL[cyan] foo \NC bar \NC \NR +%D \NL[gray] foo \NC bar \NC \NR +%D \stoptabulate +%D +%D \starttabulate +%D \NL[red] foo \NC bar \NC \NR +%D \NL[green] foo \NL[red] bar \NC \NR +%D \NC foo \NC bar \NC \NR +%D \NL[blue] foo \NC \input tufte \NC \NR +%D \NL[gray] foo \NC bar \NC \NR +%D \NL[yellow] foo \NC bar \NC \NR +%D \stoptabulate +%D \stoptyping + +% \setuptabulate +% [\c!background=, +% \c!backgroundcolor=, +% \c!foregroundcolor=, +% \c!foregroundstyle=] + +\let\m_table_current_row_background \empty +\let\m_table_current_row_background_default \empty +\let\m_table_current_row_background_filler \empty +\let\m_table_current_row_background_defaultfiller\empty +\let\m_table_current_row_background_auto \empty + +\unexpanded\def\tabl_register_row_background#1% + {\xdef\m_table_current_row_background{#1}} + +\unexpanded\def\tabl_register_row_background_filler#1% + {\xdef\m_table_current_row_background_filler{#1}} + +\unexpanded\def\tabl_synchronize_row_background + {\iftrialtypesetting\else + \ifx\m_table_current_row_background_filler\empty + \ifx\m_table_current_row_background\empty + % nothing + \tabl_synchronize_row_background_dummy + \else + \tabl_synchronize_row_background_indeed\m_table_current_row_background + \fi + \else + \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler + \fi + \fi} + +\unexpanded\def\tabl_synchronize_row_background_dummy + {\iftrialtypesetting\else + \begingroup + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint + \endgroup + \fi} + +\unexpanded\def\tabl_synchronize_row_background_indeed#1% + {\iftrialtypesetting\else + \begingroup + \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata + \dousecolorparameter{#1}% + \setbox\scratchbox\hpack{}% + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent + \endgroup + \fi} + +\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1% + {\iftrialtypesetting\else + \begingroup + \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata + \node_linefiller_set{#1}% + \setbox\scratchbox\hpack{}% + %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent + \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent + \endgroup + \fi} + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty + \global\c_tabl_tabulate_nofrealrows\zerocount + \global\c_tabl_tabulate_autocolor\zerocount + \clf_resetbackgroundrowdata +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty + \global\c_tabl_tabulate_nofrealrows\zerocount + \global\c_tabl_tabulate_autocolor\zerocount + \clf_resetbackgroundrowdata +\to \t_tabl_tabulate_initializers_second + +\appendtoks + \tabl_synchronize_row_background +\to \t_tabl_tabulate_every_real_row + +\appendtoks + \glet\m_table_current_row_background\empty + \glet\m_table_current_row_background_filler\empty +\to \t_tabl_tabulate_every_after_row + +\unexpanded\def\tabl_tabulate_NL_first[#1]% + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background{#1}% + \fi + \ignorespaces} + +\unexpanded\def\tabl_tabulate_ND_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background\m_table_current_row_background_default + \fi + \ignorespaces} + +\unexpanded\def\tabl_tabulate_LB_first[#1]% + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background{#1}% + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\unexpanded\def\tabl_tabulate_DB_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background\m_table_current_row_background_default + \fi + \let\fontstyle\globalfontstyle + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\unexpanded\def\tabl_tabulate_NF_first[#1]% + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler{#1}% + \fi + \ignorespaces} + +\unexpanded\def\tabl_tabulate_NP_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler\m_table_current_row_background_default_filler + \fi + \ignorespaces} + +\unexpanded\def\tabl_tabulate_FB_first[#1]% + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler{#1}% + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\unexpanded\def\tabl_tabulate_PB_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background_filler\m_table_current_row_background_default_filler + \fi + \let\fontstyle\globalfontstyle + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\unexpanded\def\tabl_tabulate_BC_first % overloaded + {\tabl_tabulate_column_normal\plusone\zerocount + \let\fontstyle\globalfontstyle + \ifx\m_table_current_row_background\empty + \ifx\m_table_current_row_background_filler\empty + \usetabulationstyleandcolor\c!headstyle\c!headcolor + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi} + +\unexpanded\def\tabl_tabulate_A_first + {\global\advance\c_tabl_tabulate_autocolor\plusone + \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% + \ifx\m_table_current_row_background_auto\empty + \global\c_tabl_tabulate_autocolor\plusone + \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% + \fi + \ifx\m_table_current_row_background_auto\empty + \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default + \fi + \tabl_register_row_background{\m_table_current_row_background_auto}} + +\unexpanded\def\tabl_tabulate_NA_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \iftrialtypesetting\else + \ifcase\c_tabl_tabulate_column\or + \tabl_tabulate_A_first + \fi + \fi + \ignorespaces} + +\unexpanded\def\tabl_tabulate_BA_first + {\tabl_tabulate_column_normal\plusone\zerocount\relax + \iftrialtypesetting\else + \ifcase\c_tabl_tabulate_column\or + \tabl_tabulate_A_first + \fi + \fi + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \ignorespaces} + +\appendtoks + \let\NL\tabl_tabulate_NL_first % NC with Line + \let\ND\tabl_tabulate_ND_first % NC with Default Line + \let\LB\tabl_tabulate_LB_first % BC with Line + \let\DB\tabl_tabulate_DB_first % BC with Default Line + \let\NF\tabl_tabulate_NF_first % NC with Filler + \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler + \let\FB\tabl_tabulate_FB_first % BC with Filler + \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler + \let\NA\tabl_tabulate_NA_first % NC with Auto Line + \let\BA\tabl_tabulate_BA_first % NC with Auto Line +\to \t_tabl_tabulate_initializers_first + +\appendtoks + \edef\m_table_current_row_background_default {\tabulateparameter\c!backgroundcolor}% + \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}% + \let \m_table_current_row_background_auto \empty +\to \everytabulate + +\setuptabulate + [\c!headcolor=, + \c!headstyle=\bf, + \c!backgroundcolor=\tabulationparameter\c!rulecolor, + \c!foregroundcolor=, + \c!foregroundstyle=\tabulationparameter\c!headstyle] + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv index 2c4b694b332..e0ddce38a58 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-tsp.mkiv @@ -441,6 +441,35 @@ \exitloop \fi\fi} +%D Maybe handy: +%D +%D \starttyping +%D \splitfloat +%D {\placefigure{some caption}} +%D {\startsplittext +%D \typefile[option=TEX,before=,after=]{oeps.tex} +%D \stopsplittext} +%D \stoptyping + +\def\handlesplittext#1% + {\setbox\tsplitresult\vbox + {\vsplit\tsplitcontent to \dimexpr#1-\lineheight\relax}} + +\unexpanded\def\startsplittext + {\begingroup + \resettsplit + \let\tsplitminimumfreelines\!!zerocount + \let\tsplitminimumfreespace\!!zeropoint + \let\extrasplitfloatlines \!!plusone + \let\tsplitdirectsplitter \handlesplittext + \setbox\tsplitcontent\vbox\bgroup + \insidefloattrue} + +\unexpanded\def\stopsplittext + {\egroup + \handledirecttsplit + \endgroup} + \protect \endinput % test cases diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua index 524ca109c61..c9d50638e67 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.lua @@ -70,7 +70,7 @@ local getbox = nuts.getbox local getwhd = nuts.getwhd local setlink = nuts.setlink -local setdir = nuts.setdir +local setdirection = nuts.setdirection local setshift = nuts.setshift local copy_node_list = nuts.copy_list @@ -84,6 +84,8 @@ local new_glue = nodepool.glue local new_kern = nodepool.kern local new_hlist = nodepool.hlist +local lefttoright_code = nodes.dirvalues.lefttoright + local v_stretch = variables.stretch local v_normal = variables.normal local v_width = variables.width @@ -375,7 +377,8 @@ function xtables.set_reflow_width() -- drc.dimensionstate = dimensionstate -- - local nx, ny = drc.nx, drc.ny + local nx = drc.nx + local ny = drc.ny if nx > 1 or ny > 1 then -- local spans = data.spans -- not used local self = true @@ -886,13 +889,13 @@ function xtables.construct() -- we have a direction issue here but hpack_node_list(list,0,"exactly","TLT") cannot be used -- due to the fact that we need the width local hbox = hpack_node_list(list) - setdir(hbox,"TLT") + setdirection(hbox,lefttoright_code) result[nofr] = { hbox, size, i < nofrange and rowdistance > 0 and rowdistance or false, -- might move false, - rp and rp.samepage or false, + rp or false, } end end @@ -901,7 +904,7 @@ function xtables.construct() result[1] [5] = false result[nofr][5] = false for i=2,nofr-1 do - local r = result[i] + local r = result[i][5] if r == v_both or r == v_before then result[i-1][5] = true elseif r == v_after then diff --git a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi index dc4a30e2b0c..1483043316d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/tabl-xtb.mkvi @@ -102,6 +102,10 @@ \newcount\c_tabl_x_nesting \newcount\c_tabl_x_skip_mode % 1 = skip \newdimen\d_tabl_x_textwidth +\newcount\c_tabl_x_swapped +\newcount\c_tabl_x_swapped_max + +\let\m_tabl_x_swapped_settings\empty \let\currentxtablerow \clf_x_table_r \let\currentxtablecolumn\clf_x_table_c @@ -112,6 +116,7 @@ \installcorenamespace{xtable} \installcorenamespace{xtablecheck} +\installcorenamespace{xtableswap} \installframedautocommandhandler \??xtable {xtable} \??xtable @@ -271,6 +276,8 @@ \let\tabl_x_start_cell_nop\relax \let\tabl_x_stop_cell \relax +\newtoks\t_table_x_cleanup + \unexpanded\def\tabl_x_process {\begingroup % * \forgetall % moved here @@ -296,6 +303,7 @@ % not so nice but needed as we use this in the setup \linewidth\xtableparameter\c!rulethickness\relax % so we freeze it + \c_tabl_x_swapped_max\zerocount \begingroup \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop @@ -305,6 +313,10 @@ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width \settrialtypesetting \tabl_x_get_buffer + \ifcase\c_tabl_x_swapped_max + \else + \tabl_x_flush_swapped + \fi \clf_x_table_reflow_width \endgroup \begingroup @@ -315,7 +327,11 @@ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height \settrialtypesetting - \tabl_x_get_buffer + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi \clf_x_table_reflow_height \endgroup \begingroup @@ -325,7 +341,11 @@ \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop \let\tabl_x_stop_cell \tabl_x_stop_cell_construct - \tabl_x_get_buffer + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi \clf_x_table_construct \endgroup \endgroup % * @@ -340,6 +360,7 @@ \dostoptagged \resetbuffer[\tabl_x_current_buffer]% \resetcharacteralign + \the\t_table_x_cleanup \egroup} % text flow split modes @@ -477,10 +498,6 @@ \unexpanded\def\stopxcell {\tabl_x_stop_cell} -\unexpanded\def\dummyxcell#1% - {\tabl_x_start_cell_nop - \tabl_x_stop_cell} - \unexpanded\def\dummyxcell {\tabl_x_start_cell_nop \tabl_x_stop_cell} @@ -879,4 +896,124 @@ \let\NR\tabl_x_nr \to \everypreparextable +%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting. + +\unexpanded\def\tabl_x_c_cell_start#settings% + {\begingroup + \tabl_x_set_checked{#settings}% + \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} + +\unexpanded\def\tabl_x_c_cell_stop + {\tabl_x_stop_cell + \endgroup} + +% \unexpanded\def\dummyxcell +% {\tabl_x_start_cell_nop +% \tabl_x_stop_cell} + +\def\tabl_x_flush_swapped + {\dorecurse\c_tabl_x_swapped_max + {\expandafter + \startxrow + \the\csname\??xtableswap##1\endcsname\relax + \stopxrow}} + +\def\tabl_x_collect_allocate + {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname} + +\def\tabl_x_collect_advance + {\global\advance\c_tabl_x_swapped\plusone + \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max + \global\c_tabl_x_swapped_max\c_tabl_x_swapped + \fi + \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \ifx\t_tabl_x_swapped\relax + \tabl_x_collect_allocate + \fi} + +\unexpanded\def\tabl_x_collect_cell_start + {\doifelsenextoptionalcs + \tabl_x_collect_cell_start_yes + \tabl_x_collect_cell_start_nop} + +\def\tabl_x_collect_cell_start_nop#content\stopxcell + {\tabl_x_collect_advance + \ifx\m_tabl_x_swapped_settings\empty + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}% + \fi} + +\def\tabl_x_collect_cell_start_yes[#settings]#content\stopxcell + {\tabl_x_collect_advance + \ifx\m_tabl_x_swapped_settings\empty + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}% + \fi + \getdummyparameters[\c!ny=1,#settings]% + \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax + \ifcase\scratchcounter\else + \dorecurse\scratchcounter\tabl_x_collect_advance + \fi} + +\unexpanded\def\startxcolumn % todo: arguments + {\begingroup + \global\c_tabl_x_swapped\zerocount + \let\startxcell\tabl_x_collect_cell_start + \let\stopxcell \relax + \doifelsenextoptionalcs\tabl_x_start_column_yes\tabl_x_start_column_nop} + +\def\tabl_x_start_column_yes[#1]% + {\xdef\m_tabl_x_swapped_settings{#1}} + +\def\tabl_x_start_column_nop + {\glet\m_tabl_x_swapped_settings\empty} + +\unexpanded\def\stopxcolumn + {\endgroup} + +\appendtoks + \dorecurse\c_tabl_x_swapped_max + {\global\csname\??xtableswap\number#1\endcsname\emptytoks}% +\to \t_table_x_cleanup + +%D \stopbuffer +%D \setupxtable[one][foregroundcolor=red] +%D \setupxtable[two][foregroundcolor=blue] +%D +%D \startlinecorrection +%D \startxtable +%D \startxrow[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxrow +%D \startxrow[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxrow +%D \stopxtable +%D \stoplinecorrection +%D +%D \startlinecorrection +%D \startxtable +%D \startxcolumn[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxcolumn +%D \startxcolumn[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxcolumn +%D \stopxtable +%D \stoplinecorrection +%D \stopbuffer +%D +%D \typebuffer \getbuffer + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua index f41fb9b0885..19fff66b8f4 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/task-ini.lua @@ -18,224 +18,132 @@ if not modules then modules = { } end modules ['task-ini'] = { -- not apply the font handler, we can remove all checks for subtypes 255 local tasks = nodes.tasks -local prependaction = tasks.prependaction local appendaction = tasks.appendaction local disableaction = tasks.disableaction local enableaction = tasks.enableaction local freezegroup = tasks.freezegroup local freezecallbacks = callbacks.freeze -appendaction("processors", "normalizers", "languages.replacements.handler") -- disabled - -appendaction("processors", "normalizers", "typesetters.wrappers.handler") -- disabled -appendaction("processors", "normalizers", "typesetters.characters.handler") -- always on -appendaction("processors", "normalizers", "fonts.collections.process") -- disabled -appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled - -appendaction("processors", "characters", "scripts.autofontfeature.handler") -appendaction("processors", "characters", "scripts.splitters.handler") -- disabled -appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled -appendaction("processors", "characters", "typesetters.directions.handler") -- disabled -appendaction("processors", "characters", "typesetters.cases.handler") -- disabled -appendaction("processors", "characters", "typesetters.breakpoints.handler") -- disabled -appendaction("processors", "characters", "scripts.injectors.handler") -- disabled - -------------("processors", "words", "languages.replacements.handler") -- disabled -appendaction("processors", "words", "languages.words.check") -- disabled -- might move up, no disc check needed then -appendaction("processors", "words", "languages.hyphenators.handler") -- always on -appendaction("processors", "words", "typesetters.initials.handler") -- disabled -- might move up -appendaction("processors", "words", "typesetters.firstlines.handler") -- disabled - -appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split") -- experimental -appendaction("processors", "fonts", "nodes.handlers.characters") -- maybe todo -appendaction("processors", "fonts", "nodes.injections.handler") -appendaction("processors", "fonts", "typesetters.fontkerns.handler") -appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nohead") -- maybe todo -appendaction("processors", "fonts", "builders.kernel.ligaturing") -- not always on (could be selective: if only node mode) -appendaction("processors", "fonts", "builders.kernel.kerning") -- not always on (could be selective: if only node mode) -appendaction("processors", "fonts", "nodes.handlers.stripping") -- disabled (might move) -------------("processors", "fonts", "typesetters.italics.handler") -- disabled (after otf/kern handling) -appendaction("processors", "fonts", "nodes.handlers.flatten") - -appendaction("processors", "lists", "typesetters.rubies.check") -- disabled (maybe someplace else) -appendaction("processors", "lists", "typesetters.characteralign.handler") -- disabled (we need to to this after otf appliance) -appendaction("processors", "lists", "typesetters.spacings.handler") -- disabled -appendaction("processors", "lists", "typesetters.kerns.handler") -- disabled -appendaction("processors", "lists", "typesetters.digits.handler") -- disabled (after otf handling) -appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling) -appendaction("processors", "lists", "languages.visualizediscretionaries") -- disabled - -appendaction("processors", "after", "typesetters.marksuspects") - -appendaction("shipouts", "normalizers", "typesetters.showsuspects") -appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler") -- disabled -------------("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled -appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace") -- disabled -appendaction("shipouts", "normalizers", "typesetters.alignments.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.references.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.destinations.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.rules.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.shifts.handler") -- disabled -appendaction("shipouts", "normalizers", "structures.tags.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.handlers.accessibility") -- disabled -appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds") -- disabled -appendaction("shipouts", "normalizers", "nodes.handlers.alignbackgrounds") -- disabled -------------("shipouts", "normalizers", "nodes.handlers.export") -- disabled -appendaction("shipouts", "normalizers", "typesetters.rubies.attach") -- disabled - -appendaction("shipouts", "finishers", "nodes.visualizers.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.colorintents.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.negatives.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.effects.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.viewerlayers.handler") -- disabled - ---maybe integrate relocate and families - -appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nohead") - -appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nohead") -- always on (maybe disabled) -appendaction("math", "normalizers", "noads.handlers.variants", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.families", nil, "nohead") -- always on - -appendaction("math", "normalizers", "noads.handlers.render", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.fixscripts",nil, "nohead") -- * first-- always on -appendaction("math", "normalizers", "noads.handlers.domains", nil, "nohead") -- * last -- disabled -appendaction("math", "normalizers", "noads.handlers.autofences",nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.resize", nil, "nohead") -- always on -------------("math", "normalizers", "noads.handlers.respace", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.alternates",nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.tags", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.classes", nil, "nohead") -- disabled - -appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on -------------("math", "builders", "noads.handlers.italics", nil, "nohead") -- disabled -appendaction("math", "builders", "typesetters.directions.processmath") -- disabled (has to happen pretty late) -appendaction("math", "builders", "noads.handlers.makeup", nil, "nohead") -- disabled (has to happen last) -appendaction("math", "builders", "noads.handlers.align", nil, "nohead") - -appendaction("finalizers", "lists", "typesetters.paragraphs.normalize") -- moved here -appendaction("finalizers", "lists", "typesetters.margins.localhandler") -- disabled -appendaction("finalizers", "lists", "builders.paragraphs.keeptogether") -------------("finalizers", "lists", "nodes.handlers.graphicvadjust") -- todo -appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize") -- experimental -appendaction("finalizers", "lists", "builders.paragraphs.tag") - --- the next can also be in contributers normalizers (when we remove the loop in the handler) - -appendaction("finalizers", "lists", "nodes.linefillers.handler") - -appendaction("contributers", "normalizers", "nodes.handlers.flattenline") -appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds") - --- still experimental - -appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") -- disabled -appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate") - -appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler") -- last ! -appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler") -- here ! - -------------("vboxbuilders", "normalizers", "typesetters.margins.localhandler") -appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler") -appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler") -- here ! - --- experimental too - -appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler") -appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler") - --- rather special (this might get hardcoded): - -prependaction("processors", "before", "nodes.properties.attach") -- enabled but optimized for quick abort -appendaction ("shipouts", "normalizers", "nodes.properties.delayed") -- enabled but optimized for quick abort - --- speedup: only kick in when used - -disableaction("processors", "typesetters.wrappers.handler") -disableaction("processors", "languages.replacements.handler") -disableaction("processors", "typesetters.characteralign.handler") -disableaction("processors", "scripts.autofontfeature.handler") -disableaction("processors", "scripts.splitters.handler") -disableaction("processors", "scripts.injectors.handler") -- was enabled -disableaction("processors", "fonts.collections.process") -disableaction("processors", "fonts.checkers.missing") -disableaction("processors", "chars.handle_breakpoints") -disableaction("processors", "typesetters.cleaners.handler") -disableaction("processors", "typesetters.cases.handler") -disableaction("processors", "typesetters.digits.handler") -disableaction("processors", "typesetters.breakpoints.handler") -disableaction("processors", "typesetters.directions.handler") -disableaction("processors", "languages.words.check") -disableaction("processors", "typesetters.initials.handler") -disableaction("processors", "typesetters.firstlines.handler") -disableaction("processors", "typesetters.spacings.handler") -disableaction("processors", "typesetters.kerns.handler") -disableaction("processors", "typesetters.italics.handler") -disableaction("processors", "languages.visualizediscretionaries") -disableaction("processors", "nodes.handlers.stripping") -disableaction("processors", "builders.paragraphs.solutions.splitters.split") -disableaction("processors", "typesetters.rubies.check") -disableaction("processors", "typesetters.fontkerns.handler") -disableaction("processors", "nodes.handlers.flatten") -disableaction("processors", "typesetters.marksuspects") - -disableaction("shipouts", "typesetters.showsuspects") -disableaction("shipouts", "typesetters.margins.finalhandler") -disableaction("shipouts", "builders.paragraphs.expansion.trace") -disableaction("shipouts", "typesetters.alignments.handler") -disableaction("shipouts", "nodes.rules.handler") -disableaction("shipouts", "nodes.shifts.handler") -disableaction("shipouts", "attributes.colors.handler") -disableaction("shipouts", "attributes.transparencies.handler") -disableaction("shipouts", "attributes.colorintents.handler") -disableaction("shipouts", "attributes.effects.handler") -disableaction("shipouts", "attributes.negatives.handler") -disableaction("shipouts", "attributes.viewerlayers.handler") -disableaction("shipouts", "structures.tags.handler") -disableaction("shipouts", "nodes.visualizers.handler") -disableaction("shipouts", "nodes.handlers.accessibility") -disableaction("shipouts", "nodes.handlers.backgrounds") -disableaction("shipouts", "nodes.handlers.alignbackgrounds") -disableaction("shipouts", "nodes.references.handler") -disableaction("shipouts", "nodes.destinations.handler") --------------("shipouts", "nodes.handlers.export") -disableaction("shipouts", "typesetters.rubies.attach") - -disableaction("finalizers", "typesetters.margins.localhandler") -disableaction("finalizers", "builders.paragraphs.keeptogether") -disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") --------------("finalizers", "nodes.handlers.graphicvadjust") -- sort of obsolete -disableaction("finalizers", "builders.paragraphs.tag") -disableaction("finalizers", "nodes.linefillers.handler") - -disableaction("contributers","nodes.handlers.flattenline") -disableaction("contributers","nodes.handlers.textbackgrounds") - -disableaction("math", "noads.handlers.showtree") -disableaction("math", "noads.handlers.tags") -disableaction("math", "noads.handlers.italics") -disableaction("math", "noads.handlers.collapse") -disableaction("math", "noads.handlers.kernpairs") -disableaction("math", "noads.handlers.domains") -disableaction("math", "noads.handlers.classes") -disableaction("math", "noads.handlers.autofences") -disableaction("math", "noads.handlers.makeup") -disableaction("math", "typesetters.directions.processmath") - -disableaction("mvlbuilders", "typesetters.margins.globalhandler") -disableaction("mvlbuilders", "nodes.handlers.migrate") -disableaction("mvlbuilders", "typesetters.checkers.handler") -disableaction("mvlbuilders", "builders.profiling.pagehandler") - --------------("vboxbuilders","typesetters.margins.localhandler") -disableaction("vboxbuilders","typesetters.checkers.handler") -disableaction("vboxbuilders","builders.profiling.vboxhandler") +------------("processors", "before", "nodes.properties.attach", nil, "nut", "enabled" ) + +appendaction("processors", "normalizers", "typesetters.periodkerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "languages.replacements.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "typesetters.wrappers.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "typesetters.characters.handler", nil, "nut", "enabled" ) +appendaction("processors", "normalizers", "fonts.collections.process", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "fonts.checkers.missing", nil, "nut", "disabled" ) + +appendaction("processors", "characters", "scripts.autofontfeature.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "scripts.splitters.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.cleaners.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.directions.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.cases.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.breakpoints.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "scripts.injectors.handler", nil, "nut", "disabled" ) + +appendaction("processors", "words", "languages.words.check", nil, "nut", "disabled" ) +appendaction("processors", "words", "languages.hyphenators.handler", nil, "nut", "enabled" ) +appendaction("processors", "words", "typesetters.initials.handler", nil, "nut", "disabled" ) +appendaction("processors", "words", "typesetters.firstlines.handler", nil, "nut", "disabled" ) + +appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.characters", nil, "nut", "enabled" ) +appendaction("processors", "fonts", "nodes.injections.handler", nil, "nut", "enabled" ) +appendaction("processors", "fonts", "typesetters.fontkerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nonut", "enabled" ) +appendaction("processors", "fonts", "builders.kernel.ligaturing", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "builders.kernel.kerning", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "builders.kernel.cleanup", nil, "nut", "enabled" ) +appendaction("processors", "fonts", "nodes.handlers.stripping", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.flatten", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "fonts.goodies.colorschemes.coloring", nil, "nut", "disabled" ) + +appendaction("processors", "lists", "typesetters.rubies.check", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.characteralign.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.spacings.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.kerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.digits.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.italics.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "languages.visualizediscretionaries", nil, "nut", "disabled" ) + +appendaction("processors", "after", "typesetters.marksuspects", nil, "nut", "disabled" ) + +appendaction("shipouts", "normalizers", "typesetters.showsuspects", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler", nil, "nut", "disabled" ) +------------("shipouts", "normalizers", "nodes.handlers.cleanuppage", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.alignments.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.references.handler", nil, "nut", "production") +appendaction("shipouts", "normalizers", "nodes.destinations.handler", nil, "nut", "production") +appendaction("shipouts", "normalizers", "nodes.rules.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.shifts.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "structures.tags.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.handlers.accessibility", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.rubies.attach", nil, "nut", "disabled" ) +------------("shipouts", "normalizers", "nodes.properties.delayed", nil, "nut", "production") + +appendaction("shipouts", "finishers", "nodes.visualizers.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.colors.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.transparencies.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.colorintents.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.negatives.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.effects.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.viewerlayers.handler", nil, "nut", "disabled" ) + +appendaction("shipouts", "wrapup", "nodes.handlers.export", nil, "nut", "disabled" ) -- always last +appendaction("shipouts", "wrapup", "luatex.synctex.collect", nil, "nut", "disabled" ) + +appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.unstack", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.variants", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.families", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.render", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.fixscripts", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.domains", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.autofences", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.resize", nil, "nonut", "enabled" ) +------------("math", "normalizers", "noads.handlers.respace", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.alternates", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.tags", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.italics", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.classes", nil, "nonut", "disabled" ) + +appendaction("math", "builders", "builders.kernel.mlist_to_hlist", nil, "nut", "enabled" ) -- mandate +appendaction("math", "builders", "typesetters.directions.processmath", nil, "nut", "disabled" ) +appendaction("math", "builders", "noads.handlers.makeup", nil, "nonut", "disabled" ) +appendaction("math", "builders", "noads.handlers.align", nil, "nonut", "enabled" ) + +appendaction("finalizers", "lists", "typesetters.paragraphs.normalize", nil, "nut", "enabled" ) -- "disabled" +appendaction("finalizers", "lists", "typesetters.margins.localhandler", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "builders.paragraphs.keeptogether", nil, "nut", "disabled" ) +appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize", nil, "nonut", "disabled" ) +appendaction("finalizers", "lists", "builders.paragraphs.tag", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "nodes.linefillers.handler", nil, "nut", "disabled" ) + +appendaction("contributers", "normalizers", "nodes.handlers.flattenline", nil, "nut", "disabled" ) +appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds", nil, "nut", "disabled" ) + +appendaction("vboxbuilders", "normalizers", "nodes.handlers.backgroundsvbox", nil, "nut", "disabled" ) +------------("vboxbuilders", "normalizers", "typesetters.margins.localhandler", nil, "nut", "disabled" ) +appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler", nil, "nut", "enabled" ) +appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler", nil, "nut", "disabled" ) +appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" ) + +appendaction("mvlbuilders", "normalizers", "nodes.handlers.backgroundspage", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler", nil, "nut", "enabled" ) +appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" ) + +appendaction("everypar", "normalizers", "nodes.handlers.checkparcounter", nil, "nut", "disabled" ) + +-- some protection freezecallbacks("find_.*_file", "find file using resolver") freezecallbacks("read_.*_file", "read file at once") @@ -253,8 +161,12 @@ freezegroup("finalizers", "normalizers") freezegroup("finalizers", "fonts") freezegroup("finalizers", "lists") +freezegroup("math", "normalizers") +freezegroup("math", "builders") + freezegroup("shipouts", "normalizers") freezegroup("shipouts", "finishers") +freezegroup("shipouts", "wrapup") freezegroup("mvlbuilders", "normalizers") freezegroup("vboxbuilders", "normalizers") @@ -265,15 +177,14 @@ freezegroup("vboxbuilders", "normalizers") freezegroup("math", "normalizers") freezegroup("math", "builders") --- new: disabled here +freezegroup("everypar", "normalizers") -disableaction("processors", "builders.kernel.ligaturing") -disableaction("processors", "builders.kernel.kerning") +-- new: disabled here directives.register("nodes.basepass", function(v) if v then - enableaction("processors", "builders.kernel.ligaturing") - enableaction("processors", "builders.kernel.kerning") + enableaction("processors", "builders.kernel.ligaturing") + enableaction("processors", "builders.kernel.kerning") else disableaction("processors", "builders.kernel.ligaturing") disableaction("processors", "builders.kernel.kerning") diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-aux.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-aux.mkiv new file mode 100644 index 00000000000..5b43de596f3 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/toks-aux.mkiv @@ -0,0 +1,51 @@ +%D \module +%D [ file=toks-aux, +%D version=2018.11.29, +%D title=\CONTEXT\ Token Support, +%D subtitle=Helpers, +%D author=Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Token Support / Helpers} + +\unprotect + +\installcorenamespace {tokenlist} + +\unexpanded\def\definetokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \global\lastnamedcs\emptytoks + \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi} + +\unexpanded\def\starttokenlist[#1]#2\stoptokenlist + {\ifcsname\??tokenlist#1\endcsname \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi + \toksapp\lastnamedcs{#2}} + +\let\stoptokenlist\relax + +\def\gettokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \the\lastnamedcs + \fi} + +\def\settokenlist[#1]#2% + {\ifcsname\??tokenlist#1\endcsname \else + \expandafter\newtoks\csname\??tokenlist#1\endcsname + \fi + \toksapp\lastnamedcs{#2}} + +\unexpanded\def\resettokenlist[#1]% + {\ifcsname\??tokenlist#1\endcsname + \lastnamedcs\emptytoks + \fi} + +\protect diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua index 15e5df267ef..43e2d80a32b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.lua @@ -18,41 +18,15 @@ local printtable = table.print local concat = table.concat local format = string.format -if setinspector then +if token.commands then - local istoken = token.is_token - local simple = { letter = "letter", other_char = "other" } + local commands = token.commands() - local function astable(t) - if t and istoken(t) then - local cmdname = t.cmdname - local simple = simple[cmdname] - if simple then - return { - category = simple, - character = utfchar(t.mode) or nil, - } - else - return { - command = t.command, - id = t.id, - tok = t.tok, - csname = t.csname, - active = t.active, - expandable = t.expandable, - protected = t.protected, - mode = t.mode, - index = t.index, - cmdname = cmdname, - } - end - end - end + tokens.commands = utilities.storage.allocate(table.swapped(commands,commands)) - tokens.istoken = istoken - tokens.astable = astable +else - setinspector("token",function(v) if istoken(v) then printtable(astable(v),tostring(v)) return true end end) + tokens.commands = { } end @@ -69,6 +43,8 @@ local scan_token = token.scan_token local scan_word = token.scan_word local scan_number = token.scan_number local scan_csname = token.scan_csname +local scan_real = token.scan_real +local scan_float = token.scan_float local get_next = token.get_next @@ -77,25 +53,26 @@ local get_macro = token.get_macro local get_meaning = token.get_meaning local get_cmdname = token.get_cmdname local set_char = token.set_char +local set_lua = token.set_lua + local create_token = token.create +local new_token = token.new +local is_defined = token.is_defined +local is_token = token.is_token -if not set_char then -- for a while - local contextsprint = context.sprint - local ctxcatcodes = catcodes.numbers.ctxcatcodes - set_char = function(n,u) contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",n,u)) end -end +if not is_defined then + + is_defined = function(name) + return get_cmdname(create_token(name)) ~= "undefined_cs" + end -function tokens.defined(name) - return get_cmdname(create_token(name)) ~= "undefined_cs" end --- set_macro = function(k,v,g) --- if g == "global" then --- context.setgvalue(k,v or '') --- else --- context.setvalue(k,v or '') --- end --- end +tokens.new = new_token +tokens.create = create_token +tokens.istoken = is_token +tokens.isdefined = is_defined +tokens.defined = is_defined local bits = { escape = 0x00000001, -- 2^00 @@ -240,6 +217,8 @@ tokens.scanners = { -- these expand glue = scan_glue, skip = scan_glue, integer = scan_int, + real = scan_real, + float = scan_float, count = scan_int, string = scan_string, argument = scan_argument, @@ -268,6 +247,7 @@ tokens.getters = { -- these don't expand tokens.setters = { macro = set_macro, char = set_char, + lua = set_lua, count = tex.setcount, dimen = tex.setdimen, skip = tex.setglue, @@ -297,3 +277,48 @@ tokens.setters = { -- /* unsave_tex_scanner(texstate); */ -- return 1; -- } + +if setinspector then + + local simple = { letter = "letter", other_char = "other" } + + local function astable(t) + if t and is_token(t) then + local cmdname = t.cmdname + local simple = simple[cmdname] + if simple then + return { + category = simple, + character = utfchar(t.mode) or nil, + } + else + return { + command = t.command, + id = t.id, + tok = t.tok, + csname = t.csname, + active = t.active, + expandable = t.expandable, + protected = t.protected, + mode = t.mode, + index = t.index, + cmdname = cmdname, + } + end + end + end + + tokens.astable = astable + + setinspector("token",function(v) local t = astable(v) if t then printtable(t,tostring(v)) return true end end) + +end + +tokens.cache = table.setmetatableindex(function(t,k) + if not is_defined(k) then + set_macro(k,"","global") + end + local v = create_token(k) + t[k] = v + return v +end) diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv index 9d3375432c8..af22d53933e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/toks-ini.mkiv @@ -15,11 +15,6 @@ \unprotect -\newtoks\t_get_macro % will go away - \registerctxluafile{toks-ini}{} -\registerctxluafile{toks-scn}{} -\registerctxluafile{cldf-scn}{} -\registerctxluafile{cldf-stp}{} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua index fe32a1de4d8..f73ecc86c50 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua @@ -106,7 +106,40 @@ local function scanconditional() return nil end +local function scantable(t,data) + if not data then + data = { } + end + local wrapped = scanopen() + while true do + local key = scanword() + if key then + local get = t[key] + if get then + data[key] = get() + else + -- catch all we can get + end + else + break + end + end + if wrapped then + scanclose() + end + return data +end + +function tokens.constant(s) + if type(s) == "string" then + return "'" .. s .. "'" + else + return s + end +end + scanners.list = scanlist +scanners.table = scantable scanners.conditional = scanconditional local shortcuts = { @@ -118,6 +151,7 @@ local shortcuts = { scanstring = scanstring, scaninteger = scaninteger, scannumber = scannumber, + scantable = scantable, scankeyword = scankeyword, scankeywordcs = scankeywordcs, scanword = scanword, @@ -254,6 +288,8 @@ local presets = { ["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" }, } +tokens.presets = presets + function tokens.compile(specification) local f = { } local n = 0 @@ -319,7 +355,7 @@ function tokens.compile(specification) return c end end - local p = t and presets[t] + local p = t and presets[t] -- already done in implement if p then t = p end @@ -460,35 +496,3 @@ end -- } -- -- os.exit() - -function tokens.scantable(t,data) - if not data then - data = { } - end - local wrapped = scanopen() - while true do - local key = scanword() - if key then - local get = t[key] - if get then - data[key] = get() - else - -- catch all we can get - end - else - break - end - end - if wrapped then - scanclose() - end - return data -end - -function tokens.constant(s) - if type(s) == "string" then - return "'" .. s .. "'" - else - return s - end -end diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.mkiv b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.mkiv new file mode 100644 index 00000000000..49edf0c242a --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.mkiv @@ -0,0 +1,22 @@ +%D \module +%D [ file=toks-ini, +%D version=2007.03.03, +%D title=\CONTEXT\ Token Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Token Support / Scanners} + +\unprotect + +\registerctxluafile{toks-scn}{} +\registerctxluafile{cldf-scn}{} +\registerctxluafile{cldf-stp}{} + +\protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua index 03df8682541..95f3052fe6f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-deb.lua @@ -220,7 +220,13 @@ function tracers.printerror(specification) else report_nl() if luaerrorline then - report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror) + if linenumber == 0 or not filename or filename == "" then + print("\nfatal lua error:\n\n",lastluaerror,"\n") + os.exit(1) + return + else + report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror) + end elseif lastmpserror then report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror) else @@ -341,22 +347,25 @@ directives.register("system.showerror", lmx.overloaderror) -- trace_calls(n) -- end) -- indirect is needed for nilling -local editor = [[scite "-open:%filename%" -goto:%linenumber%]] - -directives.register("system.editor",function(v) - editor = v -end) +-- Obsolete ... not that usefull as normally one runs from an editor and +-- when run unattended it makes no sense either. -callback.register("call_edit",function(filename,linenumber) - if editor then - editor = gsub(editor,"%%s",filename) - editor = gsub(editor,"%%d",linenumber) - editor = gsub(editor,"%%filename%%",filename) - editor = gsub(editor,"%%linenumber%%",linenumber) - logs.report("system","starting editor: %s",editor) - os.execute(editor) - end -end) +-- local editor = [[scite "-open:%filename%" -goto:%linenumber%]] +-- +-- directives.register("system.editor",function(v) +-- editor = v +-- end) +-- +-- callback.register("call_edit",function(filename,linenumber) +-- if editor then +-- editor = gsub(editor,"%%s",filename) +-- editor = gsub(editor,"%%d",linenumber) +-- editor = gsub(editor,"%%filename%%",filename) +-- editor = gsub(editor,"%%linenumber%%",linenumber) +-- logs.report("system","starting editor: %s",editor) +-- os.execute(editor) +-- end +-- end) implement { name = "showtrackers", actions = trackers.show } implement { name = "enabletrackers", actions = trackers.enable, arguments = "string" } diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua index 439e8b2dc7c..7a5c35fd5fa 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-inf.lua @@ -82,9 +82,13 @@ local seconds = function(n) return n or 0 end -- -- end -local function starttiming(instance) +local function starttiming(instance,reset) local timer = timers[instance or "notimer"] local it = timer.timing + if reset then + it = 0 + timer.loadtime = 0 + end if it == 0 then timer.starttime = ticks() if not timer.loadtime then @@ -123,6 +127,24 @@ local function elapsed(instance) end end +local function currenttime(instance) + if type(instance) == "number" then + return instance + else + local timer = timers[instance or "notimer"] + local it = timer.timing + if it > 1 then + -- whatever + else + local starttime = timer.starttime + if starttime and starttime > 0 then + return seconds(timer.loadtime + ticks() - starttime) + end + end + return 0 + end +end + local function elapsedtime(instance) return format("%0.3f",elapsed(instance)) end @@ -141,6 +163,7 @@ statistics.hastiming = hastiming statistics.resettiming = resettiming statistics.starttiming = starttiming statistics.stoptiming = stoptiming +statistics.currenttime = currenttime statistics.elapsed = elapsed statistics.elapsedtime = elapsedtime statistics.elapsedindeed = elapsedindeed @@ -229,17 +252,26 @@ end function statistics.runtime() stoptiming(statistics) - -- stoptiming(statistics) -- somehow we can start the timer twice, but where - return statistics.formatruntime(elapsedtime(statistics)) + -- stoptiming(statistics) -- somehow we can start the timer twice, but where + local runtime = lua.getruntime and lua.getruntime() or elapsedtime(statistics) + return statistics.formatruntime(runtime) end local report = logs.reporter("system") -function statistics.timed(action) +function statistics.timed(action,all) starttiming("run") action() stoptiming("run") - report("total runtime: %s seconds",elapsedtime("run")) + local runtime = tonumber(elapsedtime("run")) + if all then + local alltime = tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics)) + if alltime and alltime > 0 then + report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime) + return + end + end + report("total runtime: %0.3f seconds",runtime) end -- goodie diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua index e7a030257aa..aec1844ec5a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-jus.lua @@ -15,7 +15,6 @@ local a_alignstate = attributes.private("alignstate") local a_justification = attributes.private("justification") local nuts = nodes.nuts -local tonut = nuts.tonut local getfield = nuts.getfield local getlist = nuts.getlist @@ -26,8 +25,9 @@ local setlink = nuts.setlink local getwidth = nuts.getwidth local findtail = nuts.tail -local traverse_id = nuts.traverse_id -local list_dimensions = nuts.dimensions +local nexthlist = nuts.traversers.hlist + +local getdimensions = nuts.dimensions local copy_list = nuts.copy_list local tracedrule = nodes.tracers.pool.nuts.rule @@ -77,14 +77,14 @@ trackers.register("visualizers.justification", function(v) end) function checkers.handler(head) - for current in traverse_id(hlist_code,tonut(head)) do + for current in nexthlist, head do if getattr(current,a_justification) == 1 then setattr(current,a_justification,0) -- kind of reset local width = getwidth(current) if width > 0 then local list = getlist(current) if list then - local naturalwidth, naturalheight, naturaldepth = list_dimensions(list) + local naturalwidth, naturalheight, naturaldepth = getdimensions(list) local delta = naturalwidth - width if naturalwidth == 0 or delta == 0 then -- special box diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua index 1471bd4c7f2..206af566803 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-log.lua @@ -405,6 +405,15 @@ if runningtex then setlogfile = ignore settimedlog = ignore + -- settimedlog = function() + -- local localtime = os.localtime + -- local writeline = write_nl + -- write_nl = function(f,...) + -- writeline(f,localtime() .. " | " .. concat { ... }) + -- end + -- settimedlog = ignore + -- end + else local report_yes, subreport_yes, status_yes @@ -758,7 +767,7 @@ if tex then local report = logs.reporter("pages") -- not needed but saves checking when we grep for it local texgetcount = tex and tex.getcount - local real, user, sub + local real, user, sub = 0, 0, 0 function logs.start_page_number() real = texgetcount("realpageno") @@ -766,47 +775,35 @@ if tex then sub = texgetcount("subpageno") end - local timing = false - local starttime = nil - local lasttime = nil + local timing = false + local lasttime = nil trackers.register("pages.timing", function(v) -- only for myself (diagnostics) - starttime = os.clock() -- todo: use other timer - timing = true + timing = "" end) function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average if timing then - local elapsed, average - local stoptime = os.clock() + local elapsed = statistics.currenttime(statistics) + local average, page if not lasttime or real < 2 then - elapsed = stoptime - average = stoptime - starttime = stoptime - else - elapsed = stoptime - lasttime - average = (stoptime - starttime) / (real - 1) - end - lasttime = stoptime - if real <= 0 then - report("flushing page, time %0.04f / %0.04f",elapsed,average) - elseif user <= 0 then - report("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average) - elseif sub <= 0 then - report("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average) + average = elapsed + page = elapsed else - report("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average) + average = elapsed / (real - 1) + page = elapsed - lasttime end + lasttime = elapsed + timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) + end + if real <= 0 then + report("flushing page%s",timing) + elseif user <= 0 then + report("flushing realpage %s%s",real,timing) + elseif sub <= 0 then + report("flushing realpage %s, userpage %s%s",real,user,timing) else - if real <= 0 then - report("flushing page") - elseif user <= 0 then - report("flushing realpage %s",real) - elseif sub <= 0 then - report("flushing realpage %s, userpage %s",real,user) - else - report("flushing realpage %s, userpage %s, subpage %s",real,user,sub) - end + report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) end logs.flush() end @@ -1031,7 +1028,7 @@ end if tex and tex.error then function logs.texerrormessage(...) -- for the moment we put this function here - tex.error(format(...), { }) + tex.error(format(...)) end else function logs.texerrormessage(...) diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua index 56291f8c83d..03f0a67d107 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-par.lua @@ -15,13 +15,13 @@ local concat = table.concat local nuts = nodes.nuts local tonut = nuts.tonut -local getfield = nuts.getfield local getid = nuts.getid local getnext = nuts.getnext local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar local getwidth = nuts.getwidth +local getexpansion = nuts.getexpansion + +local isglyph = nuts.isglyph local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist @@ -63,23 +63,23 @@ local function colorize(n) -- tricky: the built-in method creates dummy fonts and the last line normally has the -- original font and that one then has ex.auto set while n do - local id = getid(n) - if id == glyph_code then - local ne = getfield(n,"expansion_factor") + local char, id = isglyph(n) + if char then + local ne = getexpansion(n) if ne == 0 then if length > 0 then flush() end setnodecolor(n,"hz:zero") else - local f = getfont(n) - if f ~= font then + -- id == font + if id ~= font then if length > 0 then flush() end - local pf = parameters[f] + local pf = parameters[id] local ex = pf.expansion if ex and ex.auto then size = pf.size - font = f -- save lookups + font = id -- save lookups else size = false end @@ -100,7 +100,7 @@ local function colorize(n) end if trace_verbose then length = length + 1 - list[length] = utfchar(getchar(n)) + list[length] = utfchar(char) width = width + getwidth(n) -- no kerning yet end end @@ -109,7 +109,10 @@ local function colorize(n) if length > 0 then flush() end - colorize(getlist(n),flush) + local list = getlist(n) + if list then + colorize(list,flush) + end else -- nothing to show on kerns if length > 0 then flush() @@ -125,7 +128,7 @@ end builders.paragraphs.expansion = builders.paragraphs.expansion or { } function builders.paragraphs.expansion.trace(head) - colorize(tonut(head),true) + colorize(head,true) return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua index 530915fe0a2..6311d638296 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-set.lua @@ -396,3 +396,20 @@ if texconfig then directives.register("luatex.stacksize", function(v) set("stack_size",v) end) end + +-- for now here: + +local data = table.setmetatableindex("table") + +updaters = { + register = function(what,f) + local d = data[what] + d[#d+1] = f + end, + apply = function(what,...) + local d = data[what] + for i=1,#d do + d[i](...) + end + end, +} diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua index 0e37752db36..b61dadb515a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.lua @@ -28,8 +28,6 @@ local compactfloat = number.compactfloat -- todo: inline concat (more efficient) -- todo: tags can also be numbers (just add to hash) --- todo: dir and localpar nodes - local nodecodes = nodes.nodecodes local nuts = nodes.nuts @@ -47,12 +45,10 @@ local setattr = nuts.setattr local setwidth = nuts.setwidth local setshift = nuts.setshift -local getfield = nuts.getfield local getid = nuts.getid local getfont = nuts.getfont local getattr = nuts.getattr local getsubtype = nuts.getsubtype -local getchar = nuts.getchar local getbox = nuts.getbox local getlist = nuts.getlist local getleader = nuts.getleader @@ -63,22 +59,26 @@ local getdisc = nuts.getdisc local getwhd = nuts.getwhd local getkern = nuts.getkern local getpenalty = nuts.getpenalty -local getdir = nuts.getdir local getwidth = nuts.getwidth local getdepth = nuts.getdepth local getshift = nuts.getshift +local getexpansion = nuts.getexpansion + +local isglyph = nuts.isglyph local hpack_nodes = nuts.hpack local vpack_nodes = nuts.vpack local copy_list = nuts.copy_list +local copy_node = nuts.copy_node local flush_node_list = nuts.flush_list local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after -local traverse_nodes = nuts.traverse local apply_to_nodes = nuts.apply local find_tail = nuts.tail local effectiveglue = nuts.effective_glue +local nextnode = nuts.traversers.node + local hpack_string = nuts.typesetters.tohpack local texgetattribute = tex.getattribute @@ -188,13 +188,16 @@ end -- we can preset a bunch of bits -local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") -local function enable() +local function initialize() + -- if not usedfont then -- we use a narrow monospaced font -- infofont ? visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") }) end + -- for mode, value in next, modes do local tag = formatters["v_%s"](mode) attributes.viewerlayers.define { @@ -225,14 +228,25 @@ local function enable() l_line = layers.line l_space = layers.space l_depth = layers.depth - enableaction("shipouts","nodes.visualizers.handler") - report_visualize("enabled") - enabled = true - tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end -- if not userrule then userrule = nuts.rules.userrule end + -- + if not outlinerule then + outlinerule = nuts.pool.outlinerule + end + initialize = false +end + +local function enable() + if initialize then + initialize() + end + enableaction("shipouts","nodes.visualizers.handler") + report_visualize("enabled") + enabled = true + tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end end local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in @@ -454,7 +468,7 @@ local fontkern, italickern do local function somekern(head,current,cache,color,layer) local width = getkern(current) - local extra = getfield(current,"expansion_factor") + local extra = getexpansion(current) local kern = width + extra local info = cache[kern] if not info then @@ -495,7 +509,7 @@ local glyphexpansion do local f_cache = caches["glyphexpansion"] glyphexpansion = function(head,current) - local extra = getfield(current,"expansion_factor") + local extra = getexpansion(current) if extra ~= 0 then extra = extra / 1000 local info = f_cache[extra] @@ -529,7 +543,7 @@ local kernexpansion do local f_cache = caches["kernexpansion"] kernexpansion = function(head,current) - local extra = getfield(current,"expansion_factor") + local extra = getexpansion(current) if extra ~= 0 then extra = extra / 1000 local info = f_cache[extra] @@ -564,29 +578,17 @@ local whatsit do local w_cache = caches["whatsit"] local tags = { - open = "FIC", - write = "FIW", - close = "FIC", - special = "SPE", - latelua = "LUA", - savepos = "POS", - userdefined = "USR", - -- backend stuff - pdfliteral = "PDF", - pdfrefobj = "PDF", - pdfannot = "PDF", - pdfstartlink = "PDF", - pdfendlink = "PDF", - pdfdest = "PDF", - pdfthread = "PDF", - pdfstartthread = "PDF", - pdfendthread = "PDF", - pdfthreaddata = "PDF", - pdflinkdata = "PDF", - pdfcolorstack = "PDF", - pdfsetmatrix = "PDF", - pdfsave = "PDF", - pdfrestore = "PDF", + open = "OPN", + write = "WRI", + close = "CLS", + special = "SPE", + latelua = "LUA", + savepos = "POS", + userdefined = "USR", + literal = "LIT", + setmatrix = "MAT", + save = "SAV", + restore = "RES", } whatsit = function(head,current) @@ -700,40 +702,11 @@ local ruledbox do local wd, ht, dp = getwhd(current) if wd ~= 0 then local shift = getshift(current) - local dir = getdir(current) - -- if dir == "LTL" or dir == "RRT" then - -- wd, ht, dp = ht + dp, wd, 0 - -- end local next = getnext(current) local prev = previous - -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3 setboth(current) local linewidth = emwidth/fraction local size = 2*linewidth - -- local baseline, baseskip - -- if dp ~= 0 and ht ~= 0 then - -- if wd > 20*linewidth then - -- local targetsize = wd - size - -- baseline = b_cache[targetsize] - -- if not baseline then - -- -- due to an optimized leader color/transparency we need to set the glue node in order - -- -- to trigger this mechanism - -- local leader = setlink(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size)) - -- leader = hpack_nodes(leader) - -- baseline = new_glue(0,65536,0,2,0) - -- setleader(baseline,leader) - -- setsubtype(baseline,cleaders_code) - -- setlisttransparency(baseline,c_text) - -- baseline = hpack_nodes(baseline,targetsize) - -- b_cache[targetsize] = baseline - -- end - -- baseline = copy_list(baseline) - -- baseskip = new_kern(-wd+linewidth) - -- else - -- baseline = new_rule(wd-size,linewidth,0) - -- baseskip = new_kern(-wd+size) - -- end - -- end local this if not simple then this = b_cache[what] @@ -746,22 +719,9 @@ local ruledbox do end end -- we need to trigger the right mode (else sometimes no whatits) - -- local info = setlink( - -- this and copy_list(this) or nil, - -- new_rule(linewidth,ht,dp), - -- new_rule(wd-size,-dp+linewidth,dp), - -- new_rule(linewidth,ht,dp), - -- new_kern(-wd+linewidth), - -- new_rule(wd-size,ht,-ht+linewidth), - -- baseskip, - -- baseskip and baseline or nil - -- ) - -- - -- userrules: - -- local info = setlink( this and copy_list(this) or nil, - userrule { + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { width = wd, height = ht, depth = dp, @@ -772,7 +732,7 @@ local ruledbox do ) -- setlisttransparency(info,c_text) - info = new_hlist(info) + info = new_hlist(info) -- important -- setattr(info,a_layer,layer) if vertical then @@ -846,56 +806,16 @@ local ruledglyph do ruledglyph = function(head,current,previous) -- wrong for vertical glyphs local wd = getwidth(current) - -- local wd = chardata[getfont(current)][getchar(current)].width if wd ~= 0 then local wd, ht, dp = getwhd(current) - -- local dir = getdir(current) - -- if dir == "LTL" or dir = "RTT" then - -- wd, ht, dp = ht + dp, wd, 0 - -- end local next = getnext(current) local prev = previous setboth(current) local linewidth = emwidth/(2*fraction) local info -- - -- original - -- - -- local baseline - -- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then - -- baseline = new_rule(wd-2*linewidth,linewidth,0) - -- end - -- local doublelinewidth = 2*linewidth - -- -- could be a pdf rule (or a user rule now) - -- info = setlink( - -- new_rule(linewidth,ht,dp), - -- new_rule(wd-doublelinewidth,-dp+linewidth,dp), - -- new_rule(linewidth,ht,dp), - -- new_kern(-wd+linewidth), - -- new_rule(wd-doublelinewidth,ht,-ht+linewidth), - -- new_kern(-wd+doublelinewidth), - -- baseline - -- ) - -- - -- experiment with subtype outline - -- - -- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then - -- baseline = new_rule(wd,linewidth/2,0) - -- end - -- local r = new_rule(wd-linewidth,ht-linewidth/4,dp-linewidth/4) - -- setsubtype(r,nodes.rulecodes.outline) - -- setfield(r,"transform",linewidth) - -- info = setlink( - -- new_kern(linewidth/4), - -- r, - -- new_kern(-wd+linewidth/2), - -- baseline - -- ) - -- - -- userrules: - -- info = setlink( - userrule { + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { width = wd, height = ht, depth = dp, @@ -905,7 +825,8 @@ local ruledglyph do new_kern(-wd) ) -- - local char = chardata[getfont(current)][getchar(current)] + local c, f = isglyph(current) + local char = chardata[f][c] if char and type(char.unicode) == "table" then -- hackery test setlistcolor(info,c_ligature) setlisttransparency(info,c_ligature_d) @@ -942,19 +863,22 @@ end local ruledglue do - local gluecodes = nodes.gluecodes - local cleaders_code = gluecodes.cleaders - local userskip_code = gluecodes.userskip - local space_code = gluecodes.spaceskip - local xspace_code = gluecodes.xspaceskip - local leftskip_code = gluecodes.leftskip - local rightskip_code = gluecodes.rightskip + local gluecodes = nodes.gluecodes + local leadercodes = nodes.gluecodes + + local userskip_code = gluecodes.userskip + local spaceskip_code = gluecodes.spaceskip + local xspaceskip_code = gluecodes.xspaceskip + local leftskip_code = gluecodes.leftskip + local rightskip_code = gluecodes.rightskip + + local cleaders_code = leadercodes.cleaders local g_cache_v = caches["vglue"] local g_cache_h = caches["hglue"] local tags = { - -- userskip = "US", + -- [gluecodes.userskip] = "US", [gluecodes.lineskip] = "LS", [gluecodes.baselineskip] = "BS", [gluecodes.parskip] = "PS", @@ -973,12 +897,12 @@ local ruledglue do [gluecodes.thinmuskip] = "MS", [gluecodes.medmuskip] = "MM", [gluecodes.thickmuskip] = "ML", - [gluecodes.leaders] = "NL", - [gluecodes.cleaders] = "CL", - [gluecodes.xleaders] = "XL", - [gluecodes.gleaders] = "GL", - -- true = "VS", - -- false = "HS", + [leadercodes.leaders] = "NL", + [leadercodes.cleaders] = "CL", + [leadercodes.xleaders] = "XL", + [leadercodes.gleaders] = "GL", + -- true = "VS", + -- false = "HS", } -- we sometimes pass previous as we can have issues in math (not watertight for all) @@ -991,7 +915,7 @@ local ruledglue do if info then -- print("glue hit") else - if subtype == space_code or subtype == xspace_code then + if subtype == spaceskip_code or subtype == xspaceskip_code then info = sometext(amount,l_glue,c_space) elseif subtype == leftskip_code or subtype == rightskip_code then info = sometext(amount,l_glue,c_skip_a) @@ -1018,7 +942,7 @@ local ruledglue do -- ruledspace = function(head,current,parent) -- local subtype = getsubtype(current) - -- if subtype == space_code or subtype == xspace_code then + -- if subtype == spaceskip_code or subtype == xspaceskip_code then -- local width = effectiveglue(current,parent) -- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor) -- local info = g_cache_h[amount] @@ -1041,10 +965,10 @@ local ruledglue do ruledspace = function(head,current,parent) local subtype = getsubtype(current) - if subtype == space_code or subtype == xspace_code then -- not yet all space + if subtype == spaceskip_code or subtype == xspaceskip_code then -- not yet all space local width = effectiveglue(current,parent) local info - if subtype == space_code then + if subtype == spaceskip_code then info = g_cache_s[width] if not info then info = someblob("SP",l_glue,c_space,nil,width) @@ -1179,24 +1103,26 @@ end do - local disc_code = nodecodes.disc - local kern_code = nodecodes.kern - local glyph_code = nodecodes.glyph - local glue_code = nodecodes.glue - local penalty_code = nodecodes.penalty - local whatsit_code = nodecodes.whatsit - local user_code = nodecodes.user - local math_code = nodecodes.math - local hlist_code = nodecodes.hlist - local vlist_code = nodecodes.vlist - - local kerncodes = nodes.kerncodes - local font_kern_code = kerncodes.fontkern - local italic_kern_code = kerncodes.italiccorrection - ----- user_kern_code = kerncodes.userkern - - local listcodes = nodes.listcodes - local line_code = listcodes.line + local disc_code = nodecodes.disc + local kern_code = nodecodes.kern + local glyph_code = nodecodes.glyph + local glue_code = nodecodes.glue + local penalty_code = nodecodes.penalty + local whatsit_code = nodecodes.whatsit + local user_code = nodecodes.user + local math_code = nodecodes.math + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + + local kerncodes = nodes.kerncodes + local fontkern_code = kerncodes.fontkern + local italickern_code = kerncodes.italiccorrection + ----- userkern_code = kerncodes.userkern + + local listcodes = nodes.listcodes + local linelist_code = listcodes.line + + local cache local function visualize(head,vertical,forced,parent) local trace_hbox = false @@ -1225,6 +1151,58 @@ do local prev_trace_fontkern = nil local prev_trace_italic = nil local prev_trace_expansion = nil + + -- local function setthem(t,k) + -- local v_trace_hbox = band(k, 1) ~= 0 + -- local v_trace_vbox = band(k, 2) ~= 0 + -- local v_trace_vtop = band(k, 4) ~= 0 + -- local v_trace_kern = band(k, 8) ~= 0 + -- local v_trace_glue = band(k, 16) ~= 0 + -- local v_trace_penalty = band(k, 32) ~= 0 + -- local v_trace_fontkern = band(k, 64) ~= 0 + -- local v_trace_strut = band(k, 128) ~= 0 + -- local v_trace_whatsit = band(k, 256) ~= 0 + -- local v_trace_glyph = band(k, 512) ~= 0 + -- local v_trace_simple = band(k, 1024) ~= 0 + -- local v_trace_user = band(k, 2048) ~= 0 + -- local v_trace_math = band(k, 4096) ~= 0 + -- local v_trace_italic = band(k, 8192) ~= 0 + -- local v_trace_origin = band(k, 16384) ~= 0 + -- local v_trace_discretionary = band(k, 32768) ~= 0 + -- local v_trace_expansion = band(k, 65536) ~= 0 + -- local v_trace_line = band(k,131072) ~= 0 + -- local v_trace_space = band(k,262144) ~= 0 + -- local v_trace_depth = band(k,524288) ~= 0 + -- local v = function() + -- trace_hbox = v_trace_hbox + -- trace_vbox = v_trace_vbox + -- trace_vtop = v_trace_vtop + -- trace_kern = v_trace_kern + -- trace_glue = v_trace_glue + -- trace_penalty = v_trace_penalty + -- trace_fontkern = v_trace_fontkern + -- trace_strut = v_trace_strut + -- trace_whatsit = v_trace_whatsit + -- trace_glyph = v_trace_glyph + -- trace_simple = v_trace_simple + -- trace_user = v_trace_user + -- trace_math = v_trace_math + -- trace_italic = v_trace_italic + -- trace_origin = v_trace_origin + -- trace_discretionary = v_trace_discretionary + -- trace_expansion = v_trace_expansion + -- trace_line = v_trace_line + -- trace_space = v_trace_space + -- trace_depth = v_trace_depth + -- end + -- t[k] = v + -- return v + -- end + -- + -- if not cache then + -- cache = setmetatableindex(setthem) + -- end + while current do local id = getid(current) local a = forced or getattr(current,a_visual) or unsetvalue @@ -1254,6 +1232,7 @@ do trace_space = false trace_depth = false else -- dead slow: + -- cache[a]() trace_hbox = band(a, 1) ~= 0 trace_vbox = band(a, 2) ~= 0 trace_vtop = band(a, 4) ~= 0 @@ -1303,14 +1282,14 @@ do setdisc(current,pre,post,replace) elseif id == kern_code then local subtype = getsubtype(current) - if subtype == font_kern_code then + if subtype == fontkern_code then if trace_fontkern or prev_trace_fontkern then head, current = fontkern(head,current) end if trace_expansion or prev_trace_expansion then head, current = kernexpansion(head,current) end - elseif subtype == italic_kern_code then + elseif subtype == italickern_code then if trace_italic or prev_trace_italic then head, current = italickern(head,current) elseif trace_kern then @@ -1342,7 +1321,7 @@ do if trace_depth then ruleddepth(current) end - if trace_line and getsubtype(current) == line_code then + if trace_line and getsubtype(current) == linelist_code then head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent) elseif trace_hbox then head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent) @@ -1390,9 +1369,9 @@ do local function handler(head) if usedfont then starttiming(visualizers) - head = visualize(tonut(head),true) + head = visualize(head,true) stoptiming(visualizers) - return tonode(head), true + return head, true else return head, false end @@ -1433,8 +1412,7 @@ do } local function markfonts(list) - for n in traverse_nodes(list) do - local id = getid(n) + for n, id in nextnode, list do if id == glyph_code then local font = getfont(n) local okay = used[font] @@ -1507,3 +1485,57 @@ do } end + +-- Here for now: + +do + + local function make(str,forecolor,rulecolor,layer) + if initialize then + initialize() + end + local rule = new_rule(emwidth/fraction,exheight,4*exheight) + setcolor(rule,rulecolor) + settransparency(rule,rulecolor) + local info + if str == "" then + info = new_hlist(rule) + else + local text = hpack_string(str,usedfont) + local list = getlist(text) + setlistcolor(list,textcolor) + setlisttransparency(list,textcolor) + setshift(text,3.5 * exheight) + info = new_hlist(setlink(rule,text)) + end + setattr(info,a_layer,layer) + return info + end + + function visualizers.register(name,textcolor,rulecolor) + if rawget(layers,name) then + -- message + return + end + local cache = caches[name] + local layer = layers[name] + if not textcolor then + textcolor = c_text_d + end + if not rulecolor then + rulecolor = c_origin_d + end + return function(str) + if not str then + str = "" + end + local info = cache[str] + if not info then + info = make(str,textcolor,rulecolor,layer) + cache[str] = info + end + return copy_node(info) + end + end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv index a6a3fa5a2c0..570e6a7c730 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/trac-vis.mkiv @@ -76,7 +76,7 @@ \to \everyshipout \appendtoks - \global\let\syst_visualizers_speedup\relax + \glet\syst_visualizers_speedup\relax \to \t_syst_visualizers_optimize \def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize} @@ -122,6 +122,11 @@ \unexpanded\def\showfontitalics {\clf_setvisual{italic}} +\unexpanded\def\showglyphdata + {\showglyphs + \showfontkerns + \showfontitalics} + \unexpanded\def\showfontexpansion {\clf_setvisual{expansion}} diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi b/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi index 2ac3ee2071f..ac5f6af2f95 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi +++ b/Master/texmf-dist/tex/context/base/mkiv/type-ini.mkvi @@ -45,18 +45,30 @@ \let\currenttypescripts\empty \let\currenttypefile \empty +\installmacrostack\currenttypefile + \let\typescriptone \empty % public, used in typescripts \let\typescripttwo \empty % public, used in typescripts \let\typescriptthree\empty % public, used in typescripts +\installmacrostack\typescriptone +\installmacrostack\typescripttwo +\installmacrostack\typescriptthree + \let\fontclassstyle \empty +\installmacrostack\fontclassstyle + \let\m_font_typescripts_one \empty \let\m_font_typescripts_two \empty \let\m_font_typescripts_three\empty \let\m_font_typescripts_check\empty \let\m_font_typescripts_match\empty +\installmacrostack\m_font_typescripts_one +\installmacrostack\m_font_typescripts_two +\installmacrostack\m_font_typescripts_three + \let\t_font_typescripts\relax % uses as synonym \installcorenamespace{typescriptcache} @@ -75,6 +87,9 @@ \let\typescriptmethod\plusone % 1: empty==all==true 2: empty==false \let\typescriptstate \plustwo % 1: process 2: store +\installmacrostack\typescriptmethod +\installmacrostack\typescriptstate + \unexpanded\def\starttypescriptcollection {\dosingleempty\font_typescripts_collection_start} @@ -95,19 +110,21 @@ \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} +\installmacrostack\stoptypescript + \unexpanded\def\font_typescripts_use[#one][#two][#three]% - {\pushmacro\m_font_typescripts_one - \pushmacro\m_font_typescripts_two - \pushmacro\m_font_typescripts_three + {\push_macro_m_font_typescripts_one + \push_macro_m_font_typescripts_two + \push_macro_m_font_typescripts_three \edef\m_font_typescripts_one {\truetypescript{#one}}% \edef\m_font_typescripts_two {\truetypescript{#two}}% \edef\m_font_typescripts_three{\truetypescript{#three}}% - \pushmacro\typescriptone - \pushmacro\typescripttwo - \pushmacro\typescriptthree - \pushmacro\typescriptmethod - \pushmacro\typescriptstate - \pushmacro\stoptypescript + \push_macro_typescriptone + \push_macro_typescripttwo + \push_macro_typescriptthree + \push_macro_typescriptmethod + \push_macro_typescriptstate + \push_macro_stoptypescript \typescriptfoundfalse \let\typescriptstate\plusone % why \iftracetypescripts @@ -119,15 +136,15 @@ \font_typescripts_use_display \fi \setfalse\c_font_typescripts_first_pass - \popmacro\stoptypescript - \popmacro\typescriptstate - \popmacro\typescriptmethod - \popmacro\typescriptthree - \popmacro\typescripttwo - \popmacro\typescriptone - \popmacro\m_font_typescripts_three - \popmacro\m_font_typescripts_two - \popmacro\m_font_typescripts_one} + \pop_macro_stoptypescript + \pop_macro_typescriptstate + \pop_macro_typescriptmethod + \pop_macro_typescriptthree + \pop_macro_typescripttwo + \pop_macro_typescriptone + \pop_macro_m_font_typescripts_three + \pop_macro_m_font_typescripts_two + \pop_macro_m_font_typescripts_one} \def\font_typescripts_use_display {\processcommacommand[\typescriptfiles]\font_typescripts_load_file @@ -170,10 +187,10 @@ % 1 then, it doesn't get stored without doing that explicitly \unexpanded\def\loadtypescriptfile[#1]% - {\pushmacro\typescriptstate + {\push_macro_typescriptstate \let\typescriptstate\plustwo % assumes 2 at the outer level \clf_loadtypescriptfile{#1}% - \popmacro\typescriptstate} + \pop_macro_typescriptstate} \unexpanded\def\loadfoundtypescriptfile#1% {\startreadingfile @@ -191,30 +208,26 @@ {\global\advance\c_font_typescripts_n_of_preloaded\plusone \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname {\starttypescript#definitions\stoptypescript}% - %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}} - \global\t_font_typescripts\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\t_font_typescripts - \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} + \gtoksapp\t_font_typescripts\expandafter + {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} \def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection {\global\advance\c_font_typescripts_n_of_preloaded\plusone \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname {\starttypescriptcollection#definitions\stoptypescriptcollection}% - %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}} - \global\t_font_typescripts\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\t_font_typescripts - \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} + \gtoksapp\t_font_typescripts\expandafter + {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} \def\font_typescripts_load_file#filename% {\setfalse\c_font_typescripts_quit - \pushmacro\currenttypefile + \push_macro_currenttypefile \def\currenttypefile{#filename}% \ifconditional\c_font_typescripts_preload \font_typescript_process_typescript_file_and_store \else \font_typescript_process_typescript_file \fi - \popmacro\currenttypefile + \pop_macro_currenttypefile \ifconditional\c_font_typescripts_quit \quitcommalist \setfalse\c_font_typescripts_quit @@ -294,8 +307,7 @@ \def\font_typescripts_start_gobble#definitions\stoptypescript{} \def\font_typescripts_start_document#definitions\stoptypescript - %{\appendtoks\starttypescript#definitions\stoptypescript\to\c_font_typescripts_document} - {\c_font_typescripts_document\expandafter{\the\c_font_typescripts_document\starttypescript#definitions\stoptypescript}} + {\toksapp\c_font_typescripts_document{\starttypescript#definitions\stoptypescript}} \def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed {\let\typescriptone \m_font_typescripts_one @@ -344,10 +356,10 @@ \let\font_typescripts_start_process_again_three\font_typescripts_start_process_yes \def\font_typescripts_start_process_indeed - {\pushmacro\fontclass} + {\push_macro_fontclass} \unexpanded\def\stoptypescript - {\popmacro\fontclass} + {\pop_macro_fontclass} \def\font_typescripts_check#asked#target#followup[#value]% script use value next {\donefalse @@ -521,8 +533,8 @@ \let\@@tsdirection \empty \let\@@tsdesignsize\empty \geteparameters[\??ts][#settings]% todo raw - \pushmacro\fontclass - \pushmacro\fontclassstyle + \push_macro_fontclass + \push_macro_fontclassstyle \setcurrentfontclass{#name}% \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection \the\everybeforedefinetypeface} @@ -536,8 +548,8 @@ \def\font_typefaces_defining_stop {\the\everyafterdefinetypeface - \popmacro\fontclassstyle - \popmacro\fontclass} + \pop_macro_fontclassstyle + \pop_macro_fontclass} \def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d) {\font_typefaces_define_indeed[#name][#style]% @@ -597,7 +609,7 @@ {\doifelsenothing{#styles} {\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]} {\doifnot{#name}{#parentclass} - {\global\let\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed + {\glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}% \processcommalist[#styles]\font_typescripts_inherit_check_step}}} diff --git a/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv b/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv index 1763de68790..c6b0c8841fc 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/type-set.mkiv @@ -132,4 +132,6 @@ \definefilesynonym [type-imp-stixtwo.mkiv] [type-imp-stix.mkiv] +\definefilesynonym [type-imp-ibmplex.mkiv] [type-imp-plex.mkiv] + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua index 753748a2eee..55d74281f50 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-bld.lua @@ -54,10 +54,12 @@ storage.register("builders/paragraphs/constructors/names", names, "builders. storage.register("builders/paragraphs/constructors/numbers", numbers, "builders.paragraphs.constructors.numbers") local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) +local trace_vbox_builder = false trackers.register("builders.vbox", function(v) trace_vbox_builder = v end) local trace_post_builder = false trackers.register("builders.post", function(v) trace_post_builder = v end) -local report_par_builder = logs.reporter("builders","par") local report_page_builder = logs.reporter("builders","page") +local report_vbox_builder = logs.reporter("builders","vbox") +local report_par_builder = logs.reporter("builders","par") local mainconstructor = nil -- not stored in format local nofconstructors = 0 @@ -137,7 +139,7 @@ end -- also for testing (now also surrounding spacing done) -function builders.paragraphs.constructors.methods.oneline(head,followed_by_display) +function parbuilders.constructors.methods.oneline(head,followed_by_display) -- when needed we will turn this into a helper local t = texnest[texnest.ptr] local h = hpack_node(head) @@ -193,15 +195,11 @@ function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction) local done = false if head then starttiming(builders) - if trace_vpacking then + if trace_vbox_builder then local before = count_nodes(head) head, done = vboxactions(head,groupcode,size,packtype,maxdepth,direction) local after = count_nodes(head) - if done then - nodes.processors.tracer("vpack","changed",head,groupcode,before,after,true) - else - nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true) - end + nodes.processors.tracer("vpack",head,groupcode,before,after,done) else head, done = vboxactions(head,groupcode) end @@ -254,13 +252,13 @@ function builders.buildpage_filter(groupcode) if trace_page_builder then report(groupcode) end - return nil, false -- no return value needed +-- return nil, false -- no return value needed + return nil end end -registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc") -registercallback('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)") -----------------('contribute_filter', builders.contribute_filter, "adding content to lists") +registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc") +registercallback('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)") statistics.register("v-node processing time", function() return statistics.elapsedseconds(builders) @@ -277,11 +275,21 @@ implement { name = "disableparbuilder", actions = constructors.disable } -- Here are some tracers: -local new_kern = nodes.pool.kern -local new_rule = nodes.pool.rule -local hpack = nodes.hpack +local nuts = nodes.nuts +local tonut = nodes.tonut local setcolor = nodes.tracers.colors.set local listtoutf = nodes.listtoutf +local new_kern = nuts.pool.kern +local new_rule = nuts.pool.rule +local hpack = nuts.hpack +local getheight = nuts.getheight +local getdepth = nuts.getdepth +local getdirection = nuts.getdirection +local getlist = nuts.getlist +local setwidth = nuts.setwidth +local setdirection = nuts.setdirection +local setlink = nuts.setlink +local tonode = nuts.tonode local report_hpack = logs.reporter("hpack routine") local report_vpack = logs.reporter("vpack routine") @@ -305,8 +313,9 @@ end) local report, show = false, false local function hpack_quality(how,detail,n,first,last) + n = tonut(n) if report then - local str = listtoutf(n.head,"",true,nil,true) + local str = listtoutf(getlist(n),"",true,nil,true) if last <= 0 then report_hpack("%s hbox: %s",how,str) elseif first > 0 and first < last then @@ -316,10 +325,10 @@ local function hpack_quality(how,detail,n,first,last) end end if show then - local width = 2*65536 - local height = n.height - local depth = n.depth - local dir = n.dir + local width = 2*65536 + local height = getheight(n) + local depth = getdepth(n) + local direction = getdirection(n) if height < 4*65526 then height = 4*65526 end @@ -327,12 +336,11 @@ local function hpack_quality(how,detail,n,first,last) depth = 2*65526 end local rule = new_rule(width,height,depth) - rule.dir = dir + setdirection(rule,direction) if how == "overfull" then setcolor(rule,"red") local kern = new_kern(-detail) - kern.next = rule - rule.prev = kern + setlink(kern,rule) rule = kern elseif how == "underfull" then setcolor(rule,"blue") @@ -342,9 +350,9 @@ local function hpack_quality(how,detail,n,first,last) setcolor(rule,"cyan") end rule = hpack(rule) - rule.width = 0 - rule.dir = dir - return rule + setwidth(rule,0) + setdirection(rule,direction) + return tonode(rule) -- can be a nut end end @@ -387,3 +395,4 @@ end) -- end, -- "experimental prevdepth checking" -- ) + diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua index 51760bbf48d..76e50ce1859 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-brk.lua @@ -23,7 +23,6 @@ local settings_to_array = utilities.parsers.settings_to_array local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -76,14 +75,14 @@ local new_wordboundary = nodepool.wordboundary local nodecodes = nodes.nodecodes local kerncodes = nodes.kerncodes -local glyph_code = nodecodes.glyph local kern_code = nodecodes.kern local math_code = nodecodes.math local fontkern_code = kerncodes.fontkern ------ userkern_code = kerncodes.userkern local italickern_code = kerncodes.italiccorrection +local is_letter = characters.is_letter + local typesetters = typesetters typesetters.breakpoints = typesetters.breakpoints or {} @@ -241,10 +240,9 @@ end function breakpoints.handler(head) local done = false - local nead = tonut(head) local attr = nil local map = nil - local current = nead + local current = head while current do local char, id = isglyph(current) if char then @@ -313,7 +311,7 @@ function breakpoints.handler(head) end end if not done then - return head, false + return head end -- we have hits local numbers = languages.numbers @@ -323,17 +321,21 @@ function breakpoints.handler(head) local stop = data[2] local cmap = data[3] local smap = data[4] --- local lang = getlang(start) -- -- we do a sanity check for language +-- local lang = getlang(start) -- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""]) -- if smap then local nleft = smap.nleft local cleft = 0 local prev = getprev(start) - local kern = nil + local kern = nil while prev and nleft ~= cleft do - local id = getid(prev) - if id == glyph_code then + local char, id = isglyph(prev) + if char then + if not is_letter[char] then + cleft = -1 + break + end cleft = cleft + 1 prev = getprev(prev) elseif id == kern_code then @@ -359,6 +361,10 @@ function breakpoints.handler(head) while next and nright ~= cright do local char, id = isglyph(next) if char then + if not is_letter[char] then + cright = -1 + break + end if cright == 1 and cmap[char] then -- let's not make it too messy break @@ -383,13 +389,13 @@ function breakpoints.handler(head) if nright == cright then local method = methods[smap.type] if method then - nead, start = method(nead,start,stop,smap,kern) + head, start = method(head,start,stop,smap,kern) end end -- end end end - return tonode(nead), true + return head end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua index 4dffd1c49a2..7e8003c620f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.lua @@ -18,8 +18,6 @@ local report_casing = logs.reporter("typesetting","casing") local nodes, node = nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -29,6 +27,7 @@ local takeattr = nuts.takeattr local getfont = nuts.getfont local getsubtype = nuts.getsubtype local getchar = nuts.getchar +local isglyph = nuts.isglyph local getdisc = nuts.getdisc local setattr = nuts.setattr @@ -37,12 +36,12 @@ local setfont = nuts.setfont local copy_node = nuts.copy local end_of_math = nuts.end_of_math -local traverse_id = nuts.traverse_id local insert_after = nuts.insert_after local find_attribute = nuts.find_attribute +local nextglyph = nuts.traversers.glyph + local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes local kerncodes = nodes.kerncodes local glyph_code = nodecodes.glyph @@ -98,19 +97,6 @@ local function get(a) extract(a, 0, 8) -- run end --- local function get(a) --- return --- (a >> 8) & ~(-1 << 8), -- & 0x0FF -- tag --- (a >> 16) & ~(-1 << 12), -- & 0xFFF -- font --- (a >> 0) & ~(-1 << 8) -- & 0x0FF -- run --- end - --- print(get(set( 1, 0))) --- print(get(set( 1, 99))) --- print(get(set( 2, 96))) --- print(get(set( 30, 922))) --- print(get(set(250,4000))) - -- a previous implementation used char(0) as placeholder for the larger font, so we needed -- to remove it before it can do further harm ... that was too tricky as we use char 0 for -- other cases too @@ -128,10 +114,9 @@ local categories = characters.categories -- true false true == mixed local function replacer(start,codes) - local char = getchar(start) - local dc = codes[char] + local char, fnt = isglyph(start) + local dc = codes[char] if dc then - local fnt = getfont(start) local ifc = fontchar[fnt] if type(dc) == "table" then for i=1,#dc do @@ -149,13 +134,11 @@ local function replacer(start,codes) insert_after(start,start,g) end end - return start, true elseif ifc[dc] then setchar(start,dc) - return start, true end end - return start, false + return start end local registered, n = { }, 0 @@ -191,9 +174,9 @@ local function Words(start,attr,lastfont,n,count,where,first) -- looks quite com end if count == 1 and where ~= "post" then replacer(first or start,uccodes) - return start, true, true + return start, true else - return start, false, true + return start, true end end @@ -203,9 +186,9 @@ local function Word(start,attr,lastfont,n,count,where,first) end local function camel(start,attr,lastfont,n,count,where,first) - local _, done_1 = word(start,attr,lastfont,n,count,where,first) - local _, done_2 = Words(start,attr,lastfont,n,count,where,first) - return start, done_1 or done_2, true + word(start,attr,lastfont,n,count,where,first) + Words(start,attr,lastfont,n,count,where,first) + return start, true end -- local function mixed(start,attr,lastfont,n,count,where,first) @@ -216,19 +199,16 @@ end -- local char = getchar(first) -- local dc = uccodes[char] -- if not dc then --- return start, false, true +-- -- quit -- elseif dc == char then -- local lfa = lastfont[n] -- if lfa then -- setfont(first,lfa) --- return start, true, true --- else --- return start, false, true -- end -- else -- replacer(first or start,uccodes) --- return start, true, true -- end +-- return start, true -- end local function mixed(start,attr,lastfont,n,count,where,first) @@ -239,38 +219,33 @@ local function mixed(start,attr,lastfont,n,count,where,first) local char = getchar(used) local dc = uccodes[char] if not dc then - return start, false, true + -- quit elseif dc == char then local lfa = lastfont[n] if lfa then setfont(used,lfa) - return start, true, true - else - return start, false, true end - else - if check_kerns then - local p = getprev(used) - if p and getid(p) == glyph_code then - local c = lccodes[char] - local c = type(c) == "table" and c[1] or c - replacer(used,uccodes) - local fp = getfont(p) - local fc = getfont(used) - if fp ~= fc then - local k = fonts.getkern(fontdata[fp],getchar(p),c) - if k ~= 0 then - insert_after(p,p,newkern(k)) - end + elseif check_kerns then + local p = getprev(used) + if p and getid(p) == glyph_code then + local c = lccodes[char] + local c = type(c) == "table" and c[1] or c + replacer(used,uccodes) + local fp = getfont(p) + local fc = getfont(used) + if fp ~= fc then + local k = fonts.getkern(fontdata[fp],getchar(p),c) + if k ~= 0 then + insert_after(p,p,newkern(k)) end - else - replacer(used,uccodes) end else replacer(used,uccodes) end - return start, true, true + else + replacer(used,uccodes) end + return start, true end local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 @@ -284,11 +259,11 @@ local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 end end end - local s, d, c = replacer(first or start,uccodes) + local s, c = replacer(first or start,uccodes) if once then lastfont[n] = false -- here end - return start, d, c + return start, c end local function capital(start,attr,lastfont,n,where,count,first,count) -- 4 @@ -296,7 +271,7 @@ local function capital(start,attr,lastfont,n,where,count,first,count) -- 4 end local function none(start,attr,lastfont,n,count,where,first) - return start, false, true + return start, true end local function randomized(start,attr,lastfont,n,count,where,first) @@ -311,7 +286,7 @@ local function randomized(start,attr,lastfont,n,count,where,first) local n = getrandom("capital lu",0x41,0x5A) if tfm[n] then -- this also intercepts tables setchar(used,n) - return start, true + return start end end elseif kind == "ll" then @@ -319,11 +294,11 @@ local function randomized(start,attr,lastfont,n,count,where,first) local n = getrandom("capital ll",0x61,0x7A) if tfm[n] then -- this also intercepts tables setchar(used,n) - return start, true + return start end end end - return start, false + return start end register(variables.WORD, WORD) -- 1 @@ -341,10 +316,9 @@ register(variables.cap, variables.capital) -- clone register(variables.Cap, variables.Capital) -- clone function cases.handler(head) -- not real fast but also not used on much data - local start = tonut(head) + local start = head local lastfont = { } local lastattr = nil - local done = false local count = 0 local previd = nil local prev = nil @@ -367,10 +341,7 @@ function cases.handler(head) -- not real fast but also not used on much data end local action = actions[n] -- map back to low number if action then - start, ok = action(start,attr,lastfont,n,count) - if ok then - done = true - end + start = action(start,attr,lastfont,n,count) if trace_casing then report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok) end @@ -396,32 +367,38 @@ function cases.handler(head) -- not real fast but also not used on much data local pre, post, replace = getdisc(start) if replace then local cnt = count - for g in traverse_id(glyph_code,replace) do + for g in nextglyph, replace do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) + if quit then + break + end end end if pre then local cnt = count - for g in traverse_id(glyph_code,pre) do + for g in nextglyph, pre do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) + if quit then + break + end end end if post then local cnt = count - for g in traverse_id(glyph_code,post) do + for g in nextglyph, post do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"post",g) + if quit then + break + end end end end @@ -441,17 +418,16 @@ function cases.handler(head) -- not real fast but also not used on much data start = getnext(start) end end - return head, done + return head end -- function cases.handler(head) -- not real fast but also not used on much data --- local attr, start = find_attribute(tonut(head),a_cases) +-- local attr, start = find_attribute(head,a_cases) -- if not start then -- return head, false -- end -- local lastfont = { } -- local lastattr = nil --- local done = false -- local count = 0 -- local previd = nil -- local prev = nil @@ -475,10 +451,7 @@ end -- end -- local action = actions[n] -- map back to low number -- if action then --- start, ok = action(start,attr,lastfont,n,count) --- if ok then --- done = true --- end +-- start = action(start,attr,lastfont,n,count) -- if trace_casing then -- report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok) -- end @@ -504,32 +477,38 @@ end -- local pre, post, replace = getdisc(start) -- if replace then -- local cnt = count --- for g in traverse_id(glyph_code,replace) do +-- for g in glyph_code, replace do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) +-- if quit then +-- break +-- end -- end -- end -- if pre then -- local cnt = count --- for g in traverse_id(glyph_code,pre) do +-- for g in nextglyph, pre do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) +-- if quit then +-- break +-- end -- end -- end -- if post then -- local cnt = count --- for g in traverse_id(glyph_code,post) do +-- for g in nextglyph, post do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"post",g) +-- if quit then +-- break +-- end -- end -- end -- end @@ -555,26 +534,22 @@ end -- attr, start = find_attribute(start,a_cases) -- end -- end --- return head, done +-- return head -- end -- function cases.handler(head) -- let's assume head doesn't change ... no reason --- local done = false -- local lastfont = { } --- for first, last, size, attr in nuts.words(tonut(head),a_cases) do +-- for first, last, size, attr in nuts.words(head,a_cases) do -- local n, id, m = get(attr) -- if lastfont[n] == nil then -- lastfont[n] = id -- end -- local action = actions[n] -- if action then --- local _, ok = action(first,attr,lastfont,n) --- if ok then --- done = true --- end +-- action(first,attr,lastfont,n) -- end -- end --- return head, done +-- return head -- end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv index 4d1272e103c..890b0818675 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cap.mkiv @@ -81,20 +81,23 @@ % todo: names casings -\unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\v!WORD ]}{}} -\unexpanded\def\word {\groupedcommand{\setcharactercasing[\v!word ]}{}} -\unexpanded\def\Word {\groupedcommand{\setcharactercasing[\v!Word ]}{}} -\unexpanded\def\Words{\groupedcommand{\setcharactercasing[\v!Words]}{}} -\unexpanded\def\camel{\groupedcommand{\setcharactercasing[\v!camel]}{}} - -% This might become: -% -% \unexpanded\def\WORD {\bgroup\def\g_word{\setcharactercasing[\v!WORD ]}\afterassignment\g_word\let\nexttoken} -% \unexpanded\def\word {\bgroup\def\g_word{\setcharactercasing[\v!word ]}\afterassignment\g_word\let\nexttoken} -% \unexpanded\def\Word {\bgroup\def\g_word{\setcharactercasing[\v!Word ]}\afterassignment\g_word\let\nexttoken} -% \unexpanded\def\Words{\bgroup\def\g_word{\setcharactercasing[\v!Words]}\afterassignment\g_word\let\nexttoken} -% -% so no longer {\Word test} and { } mandate (also later \groupedcommands will go) +% \unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\v!WORD ]}{}} +% \unexpanded\def\word {\groupedcommand{\setcharactercasing[\v!word ]}{}} +% \unexpanded\def\Word {\groupedcommand{\setcharactercasing[\v!Word ]}{}} +% \unexpanded\def\Words{\groupedcommand{\setcharactercasing[\v!Words]}{}} +% \unexpanded\def\camel{\groupedcommand{\setcharactercasing[\v!camel]}{}} + +\unexpanded\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font} +\unexpanded\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font} +\unexpanded\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font} +\unexpanded\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font} +\unexpanded\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font} + +\unexpanded\def\WORD {\triggergroupedcommandcs\typo_capitale_WORD } +\unexpanded\def\word {\triggergroupedcommandcs\typo_capitale_word } +\unexpanded\def\Word {\triggergroupedcommandcs\typo_capitale_Word } +\unexpanded\def\Words{\triggergroupedcommandcs\typo_capitale_Words} +\unexpanded\def\camel{\triggergroupedcommandcs\typo_capitale_camel} \let\WORDS\WORD \let\words\word @@ -176,16 +179,27 @@ \sc \clf_setcharactercasing{\currentcapitals}\fontid\font} -\unexpanded\def\pseudosmallcapped{\groupedcommand{\typo_capitals_set_fake\v!WORD }\donothing} % all upper -\unexpanded\def\pseudoSmallcapped{\groupedcommand{\typo_capitals_set_fake\v!capital}\donothing} % one upper + font -\unexpanded\def\pseudoSmallCapped{\groupedcommand{\typo_capitals_set_fake\v!Capital}\donothing} % some upper + font -\unexpanded\def\pseudoMixedCapped{\groupedcommand{\typo_capitals_set_fake\v!mixed }\donothing} % UpperCase +% \unexpanded\def\pseudosmallcapped{\groupedcommand{\typo_capitals_set_fake\v!WORD }\donothing} % all upper +% \unexpanded\def\pseudoSmallcapped{\groupedcommand{\typo_capitals_set_fake\v!capital}\donothing} % one upper + font +% \unexpanded\def\pseudoSmallCapped{\groupedcommand{\typo_capitals_set_fake\v!Capital}\donothing} % some upper + font +% \unexpanded\def\pseudoMixedCapped{\groupedcommand{\typo_capitals_set_fake\v!mixed }\donothing} % UpperCase +% +% \unexpanded\def\realsmallcapped {\groupedcommand{\typo_capitals_set_real\v!WORD }\donothing} % all lower +% \unexpanded\def\realSmallcapped {\groupedcommand{\typo_capitals_set_real\v!Word }\donothing} % one upper + font +% \unexpanded\def\realSmallCapped {\groupedcommand{\typo_capitals_set_real\v!Words }\donothing} % some upper +% +% \unexpanded\def\notsmallcapped {\groupedcommand{\typo_capitals_set_fake\v!word }\donothing} + +\unexpanded\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped} +\unexpanded\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped} +\unexpanded\def\pseudoSmallCapped{\triggergroupedcommandcs\font_style_pseudoSmallCapped} +\unexpanded\def\pseudoMixedCapped{\triggergroupedcommandcs\font_style_pseudoMixedCapped} -\unexpanded\def\realsmallcapped {\groupedcommand{\typo_capitals_set_real\v!WORD }\donothing} % all lower -\unexpanded\def\realSmallcapped {\groupedcommand{\typo_capitals_set_real\v!Word }\donothing} % one upper + font -\unexpanded\def\realSmallCapped {\groupedcommand{\typo_capitals_set_real\v!Words }\donothing} % some upper +\unexpanded\def\realsmallcapped {\triggergroupedcommandcs\font_style_realsmallcapped} +\unexpanded\def\realSmallcapped {\triggergroupedcommandcs\font_style_realSmallcapped} +\unexpanded\def\realSmallCapped {\triggergroupedcommandcs\font_style_realSmallCapped} -\unexpanded\def\notsmallcapped {\groupedcommand{\typo_capitals_set_fake\v!word }\donothing} +\unexpanded\def\notsmallcapped {\triggergroupedcommandcs\font_style_notsmallcapped} \unexpanded\def\font_style_pseudosmallcapped{\typo_capitals_set_fake\v!WORD } % all upper \unexpanded\def\font_style_pseudoSmallcapped{\typo_capitals_set_fake\v!capital} % one upper + font @@ -285,7 +299,9 @@ % % \definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=] -\unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}} +% \unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}} + +\unexpanded\def\randomizetext{\triggergroupedcommand{\attribute\caseattribute\pluseight}} \definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=] diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua index 80497a49207..15d14c8601b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.lua @@ -6,40 +6,40 @@ if not modules then modules = { } end modules ['typo-chr'] = { license = "see context related readme files" } --- local nodecodes = nodes.nodecodes --- local whatsitcodes = nodes.whatsitcodes --- local glyph_code = nodecodes.glyph --- local whatsit_code = nodecodes.whatsit --- local user_code = whatsitcodes.userdefined +-- This module can be optimized. + +-- local nodecodes = nodes.nodecodes +-- local whatsitcodes = nodes.whatsitcodes +-- +-- local glyph_code = nodecodes.glyph +-- local whatsit_code = nodecodes.whatsit -- --- local stringusernode = nodes.pool.userstring +-- local userwhatsit_code = whatsitcodes.userdefined -- --- local nuts = nodes.nuts --- local pool = nuts.pool +-- local stringusernode = nodes.pool.userstring -- --- local tonut = nuts.tonut --- local tonode = nuts.tonode --- local getid = nuts.getid --- local getprev = nuts.getprev --- local getsubtype = nuts.getsubtype --- local getchar = nuts.getchar --- local getfield = nuts.getfield +-- local nuts = nodes.nuts +-- local pool = nuts.pool -- --- local remove_node = nuts.remove --- local traverse_by_id = nuts.traverse_id +-- local getid = nuts.getid +-- local getprev = nuts.getprev +-- local getchar = nuts.getchar +-- local getdata = nuts.getdata +-- local getfield = nuts.getfield -- --- local signal = pool.userids.signal +-- local remove_node = nuts.remove +-- local nextwhatsit = nuts.traversers.whatsit -- --- local is_punctuation = characters.is_punctuation +-- local signal = pool.userids.signal +-- +-- local is_punctuation = characters.is_punctuation -- -- local actions = { -- removepunctuation = function(head,n) -- local prev = getprev(n) -- if prev then --- if getid(prev) == glyph_code then --- if is_punctuation[getchar(prev)] then --- head = remove_node(head,prev,true) --- end +-- if getid(prev) == glyph_code and is_punctuation[getchar(prev)] then +-- head = remove_node(head,prev,true) -- end -- end -- return head @@ -51,23 +51,18 @@ if not modules then modules = { } end modules ['typo-chr'] = { -- typesetters.signals = { } -- -- function typesetters.signals.handler(head) --- local h = tonut(head) -- local done = false --- for n in traverse_by_id(whatsit_code,h) do --- if getsubtype(n) == user_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then --- local action = actions[getfield(n,"value")] +-- for n, subtype in nextwhatsit, head do +-- if subtype == userwhatsit_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then +-- local action = actions[getdata(n)] -- if action then --- h = action(h,n) +-- head = action(h,n) -- end --- h = remove_node(h,n,true) +-- head = remove_node(head,n,true) -- done = true -- end -- end --- if done then --- return tonode(h), true --- else --- return head --- end +-- return head, done -- end -- -- local enabled = false @@ -88,35 +83,44 @@ if not modules then modules = { } end modules ['typo-chr'] = { local insert, remove = table.insert, table.remove -local context = context +local context = context +local ctx_doifelse = commands.doifelse + +local nodecodes = nodes.nodecodes +local boundarycodes = nodes.boundarycodes +local subtypes = nodes.subtypes + +local glyph_code = nodecodes.glyph +local localpar_code = nodecodes.localpar +local boundary_code = nodecodes.boundary -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph -local localpar_code = nodecodes.localpar +local wordboundary_code = boundarycodes.word -local texnest = tex.nest -local flush_node = node.flush_node -local flush_list = node.flush_list +local texgetnest = tex.getnest -- to be used +local texsetcount = tex.setcount -local settexattribute = tex.setattribute -local punctuation = characters.is_punctuation +local flush_node = node.flush_node +local flush_list = node.flush_list -local variables = interfaces.variables -local v_all = variables.all -local v_reset = variables.reset +local settexattribute = tex.setattribute +local punctuation = characters.is_punctuation -local a_marked = attributes.numbers['marked'] -local lastmarked = 0 -local marked = { +local variables = interfaces.variables +local v_all = variables.all +local v_reset = variables.reset + +local stack = { } + +local a_marked = attributes.numbers['marked'] +local lastmarked = 0 +local marked = { [v_all] = 1, [""] = 1, [v_reset] = attributes.unsetvalue, } -local stack = { } - local function pickup() - local list = texnest[texnest.ptr] + local list = texgetnest() if list then local tail = list.tail if tail and tail.id == glyph_code and punctuation[tail.char] then @@ -171,8 +175,7 @@ local function pickup(head,tail,str) while true do local prev = first.prev if prev and prev[a_marked] == attr then - local id = prev.id - if id == localpar_code then + if prev.id == localpar_code then -- and prev.subtype == 0 break else first = prev @@ -187,7 +190,7 @@ end local actions = { remove = function(specification) - local list = texnest[texnest.ptr] + local list = texgetnest() if list then local head = list.head local tail = list.tail @@ -250,3 +253,95 @@ interfaces.implement { actions = markcontent, arguments = "string", } + +-- We just put these here. + +interfaces.implement { + name = "lastnodeidstring", + public = true, + actions = function() + local list = texgetnest() -- "top" + local okay = false + if list then + local tail = list.tail + if tail then + okay = nodecodes[tail.id] + end + end + context(okay or "") + end, +} + +-- local t_lastnodeid = token.create("c_syst_last_node_id") +-- +-- interfaces.implement { +-- name = "lastnodeid", +-- public = true, +-- actions = function() +-- ... +-- tex.setcount("c_syst_last_node_id",okay) +-- context.sprint(t_lastnodeid) +-- end, +-- } + +interfaces.implement { + name = "lastnodeid", + actions = function() + local list = texgetnest() -- "top" + local okay = -1 + if list then + local tail = list.tail + if tail then + okay = tail.id + end + end + texsetcount("c_syst_last_node_id",okay) + end, +} + +interfaces.implement { + name = "lastnodesubtypestring", + public = true, + actions = function() + local list = texgetnest() -- "top" + local okay = false + if list then + local tail = list.tail + if head then + okay = subtypes[tail.id][tail.subtype] + end + end + context(okay or "") + end, +} + +local function lastnodeequals(id,subtype) + local list = texgetnest() -- "top" + local okay = false + if list then + local tail = list.tail + if tail then + local i = tail.id + okay = i == id or i == nodecodes[id] + if subtype then + local s = tail.subtype + okay = s == subtype or s == subtypes[i][subtype] + end + end + end + ctx_doifelse(okay) +end + +interfaces.implement { + name = "lastnodeequals", + arguments = "2 strings", + actions = lastnodeequals, +} + +interfaces.implement { + name = "atwordboundary", + actions = function() + lastnodeequals(boundary_code,wordboundary_code) + end, +} + diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv index c92c4562e0e..365c79e5154 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-chr.mkiv @@ -79,4 +79,23 @@ \def\typo_marked_remove[#1]% {\clf_pickupmarkedcontent action{remove}mark{#1}\relax} +%D A few helpers (put here for convenience): +%D +%D \starttyping +%D test test\doifelselastnode{boundary}{word}{YES}{NOP}test +%D test test\wordboundary \doifelselastnode{boundary}{word}{YES}{NOP}test +%D test test\wordboundary \doifelseatwordboundary{YES}{NOP}test +%D test test \lastnodeidstring test +%D test test\lastnodeidstring test +%D test test\number\lastnodeid test +%D \stoptyping + +\newcount\c_syst_last_node_id + +\unexpanded\def\doifelselastnode {\clf_lastnodeequals} +\unexpanded\def\doifelseatwordboundary{\clf_atwordboundary} +\unexpanded\def\lastnodeid {\clf_lastnodeid\c_syst_last_node_id} +% \lastnodeidstring % public expandable +% \lastnodesubstring % public expandable + \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua index b7187eaeb0b..b9b0e7d6cb7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-cln.lua @@ -31,15 +31,13 @@ local enableaction = nodes.tasks.enableaction local texsetattribute = tex.setattribute local nuts = nodes.nuts -local tonut = nuts.tonut -local getchar = nuts.getchar local getattr = nuts.getattr local setattr = nuts.setattr local setchar = nuts.setchar -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph local unsetvalue = attributes.unsetvalue @@ -58,9 +56,8 @@ local resetter = { -- this will become an entry in char-def -- cleaning comes first. function cleaners.handler(head) - local inline, done = false, false - for n in traverse_id(glyph_code,tonut(head)) do - local char = getchar(n) + local inline = false + for n, char, font in nextglyph, head do if resetter[char] then inline = false elseif not inline then @@ -71,7 +68,6 @@ function cleaners.handler(head) -- some day, not much change that \SS ends up here else setchar(n,upper) - done = true if trace_autocase then report_autocase("") end @@ -80,7 +76,7 @@ function cleaners.handler(head) inline = true end end - return head, done + return head end -- see typo-cap for a more advanced settings handler .. not needed now diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv index d12be6bcfda..2ce98841e19 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-del.mkiv @@ -71,35 +71,48 @@ \setnewconstant\boundarycharactermode\plusone +% old: skip symbol skip +% new: bound skip symbol skip bound + \unexpanded\def\midboundarycharacter#1#2% {\ifcase\boundarycharactermode \or - %\nobreak + \removeunwantedspaces + \wordboundary \hskip\hspaceamount\currentusedlanguage{#2}% \usedlanguageparameter#1% - %\nobreak \hskip\hspaceamount\currentusedlanguage{#2}% + \wordboundary + \ignorespaces \or \usedlanguageparameter#1% \fi \boundarycharactermode\plusone} +% old: symbol nobreak skip +% new: symbol nobreak skip wordboundary + \unexpanded\def\leftboundarycharacter#1#2% {\ifcase\boundarycharactermode \or \usedlanguageparameter#1% \nobreak - \hskip\hspaceamount\currentusedlanguage{#2}% + \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern + \wordboundary \or \usedlanguageparameter#1% \fi \boundarycharactermode\plusone} +% old: preword skip symbol +% new: bound nobreak skip symbol + \unexpanded\def\rightboundarycharacter#1#2% {\ifcase\boundarycharactermode \or - \prewordbreak %\nobreak - \hskip\hspaceamount\currentusedlanguage{#2}% + \wordboundary + \nobreak + \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern \usedlanguageparameter#1% \or \usedlanguageparameter#1% @@ -212,10 +225,15 @@ %D \typebuffer %D \getbuffer -\unexpanded\def\startsubsentence{\beginofsubsentence\prewordbreak\beginofsubsentencespacing\typo_subsentence_cleanup_start} -\unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\endofsubsentencespacing\prewordbreak\endofsubsentence} -\unexpanded\def\subsentence {\groupedcommand\startsubsentence\stopsubsentence} -\unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\prewordbreak\midsentence\prewordbreak\typo_subsentence_cleanup_stop} +%unexpanded\def\startsubsentence{\beginofsubsentence\prewordbreak\beginofsubsentencespacing\typo_subsentence_cleanup_start} +%unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\endofsubsentencespacing\prewordbreak\endofsubsentence} +%unexpanded\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence} +%unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\prewordbreak\midsentence\prewordbreak\typo_subsentence_cleanup_stop} + +\unexpanded\def\startsubsentence{\beginofsubsentence\wordboundary\beginofsubsentencespacing\wordboundary\typo_subsentence_cleanup_start} +\unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\wordboundary\endofsubsentencespacing\wordboundary\endofsubsentence} +\unexpanded\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence} +\unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\wordboundary\midsentence\wordboundary\typo_subsentence_cleanup_stop} \definehspace [quotation] [\zeropoint] \definehspace [interquotation] [.125em] @@ -277,6 +295,8 @@ \let\currentdelimitedtext\s!unknown +\installglobalmacrostack\currentdelimitedtext + \let\delimitedtextlevel\!!zerocount \def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname} @@ -301,6 +321,8 @@ \let\currentdelimitedlanguage\empty +\installglobalmacrostack\currentdelimitedlanguage + \def\typo_delimited_set_language_nop {\setusedlanguage{\delimitedtextparameter\c!language}} @@ -333,8 +355,8 @@ \let\m_delimited_argument\empty} \def\typo_delimited_push#1#2% - {\globalpushmacro\currentdelimitedtext % can we combine these two - \globalpushmacro\currentdelimitedlanguage % the language used for hyphenation + {\push_macro_currentdelimitedtext % can we combine these two + \push_macro_currentdelimitedlanguage % the language used for hyphenation \edef\currentdelimitedtext{#1}% \edef\m_delimited_argument{#2}% \ifx\m_delimited_argument\empty @@ -350,8 +372,8 @@ \def\typo_delimited_pop {\global\advance\c_typo_delimited_nesting\minusone - \globalpopmacro\currentdelimitedlanguage - \globalpopmacro\currentdelimitedtext} + \pop_macro_currentdelimitedlanguage + \pop_macro_currentdelimitedtext} \installcorenamespace{delimitedtext} \installcorenamespace{delimitedtextlevel} @@ -414,6 +436,8 @@ \dostoptagged \ignorespaces} +\newconditional\c_typo_delimited_repeating + \def\typo_delimited_start_other {\edef\p_delimited_repeat{\delimitedtextparameter\c!repeat}% \ifx\p_delimited_repeat\v!yes @@ -421,6 +445,7 @@ \else \let\typo_delimited_repeat\relax \fi + \setfalse\c_typo_delimited_repeating \edef\p_delimited_location{\delimitedtextparameter\c!location}% \ifx\p_delimited_location\v!paragraph \singleexpandafter\typo_delimited_start_par @@ -493,7 +518,7 @@ \let\typo_delimited_stop_par_indeed\stopnarrower \fi % so far - \pushmacro\checkindentation + \push_macro_checkindentation \useindentingparameter\delimitedtextparameter % \begingroup @@ -515,7 +540,7 @@ {\typo_delimited_stop_content \rightdelimitedtextmark \carryoverpar\endgroup % new per 2013-01-21 ... please left floats - \popmacro\checkindentation + \pop_macro_checkindentation \typo_delimited_stop_par_indeed \delimitedtextparameter\c!after \edef\p_delimited_spaceafter{\delimitedtextparameter\c!spaceafter}% @@ -680,30 +705,37 @@ % test test test % \stoptext -\def\typo_delimited_handle_middle#1% - {\typo_delimited_stop_content - \begingroup - \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor - \setbox\scratchbox\hbox{\delimitedtextparameter#1}% - \ifdim\wd\scratchbox>\zeropoint - \ifdim\lastkern=\d_typo_delimited_signal - \unkern - \hskip\hspaceamount\currentusedlanguage{interquotation}% +% We have no real test case for this and it's broken already for a while, +% even in \MKII. Maybe we should to this in \LUA. Only Italian has the +% middlespeech parameter set. + +\def\typo_delimited_handle_middle#1% special case + {\ifconditional\c_typo_delimited_repeating + \begingroup + \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor + \setbox\scratchbox\hbox{\delimitedtextparameter#1}% + \ifdim\wd\scratchbox>\zeropoint + \ifdim\lastkern=\d_typo_delimited_signal + \unkern + \hskip\hspaceamount\currentusedlanguage{interquotation}% + \else % maybe an option: + %\edef\p_delimited_margin{\delimitedtextparameter\c!location}% + %\ifx\p_delimited_margin\v!margin + % \hskip-\wd\scratchbox + %\fi + \fi + \strut % new, needed below + \dostarttagged\t!delimitedsymbol\empty + \dotagsetdelimitedsymbol\s!middle + \delimitedtextparameter#1% unhbox\scratchbox + \dostoptagged + % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods + \kern\d_typo_delimited_signal % +- \prewordbreak \fi - \ifhmode % else funny pagebeaks - \penalty\plustenthousand - \hskip\zeropoint % == \prewordbreak - \fi - \strut % new, needed below - \dostarttagged\t!delimitedsymbol\empty - \dotagsetdelimitedsymbol\s!middle - \delimitedtextparameter#1% unhbox\scratchbox - \dostoptagged - % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods - \kern\d_typo_delimited_signal % +- \prewordbreak - \fi - \endgroup - \typo_delimited_start_content} + \endgroup + \else + \settrue\c_typo_delimited_repeating + \fi} \def\typo_delimited_handle_left#1% {\begingroup @@ -717,11 +749,11 @@ \unskip \hskip\hspaceamount\currentusedlanguage{interquotation}% \fi\fi - \strut % new, needed below - \ifhmode % else funny pagebeaks - \penalty\plustenthousand - \hskip\zeropoint % == \prewordbreak - \fi + % \strut % new, needed below + % \ifhmode % else funny pagebeaks + % \penalty\plustenthousand + % \hskip\zeropoint % == \prewordbreak + % \fi \strut % new, needed below \dostarttagged\t!delimitedsymbol\empty \dotagsetdelimitedsymbol\s!left diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua index af01f0f0d0a..c0bbdc39668 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dha.lua @@ -41,13 +41,11 @@ if not modules then modules = { } end modules ['typo-dha'] = { local nodes, node = nodes, node -local trace_directions = false trackers.register("typesetters.directions.default", function(v) trace_directions = v end) +local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end) local report_directions = logs.reporter("typesetting","text directions") local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -57,7 +55,7 @@ local getsubtype = nuts.getsubtype local getlist = nuts.getlist local getattr = nuts.getattr local getprop = nuts.getprop -local getdir = nuts.getdir +local getdirection = nuts.getdirection local isglyph = nuts.isglyph -- or ischar local setprop = nuts.setprop @@ -71,7 +69,7 @@ local end_of_math = nuts.end_of_math local nodepool = nuts.pool local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local glyph_code = nodecodes.glyph local math_code = nodecodes.math @@ -80,9 +78,13 @@ local glue_code = nodecodes.glue local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local parfillskip_code = skipcodes.parfillskip +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft -local new_textdir = nodepool.textdir +local parfillskip_code = gluecodes.parfillskip + +local new_direction = nodepool.direction local insert = table.insert @@ -104,14 +106,14 @@ local strip = false local s_isol = fonts.analyzers.states.isol -local function stopdir(finish) - local n = new_textdir(finish == "TRT" and "-TRT" or "-TLT") +local function stopdir(finish) -- we could use finish directly + local n = new_direction(finish == righttoleft_code and righttoleft_code or lefttoright_code,true) setprop(n,"direction",true) return n end -local function startdir(finish) - local n = new_textdir(finish == "TRT" and "+TRT" or "+TLT") +local function startdir(finish) -- we could use finish directly + local n = new_direction(finish == righttoleft_code and righttoleft_code or lefttoright_code) setprop(n,"direction",true) return n end @@ -136,7 +138,7 @@ end local function process(start) - local head = tonut(start) -- we have a global head + local head = start local current = head local autodir = 0 local embedded = 0 @@ -309,27 +311,31 @@ local function process(start) elseif id == kern_code then setprop(current,"direction",'k') elseif id == dir_code then - local dir = getdir(current) - if dir == "+TRT" then - autodir = -1 - elseif dir == "+TLT" then - autodir = 1 - elseif dir == "-TRT" or dir == "-TLT" then - if embedded and embedded~= 0 then + local direction, pop = getdirection(current) + if direction == righttoleft_code then + if not pop then + autodir = -1 + elseif embedded and embedded~= 0 then + autodir = embedded + else + autodir = 0 + end + elseif direction == lefttoright_code then + if not pop then + autodir = 1 + elseif embedded and embedded~= 0 then autodir = embedded else autodir = 0 end - else - -- message end textdir = autodir setprop(current,"direction",true) - elseif id == localpar_code then - local dir = getdir(current) - if dir == 'TRT' then + elseif id == localpar_code and getsubtype(current) == 0 then + local direction = getdirection(current) + if direction == righttoleft_code then autodir = -1 - elseif dir == 'TLT' then + elseif direction == lefttoright_code then autodir = 1 end pardir = autodir @@ -443,7 +449,7 @@ local function process(start) end end - return tonode(head), done + return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua index 61e96c6b6a2..175fc0cc7ef 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dig.lua @@ -20,15 +20,12 @@ local report_digits = logs.reporter("typesetting","digits") local nodes, node = nodes, node local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev -local getfont = nuts.getfont -local getchar = nuts.getchar local getid = nuts.getid local getwidth = nuts.getwidth +local isglyph = nuts.isglyph local takeattr = nuts.takeattr local setlink = nuts.setlink @@ -99,8 +96,7 @@ function nodes.aligned(head,start,stop,width,how) end actions[1] = function(head,start,attr) - local font = getfont(start) - local char = getchar(start) + local char, font = isglyph(start) local unic = chardata[font][char].unicode or char if charbase[unic].category == "nd" then -- ignore unic tables local oldwidth = getwidth(start) @@ -111,23 +107,21 @@ actions[1] = function(head,start,attr) attr%100,div(attr,100),char,unic,newwidth-oldwidth) end head, start = nodes.aligned(head,start,start,newwidth,"middle") - return head, start, true + return head, start end end - return head, start, false + return head, start end function digits.handler(head) - head = tonut(head) - local done, current, ok = false, head, false + local current = head while current do if getid(current) == glyph_code then local attr = takeattr(current,a_digits) if attr and attr > 0 then local action = actions[attr%100] -- map back to low number if action then - head, current, ok = action(head,current,attr) - done = done and ok + head, current = action(head,current,attr) elseif trace_digits then report_digits("unknown digit trigger %a",attr) end @@ -137,7 +131,7 @@ function digits.handler(head) current = getnext(current) end end - return tonode(head), done + return head end local m, enabled = 0, false -- a trick to make neighbouring ranges work diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua index 7fbf5f6d3eb..88c84bd0244 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.lua @@ -45,8 +45,9 @@ local band = bit32.band local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue -local getnext = nodes.getnext -local getattr = nodes.getattr +local nuts = nodes.nuts +local getnext = nuts.getnext +local getattr = nuts.getattr local enableaction = nodes.tasks.enableaction local tracers = nodes.tracers @@ -165,24 +166,24 @@ local stoptiming = statistics.stoptiming -- -- \enabledirectives[typesetters.directions.onetoo] -function directions.handler(head,_,_,_,direction) +function directions.handler(head,where,_,_,direction) local only_one = not getnext(head) if only_one and not one_too then - return head, false + return head end local attr = getattr(head,a_directions) if not attr or attr == 0 then - return head, false + return head end local method = getmethod(attr) local handler = handlers[method] if not handler then - return head, false + return head end starttiming(directions) - local head, done = handler(head,direction,only_one) + head = handler(head,direction,only_one,where) stoptiming(directions) - return head, done + return head end statistics.register("text directions", function() diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv index d92c9379351..7449a705323 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dir.mkiv @@ -18,17 +18,13 @@ \unprotect -\registerctxluafile{typo-dir}{} +\registerctxluafile{typo-dir}{optimize} \registerctxluafile{typo-dha}{} -\registerctxluafile{typo-dua}{} -\registerctxluafile{typo-dub}{} -\doifelsefileexists{typo-duc-new.lua} { - \registerctxluafile{typo-duc-new}{} -} { - \registerctxluafile{typo-duc}{} -} +%registerctxluafile{typo-dua}{} +%registerctxluafile{typo-dub}{} +\registerctxluafile{typo-duc}{} -\definesystemattribute[directions][public] +\definesystemattribute[directions][public,pickup] \installcorenamespace{directions} \installcorenamespace{directionsbidimode} @@ -69,8 +65,9 @@ \expandafter\glet\csname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode} \appendtoks + \edef\p_bidi{\directionsparameter\c!bidi}% \edef\currentbidistamp - {\directionsparameter\c!bidi + {\p_bidi :\directionsparameter\c!method :\directionsparameter\c!fences}% \expandafter\let\expandafter\currentbidimode\csname\??directionsbidimode\currentbidistamp\endcsname @@ -83,6 +80,11 @@ \else \setdirection[\number\directionsbidimode]% \fi + \ifx\p_bidi\v!global + \pickupdirectionsattribute + \else + \forgetdirectionsattribute + \fi \to \everysetupdirections \appendtoks @@ -104,8 +106,8 @@ \unexpanded\edef\bidilro{\normalUchar"202D} \unexpanded\edef\bidirlo{\normalUchar"202E} -\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdir TLT\fi} -\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdir TRT\fi} +\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi} +\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi} \unexpanded\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi} \unexpanded\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi} @@ -121,85 +123,85 @@ % bidi test -\definefontfeature - [arab] - [mode=node,language=dflt,script=arab, - init=yes,medi=yes,fina=yes,isol=yes, - liga=yes,dlig=yes,rlig=yes,clig=yes, - mark=yes,mkmk=yes,kern=yes,curs=yes] - -\font\Arabic=arabtype*arab at 20pt - -\def\LATIN{LATIN} {\setdirection[1]} % enable this -\def\ARAB {محمد} - -\startluacode - function documentdata.split_tokens(str) - for s in str:bytes() do - context.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s)) - end - end -\stopluacode - -\unexpanded\def\biditest#1#2#3% font text raw - {\dontleavehmode\hbox - {\framed[offset=overlay]{\tttf#2}\quad - \enabletrackers[typesetters.directions]% - \framed[offset=overlay]{#1#3}\quad - \disabletrackers[typesetters.directions]% - \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}} - -\startbuffer[bidi-sample] -\biditest\Arabic{LATIN BARA}{\textdir TLT\relax \LATIN\ \ARAB}\par -\biditest\Arabic{BARA LATIN}{\textdir TRT\relax \LATIN\ \ARAB}\par -\biditest\Arabic{LATIN ARAB}{\textdir TLT{\bidilro \LATIN\ \ARAB}}\par % right -> left -\biditest\Arabic{LATIN ARAB}{\textdir TRT{\bidilro \LATIN\ \ARAB}}\par % right -> left -\biditest\Arabic{BARA NITAL}{\textdir TLT{\bidirlo \LATIN\ \ARAB}}\par % left -> right -\biditest\Arabic{BARA NITAL}{\textdir TRT{\bidirlo \LATIN\ \ARAB}}\par % left -> right -\stopbuffer - -\startbuffer[bidi-sample] -\biditest\Arabic{LATIN BARA}{\textdir TLT\relax \LATIN\ \ARAB}\par -\biditest\Arabic{BARA LATIN}{\textdir TRT\relax \LATIN\ \ARAB}\par -\biditest\Arabic{LATIN ARAB}{\textdir TLT\bidilro \LATIN\ \ARAB}\par % right -> left -\biditest\Arabic{LATIN ARAB}{\textdir TRT\bidilro \LATIN\ \ARAB}\par % right -> left -\biditest\Arabic{BARA NITAL}{\textdir TLT\bidirlo \LATIN\ \ARAB}\par % left -> right -\biditest\Arabic{BARA NITAL}{\textdir TRT\bidirlo \LATIN\ \ARAB}\par % left -> right -\stopbuffer - -\startbuffer[bidi-setup] -\setupdirections[bidi=off] -\stopbuffer - -{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} - -\startbuffer[bidi-setup] -\setupdirections[bidi=global] -\stopbuffer - -{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} - -\startbuffer[bidi-setup] -\setupdirections[bidi=local] -\stopbuffer - -{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} - -\startbuffer[bidi-sample] -\setupdirections[bidi=global] - - \hbox{\righttoleft\arabicfont (0001)}\par - \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par - {\righttoleft\arabicfont (0003)\par} - {\righttoleft\arabicfont (0004)}\par - \dontleavehmode{\righttoleft\arabicfont (0005)\par} - \dontleavehmode{\righttoleft\arabicfont (0006)}\par - \rtlhbox{\arabicfont (0007)}\par - \ltrhbox{\arabicfont (0008)}\par -\dontleavehmode\rtlhbox{\arabicfont (0009)}\par -\dontleavehmode\ltrhbox{\arabicfont (0010)}\par -\stopsetups - -{\typebuffer[bidi-sample] \getbuffer[bidi-sample]} - -\stoptext +% \definefontfeature +% [arab] +% [mode=node,language=dflt,script=arab, +% init=yes,medi=yes,fina=yes,isol=yes, +% liga=yes,dlig=yes,rlig=yes,clig=yes, +% mark=yes,mkmk=yes,kern=yes,curs=yes] +% +% \font\Arabic=arabtype*arab at 20pt +% +% \def\LATIN{LATIN} {\setdirection[1]} % enable this +% \def\ARAB {عربي} +% +% \startluacode +% function documentdata.split_tokens(str) +% for s in str:bytes() do +% context.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s)) +% end +% end +% \stopluacode +% +% \unexpanded\def\biditest#1#2#3% font text raw +% {\dontleavehmode\hbox +% {\framed[offset=overlay]{\tttf#2}\quad +% \enabletrackers[typesetters.directions]% +% \framed[offset=overlay]{#1#3}\quad +% \disabletrackers[typesetters.directions]% +% \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}} +% +% \startbuffer[bidi-sample] +% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{LATIN ARAB}{\lefttoright{\bidilro \LATIN\ \ARAB}}\par % right -> left +% \biditest\Arabic{LATIN ARAB}{\righttoleft{\bidilro \LATIN\ \ARAB}}\par % right -> left +% \biditest\Arabic{BARA NITAL}{\lefttoright{\bidirlo \LATIN\ \ARAB}}\par % left -> right +% \biditest\Arabic{BARA NITAL}{\righttoleft{\bidirlo \LATIN\ \ARAB}}\par % left -> right +% \stopbuffer +% +% \startbuffer[bidi-sample] +% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par +% \biditest\Arabic{LATIN ARAB}{\lefttoright\bidilro \LATIN\ \ARAB}\par % right -> left +% \biditest\Arabic{LATIN ARAB}{\righttoleft\bidilro \LATIN\ \ARAB}\par % right -> left +% \biditest\Arabic{BARA NITAL}{\lefttoright\bidirlo \LATIN\ \ARAB}\par % left -> right +% \biditest\Arabic{BARA NITAL}{\righttoleft\bidirlo \LATIN\ \ARAB}\par % left -> right +% \stopbuffer +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=off] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=global] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-setup] +% \setupdirections[bidi=local] +% \stopbuffer +% +% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]} +% +% \startbuffer[bidi-sample] +% \setupdirections[bidi=global] +% +% \hbox{\righttoleft\arabicfont (0001)}\par +% \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par +% {\righttoleft\arabicfont (0003)\par} +% {\righttoleft\arabicfont (0004)}\par +% \dontleavehmode{\righttoleft\arabicfont (0005)\par} +% \dontleavehmode{\righttoleft\arabicfont (0006)}\par +% \rtlhbox{\arabicfont (0007)}\par +% \ltrhbox{\arabicfont (0008)}\par +% \dontleavehmode\rtlhbox{\arabicfont (0009)}\par +% \dontleavehmode\ltrhbox{\arabicfont (0010)}\par +% \stopsetups +% +% {\typebuffer[bidi-sample] \getbuffer[bidi-sample]} +% +% \stoptext diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua index 1e142280fed..9a59891e103 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.lua @@ -28,14 +28,11 @@ local enableaction = tasks.enableaction local disableaction = tasks.disableaction local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev local getchar = nuts.getchar local getid = nuts.getid -local getsubtype = nuts.getsubtype local getattr = nuts.getattr local getwhd = nuts.getwhd @@ -59,8 +56,9 @@ local new_kern = nodepool.kern local insert_before = nuts.insert_before local insert_after = nuts.insert_after local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse + +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph local variables = interfaces.variables local v_default = variables.default @@ -139,9 +137,8 @@ interfaces.implement { -- a page so this has a low priority actions[v_default] = function(head,setting) - local done = false local id = getid(head) - if id == localpar_code then + if id == localpar_code then -- and getsubtype(head) == 0 -- begin of par local first = getnext(head) local indent = false @@ -173,7 +170,7 @@ actions[v_default] = function(head,setting) -- 1 char | n chars | skip first quote | ignore punct | keep punct -- if getattr(first,a_initial) then - for current in traverse(getnext(first)) do + for current in nextnode, getnext(first) do if getattr(current,a_initial) then last = current else @@ -189,10 +186,10 @@ actions[v_default] = function(head,setting) local next = getnext(first) if not next then -- don't start with a quote or so - return head, false + return head end last = nil - for current in traverse_id(glyph_code,next) do + for current in nextglyph, next do head, first = remove_node(head,first,true) first = current last = first @@ -200,21 +197,21 @@ actions[v_default] = function(head,setting) end if not last then -- no following glyph or so - return head, false + return head end else -- keep quote etc with initial local next = getnext(first) if not next then -- don't start with a quote or so - return head, false + return head end - for current in traverse_id(glyph_code,next) do + for current in nextglyph, next do last = current break end if last == first then - return head, false + return head end end elseif kind == "pf" then @@ -225,8 +222,7 @@ actions[v_default] = function(head,setting) -- maybe also: get all A. B. etc local next = getnext(first) if next then - for current in traverse_id(glyph_code,next) do - local char = getchar(current) + for current, char in nextglyph, next do local kind = category(char) if kind == "po" then if method[v_last] then @@ -241,7 +237,7 @@ actions[v_default] = function(head,setting) end end else - for current in traverse_id(glyph_code,first) do + for current in nextglyph, first do last = current if length <= 1 then break @@ -265,12 +261,12 @@ actions[v_default] = function(head,setting) end -- apply font --- local g = nodes.copy(tonode(current)) +-- local g = nuts.copy(current) -- g.subtype = 0 -- nodes.handlers.characters(g) -- nodes.handlers.protectglyphs(g) -- setchar(current,g.char) --- nodes.flush_node(g) +-- nuts.flush_node(g) -- can be a helper if ca and ca > 0 then @@ -319,7 +315,7 @@ actions[v_default] = function(head,setting) end -- local hoffset = width + hoffset + distance + (indent and parindent or 0) - for current in traverse_id(glyph_code,first) do + for current in nextglyph, first do setoffsets(current,-hoffset,-voffset) -- no longer - height here if current == last then break @@ -347,14 +343,12 @@ actions[v_default] = function(head,setting) if indent then insert_after(first,first,new_kern(-parindent)) end - done = true end end - return head, done + return head end function initials.handler(head) - head = tonut(head) local start = head local attr = nil while start do @@ -377,9 +371,8 @@ function initials.handler(head) if trace_initials then report_initials("processing initials, alternative %a",alternative) end - local head, done = action(head,settings) - return tonode(head), done + return action(head,settings) end end - return tonode(head), false + return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv index 371ea38d60e..18392510803 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-drp.mkiv @@ -118,7 +118,7 @@ \kern\zeropoint % we need a node \p_text \endgroup - \globallet\typo_initial_handle\relax} + \glet\typo_initial_handle\relax} \let\typo_initial_handle\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua index 1e48dfb9178..3db5f510ac1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dua.lua @@ -68,8 +68,6 @@ local directiondata = characters.directions local mirrordata = characters.mirrors local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -77,11 +75,11 @@ local getsubtype = nuts.getsubtype local getlist = nuts.getlist local getchar = nuts.getchar local getprop = nuts.getprop -local getdir = nuts.getdir +local getdirection = nuts.getdirection local setprop = nuts.setprop local setchar = nuts.setchar -local setdir = nuts.setdir +local setdirection = nuts.setdirection ----- setattrlist = nuts.setattrlist local remove_node = nuts.remove @@ -89,10 +87,10 @@ local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local nodepool = nuts.pool -local new_textdir = nodepool.textdir +local new_direction = nodepool.direction local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue @@ -101,23 +99,28 @@ local vlist_code = nodecodes.vlist local math_code = nodecodes.math local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local parfillskip_code = skipcodes.parfillskip ------ object_replacement = 0xFFFC -- object replacement character -local maximum_stack = 60 -- probably spec but not needed +local parfillskip_code = gluecodes.parfillskip + +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local maximum_stack = 60 local directions = typesetters.directions local setcolor = directions.setcolor ------ a_directions = attributes.private('directions') - local remove_controls = true directives.register("typesetters.directions.one.removecontrols",function(v) remove_controls = v end) -local trace_directions = false trackers .register("typesetters.directions.one", function(v) trace_directions = v end) -local trace_details = false trackers .register("typesetters.directions.one.details", function(v) trace_details = v end) - local report_directions = logs.reporter("typesetting","directions one") +local trace_directions = false trackers .register("typesetters.directions", function(v) trace_directions = v end) +local trace_details = false trackers .register("typesetters.directions.details", function(v) trace_details = v end) + + + + local whitespace = { lre = true, rle = true, @@ -234,13 +237,19 @@ local function build_list(head) -- todo: store node pointer ... saves loop list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 } current = getnext(current) elseif id == dir_code then - local dir = getdir(current) - if dir == "+TLT" then - list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } - elseif dir == "+TRT" then - list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 } - elseif dir == "-TLT" or dir == "-TRT" then - list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + local direction, pop = getdirection(current) + if direction == lefttoright_code then + if pop then + list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + else + list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } + end + elseif direction == righttoleft_code then + if pop then + list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + else + list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 } + end else list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character end @@ -323,27 +332,33 @@ local function find_run_limit_b_s_ws_on(list,start,limit) return start end -local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar) - local id = getid(head) - if id == localpar_code then - if getdir(head) == "TRT" then - return 1, "TRT", true - else - return 0, "TLT", true +local function get_baselevel(head,list,size,direction) + -- This is an adapted version: + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true + elseif getid(head) == localpar_code and getsubtype(head) == 0 then + direction = getdirection(head) + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true end - else - -- P2, P3 - for i=1,size do - local entry = list[i] - local direction = entry.direction - if direction == "r" or direction == "al" then - return 1, "TRT", true - elseif direction == "l" then - return 0, "TLT", true - end + end + -- for old times sake we we handle strings too + if direction == "TLT" then + return lefttoright_code, true + elseif direction == "TRT" then + return righttoleft_code, true + end + -- P2, P3 + for i=1,size do + local entry = list[i] + local direction = entry.direction + if direction == "r" or direction == "al" then + return righttoleft_code, true + elseif direction == "l" then + return lefttoright_code, true end - return 0, "TLT", false end + return lefttoright_code, false end local function resolve_explicit(list,size,baselevel) @@ -409,7 +424,7 @@ local function resolve_explicit(list,size,baselevel) end -- X7 elseif direction == "pdf" then - if nofstack < maximum_stack then + if noifstack > 0 then local stacktop = stack[nofstack] nofstack = nofstack - 1 level = stacktop[1] @@ -418,7 +433,7 @@ local function resolve_explicit(list,size,baselevel) entry.direction = "bn" entry.remove = true elseif trace_directions then - report_directions("stack overflow at position %a with direction %a",i,direction) + report_directions("stack underflow at position %a with direction %a",i,direction) end -- X6 else @@ -679,8 +694,6 @@ local function resolve_levels(list,size,baselevel) end end --- This is not ok but we keep it as-is: - local function insert_dir_points(list,size) -- L2, but no actual reversion is done, we simply annotate where -- begindir/endddir node will be inserted. @@ -697,11 +710,11 @@ local function insert_dir_points(list,size) local begindir = nil local enddir = nil if level % 2 == 1 then - begindir = "+TRT" - enddir = "-TRT" + begindir = righttoleft_code + enddir = righttoleft_code else - begindir = "+TLT" - enddir = "-TLT" + begindir = lefttoright_code + enddir = lefttoright_code end for i=1,size do local entry = list[i] @@ -730,7 +743,6 @@ end local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false while current do if index > size then report_directions("fatal error, size mismatch") @@ -751,34 +763,31 @@ local function apply_to_list(list,size,head,pardir) setcolor(current,direction,false,mirror) end elseif id == hlist_code or id == vlist_code then - setdir(current,pardir) -- is this really needed? + setdirection(current,pardir) -- is this really needed? elseif id == glue_code then if enddir and getsubtype(current) == parfillskip_code then -- insert the last enddir before \parfillskip glue - local d = new_textdir(enddir) - setprop(d,"directions",true) + local d = new_direction(enddir,true) + -- setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) enddir = false - done = true end elseif begindir then - if id == localpar_code then + if id == localpar_code and getsubtype(current) == 0 then -- localpar should always be the 1st node - local d = new_textdir(begindir) - setprop(d,"directions",true) + local d = new_direction(begindir) + -- setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) begindir = nil - done = true end end if begindir then - local d = new_textdir(begindir) - setprop(d,"directions",true) + local d = new_direction(begindir) + -- setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) - done = true end local skip = entry.skip if skip and skip > 0 then @@ -788,30 +797,28 @@ local function apply_to_list(list,size,head,pardir) end end if enddir then - local d = new_textdir(enddir) - setprop(d,"directions",true) + local d = new_direction(enddir,true) + -- setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) - done = true end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end index = index + 1 end - return head, done + return head end -local function process(head) - head = tonut(head) +local function process(head,direction,only_one,where) + -- This is an adapted version: local list, size = build_list(head) - local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context + local baselevel, dirfound = get_baselevel(head,list,size,direction) if not dirfound and trace_details then report_directions("no initial direction found, gambling") end @@ -825,8 +832,7 @@ local function process(head) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,baselevel) end directions.installhandler(interfaces.variables.one,process) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua index d0747ae6ccd..f27e4047660 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-dub.lua @@ -55,8 +55,6 @@ local mirrordata = characters.mirrors local textclassdata = characters.textclasses local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -65,11 +63,11 @@ local getlist = nuts.getlist local getchar = nuts.getchar local getattr = nuts.getattr local getprop = nuts.getprop -local getdir = nuts.getdir +local getdirection = nuts.getdirection local setprop = nuts.setprop local setchar = nuts.setchar -local setdir = nuts.setdir +local setdirection = nuts.setdirection local setattrlist = nuts.setattrlist local remove_node = nuts.remove @@ -77,10 +75,10 @@ local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local nodepool = nuts.pool -local new_textdir = nodepool.textdir +local new_direction = nodepool.direction local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue @@ -89,24 +87,29 @@ local vlist_code = nodecodes.vlist local math_code = nodecodes.math local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local parfillskip_code = skipcodes.parfillskip -local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much +local parfillskip_code = gluecodes.parfillskip + +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local maximum_stack = 0xFF + +local a_directions = attributes.private('directions') local directions = typesetters.directions local setcolor = directions.setcolor local getfences = directions.getfences -local a_directions = attributes.private('directions') - local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end) ----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end) -local trace_directions = false trackers .register("typesetters.directions.two", function(v) trace_directions = v end) -local trace_details = false trackers .register("typesetters.directions.two.details", function(v) trace_details = v end) -local trace_list = false trackers .register("typesetters.directions.two.list", function(v) trace_list = v end) +local report_directions = logs.reporter("typesetting","directions three") -local report_directions = logs.reporter("typesetting","directions two") +local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end) +local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end) +local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end) -- strong (old): -- @@ -117,7 +120,7 @@ local report_directions = logs.reporter("typesetting","directions two") -- lre : left to right embedding -- rle : left to left embedding -- al : right to legt arabic (esp punctuation issues) - +-- -- weak: -- -- en : english number @@ -127,23 +130,23 @@ local report_directions = logs.reporter("typesetting","directions two") -- cs : common number separator -- nsm : nonspacing mark -- bn : boundary neutral - +-- -- neutral: -- -- b : paragraph separator -- s : segment separator -- ws : whitespace -- on : other neutrals - +-- -- interesting: this is indeed better (and more what we expect i.e. we already use this split -- in the old original (also these isolates) - +-- -- strong (new): -- -- l : left to right -- r : right to left -- al : right to left arabic (esp punctuation issues) - +-- -- explicit: (new) -- -- lro : left to right override @@ -206,27 +209,28 @@ end local function show_done(list,size) local joiner = utfchar(0x200C) local result = { } + local format = formatters["<%s>"] for i=1,size do local entry = list[i] local character = entry.char local begindir = entry.begindir local enddir = entry.enddir if begindir then - result[#result+1] = formatters["<%s>"](begindir) + result[#result+1] = format(begindir) end if entry.remove then -- continue elseif character == 0xFFFC then - result[#result+1] = formatters["<%s>"]("?") + result[#result+1] = format("?") elseif character == 0x0020 then - result[#result+1] = formatters["<%s>"](" ") + result[#result+1] = format(" ") elseif character >= 0x202A and character <= 0x202C then - result[#result+1] = formatters["<%s>"](entry.original) + result[#result+1] = format(entry.original) else result[#result+1] = utfchar(character) end if enddir then - result[#result+1] = formatters["<%s>"](enddir) + result[#result+1] = format(enddir) end end return concat(result,joiner) @@ -236,17 +240,7 @@ end -- char is only used for mirror, so in fact we can as well only store it for -- glyphs only --- using metatable is slightly faster so maybe some day ... - --- local space = { char = 0x0020, direction = "ws", original = "ws" } --- local lre = { char = 0x202A, direction = "lre", original = "lre" } --- local rle = { char = 0x202B, direction = "rle", original = "rle" } --- local pdf = { char = 0x202C, direction = "pdf", original = "pdf" } --- local object = { char = 0xFFFC, direction = "on", original = "on" } --- --- local t = { level = 0 } setmetatable(t,space) list[size] = t - -local function build_list(head) -- todo: store node pointer ... saves loop +local function build_list(head) -- P1 local current = head local list = { } @@ -282,13 +276,19 @@ local function build_list(head) -- todo: store node pointer ... saves loop list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 } current = getnext(current) elseif id == dir_code then - local dir = getdir(current) - if dir == "+TLT" then - list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } - elseif dir == "+TRT" then - list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 } - elseif dir == "-TLT" or dir == "-TRT" then - list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + local direction, pop = getdirection(current) + if direction == lefttoright_code then + if pop then + list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + else + list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } + end + elseif direction == righttoleft_code then + if pop then + list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } + else + list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 } + end else list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character end @@ -343,8 +343,8 @@ end local function resolve_fences(list,size,start,limit) -- N0: funny effects, not always better, so it's an option - local stack = { } - local top = 0 + local stack = { } + local nofstack = 0 for i=start,limit do local entry = list[i] if entry.direction == "on" then @@ -355,15 +355,15 @@ local function resolve_fences(list,size,start,limit) entry.mirror = mirror entry.class = class if class == "open" then - top = top + 1 - stack[top] = { mirror, i, false } - elseif top == 0 then + nofstack = nofstack + 1 + stack[nofstack] = { mirror, i, false } + elseif nofstack == 0 then -- skip elseif class == "close" then - while top > 0 do - local s = stack[top] - if s[1] == char then - local open = s[2] + while nofstack > 0 do + local stacktop = stack[nofstack] + if stacktop[1] == char then + local open = stacktop[2] local close = i list[open ].paired = close list[close].paired = open @@ -371,7 +371,7 @@ local function resolve_fences(list,size,start,limit) else -- do we mirror or not end - top = top - 1 + nofstack = nofstack - 1 end end end @@ -394,27 +394,32 @@ end -- the action -local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar) - local id = getid(head) - if id == localpar_code then - if getdir(head) == "TRT" then - return 1, "TRT", true - else - return 0, "TLT", true +local function get_baselevel(head,list,size,direction) + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true + elseif getid(head) == localpar_code and getsubtype(head) == 0 then + direction = getdirection(head) + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true end - else - -- P2, P3 - for i=1,size do - local entry = list[i] - local direction = entry.direction - if direction == "r" or direction == "al" then -- and an ? - return 1, "TRT", true - elseif direction == "l" then - return 0, "TLT", true - end + end + -- for old times sake we we handle strings too + if direction == "TLT" then + return lefttoright_code, true + elseif direction == "TRT" then + return righttoleft_code, true + end + -- P2, P3 + for i=1,size do + local entry = list[i] + local direction = entry.direction + if direction == "r" or direction == "al" then -- and an ? + return righttoleft_code, true + elseif direction == "l" then + return lefttoright_code, true end - return 0, "TLT", false end + return lefttoright_code, false end local function resolve_explicit(list,size,baselevel) @@ -480,16 +485,17 @@ local function resolve_explicit(list,size,baselevel) end -- X7 elseif direction == "pdf" then - if nofstack < maximum_stack then + if nofstack > 0 then local stacktop = stack[nofstack] - nofstack = nofstack - 1 level = stacktop[1] override = stacktop[2] + nofstack = nofstack - 1 entry.level = level entry.direction = "bn" entry.remove = true elseif trace_directions then - report_directions("stack overflow at position %a with direction %a",i,direction) + report_directions("stack underflow at position %a with direction %a", + i, direction) end -- X6 else @@ -688,33 +694,6 @@ local function resolve_neutral(list,size,start,limit,orderbefore,orderafter) end end --- local function resolve_implicit(list,size,start,limit,orderbefore,orderafter) --- -- I1 --- for i=start,limit do --- local entry = list[i] --- local level = entry.level --- if level % 2 ~= 1 then -- not odd(level) --- local direction = entry.direction --- if direction == "r" then --- entry.level = level + 1 --- elseif direction == "an" or direction == "en" then --- entry.level = level + 2 --- end --- end --- end --- -- I2 --- for i=start,limit do --- local entry = list[i] --- local level = entry.level --- if level % 2 == 1 then -- odd(level) --- local direction = entry.direction --- if direction == "l" or direction == "en" or direction == "an" then --- entry.level = level + 1 --- end --- end --- end --- end - local function resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel) for i=start,limit do local entry = list[i] @@ -814,52 +793,6 @@ local function resolve_levels(list,size,baselevel,analyze_fences) end end --- local function insert_dir_points(list,size) --- -- L2, but no actual reversion is done, we simply annotate where --- -- begindir/endddir node will be inserted. --- local maxlevel = 0 --- local finaldir = false --- for i=1,size do --- local level = list[i].level --- if level > maxlevel then --- maxlevel = level --- end --- end --- for level=0,maxlevel do --- local started = false --- local begindir = nil --- local enddir = nil --- if level % 2 == 1 then --- begindir = "+TRT" --- enddir = "-TRT" --- else --- begindir = "+TLT" --- enddir = "-TLT" --- end --- for i=1,size do --- local entry = list[i] --- if entry.level >= level then --- if not started then --- entry.begindir = begindir --- started = true --- end --- else --- if started then --- list[i-1].enddir = enddir --- started = false --- end --- end --- end --- -- make sure to close the run at end of line --- if started then --- finaldir = enddir --- end --- end --- if finaldir then --- list[size].enddir = finaldir --- end --- end - local function insert_dir_points(list,size) -- L2, but no actual reversion is done, we simply annotate where -- begindir/endddir node will be inserted. @@ -877,12 +810,12 @@ local function insert_dir_points(list,size) local enddir -- = nil local prev -- = nil if toggle then - begindir = "+TLT" - enddir = "-TLT" + begindir = lefttoright_code + enddir = lefttoright_code toggle = false else - begindir = "+TRT" - enddir = "-TRT" + begindir = righttoleft_code + enddir = righttoleft_code toggle = true end for i=1,size do @@ -922,7 +855,7 @@ local function insert_dir_points(list,size) if trace_list and n > 1 then report_directions("unbalanced list") end - last.enddir = s[n] == "+TRT" and "-TRT" or "-TLT" + last.enddir = s[n] == righttoleft_code and righttoleft_code or lefttoright_code end end end @@ -930,7 +863,6 @@ end local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false if trace_list then report_directions("start run") end @@ -964,34 +896,31 @@ local function apply_to_list(list,size,head,pardir) setcolor(current,direction,false,mirror) end elseif id == hlist_code or id == vlist_code then - setdir(current,pardir) -- is this really needed? + setdirection(current,pardir) -- is this really needed? elseif id == glue_code then if enddir and getsubtype(current) == parfillskip_code then -- insert the last enddir before \parfillskip glue - local d = new_textdir(enddir) - setprop(d,"directions",true) + local d = new_direction(enddir,true) + -- setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) enddir = false - done = true end elseif begindir then - if id == localpar_code then + if id == localpar_code and getsubtype(current) == 0 then -- localpar should always be the 1st node - local d = new_textdir(begindir) - setprop(d,"directions",true) + local d = new_direction(begindir) + -- setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) begindir = nil - done = true end end if begindir then - local d = new_textdir(begindir) - setprop(d,"directions",true) + local d = new_direction(begindir) + -- setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) - done = true end local skip = entry.skip if skip and skip > 0 then @@ -1001,18 +930,16 @@ local function apply_to_list(list,size,head,pardir) end end if enddir then - local d = new_textdir(enddir) - setprop(d,"directions",true) + local d = new_direction(enddir,true) + -- setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) - done = true end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end @@ -1021,17 +948,16 @@ local function apply_to_list(list,size,head,pardir) if trace_list then report_directions("stop run") end - return head, done + return head end -local function process(head) - head = tonut(head) +local function process(head,direction,only_one,where) -- for the moment a whole paragraph property local attr = getattr(head,a_directions) local analyze_fences = getfences(attr) -- local list, size = build_list(head) - local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context + local baselevel, dirfound = get_baselevel(head,list,size,direction) if not dirfound and trace_details then report_directions("no initial direction found, gambling") end @@ -1045,8 +971,7 @@ local function process(head) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,baselevel) end directions.installhandler(interfaces.variables.two,process) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua index 52074019047..f91fc4d647d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-duc.lua @@ -7,8 +7,6 @@ if not modules then modules = { } end modules ['typo-duc'] = { comment = "Unicode bidi (sort of) variant c", } --- Will be replaced by typo-duc-new.lua! - -- This is a follow up on typo-uda which itself is a follow up on t-bidi by Khaled Hosny which -- in turn is based on minibidi.c from Arabeyes. This is a further optimizations, as well as -- an update on some recent unicode bidi developments. There is (and will) also be more control @@ -58,8 +56,6 @@ local mirrordata = characters.mirrors local textclassdata = characters.textclasses local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -68,11 +64,12 @@ local getlist = nuts.getlist local getchar = nuts.getchar local getattr = nuts.getattr local getprop = nuts.getprop -local getdir = nuts.getdir +local getdirection = nuts.getdirection +local isglyph = nuts.isglyph local setprop = nuts.setprop local setchar = nuts.setchar -local setdir = nuts.setdir +local setdirection = nuts.setdirection local setattrlist = nuts.setattrlist local properties = nodes.properties.data @@ -82,10 +79,10 @@ local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local nodepool = nuts.pool -local new_textdir = nodepool.textdir +local new_direction = nodepool.direction local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue @@ -94,25 +91,30 @@ local vlist_code = nodecodes.vlist local math_code = nodecodes.math local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local parfillskip_code = skipcodes.parfillskip -local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much +local parfillskip_code = gluecodes.parfillskip + +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local maximum_stack = 0xFF + +local a_directions = attributes.private('directions') local directions = typesetters.directions local setcolor = directions.setcolor local getfences = directions.getfences -local a_directions = attributes.private('directions') - local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end) ----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end) -local trace_directions = false trackers.register("typesetters.directions.three", function(v) trace_directions = v end) -local trace_details = false trackers.register("typesetters.directions.three.details", function(v) trace_details = v end) -local trace_list = false trackers.register("typesetters.directions.three.list", function(v) trace_list = v end) - local report_directions = logs.reporter("typesetting","directions three") +local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end) +local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end) +local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end) + -- strong (old): -- -- l : left to right @@ -122,7 +124,7 @@ local report_directions = logs.reporter("typesetting","directions three") -- lre : left to right embedding -- rle : left to left embedding -- al : right to legt arabic (esp punctuation issues) - +-- -- weak: -- -- en : english number @@ -132,23 +134,23 @@ local report_directions = logs.reporter("typesetting","directions three") -- cs : common number separator -- nsm : nonspacing mark -- bn : boundary neutral - +-- -- neutral: -- -- b : paragraph separator -- s : segment separator -- ws : whitespace -- on : other neutrals - +-- -- interesting: this is indeed better (and more what we expect i.e. we already use this split -- in the old original (also these isolates) - +-- -- strong (new): -- -- l : left to right -- r : right to left -- al : right to left arabic (esp punctuation issues) - +-- -- explicit: (new) -- -- lro : left to right override @@ -241,20 +243,20 @@ end -- keeping the list and overwriting doesn't save much runtime, only a few percent -- char is only used for mirror, so in fact we can as well only store it for -- glyphs only - +-- -- tracking what direction is used and skipping tests is not faster (extra kind of -- compensates gain) -local mt_space = { __index = { char = 0x0020, direction = "ws", original = "ws", level = 0 } } -local mt_lre = { __index = { char = 0x202A, direction = "lre", original = "lre", level = 0 } } -local mt_rle = { __index = { char = 0x202B, direction = "rle", original = "rle", level = 0 } } -local mt_pdf = { __index = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } } -local mt_object = { __index = { char = 0xFFFC, direction = "on", original = "on", level = 0 } } +local mt_space = { __index = { char = 0x0020, direction = "ws", original = "ws", level = 0, skip = 0 } } +local mt_lre = { __index = { char = 0x202A, direction = "lre", original = "lre", level = 0, skip = 0 } } +local mt_rle = { __index = { char = 0x202B, direction = "rle", original = "rle", level = 0, skip = 0 } } +local mt_pdf = { __index = { char = 0x202C, direction = "pdf", original = "pdf", level = 0, skip = 0 } } +local mt_object = { __index = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = 0 } } local stack = table.setmetatableindex("table") -- shared local list = { } -- shared -local function build_list(head) -- todo: store node pointer ... saves loop +local function build_list(head,where) -- P1 local current = head local size = 0 @@ -263,6 +265,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop local id = getid(current) local p = properties[current] if p and p.directions then + -- tricky as dirs can be injected in between local skip = 0 local last = id current = getnext(current) @@ -285,6 +288,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop elseif id == glyph_code then local chr = getchar(current) local dir = directiondata[chr] + -- could also be a metatable list[size] = { char = chr, direction = dir, original = dir, level = 0 } current = getnext(current) -- if not list[dir] then list[dir] = true end -- not faster when we check for usage @@ -292,13 +296,11 @@ local function build_list(head) -- todo: store node pointer ... saves loop list[size] = setmetatable({ },mt_space) current = getnext(current) elseif id == dir_code then - local dir = getdir(current) - if dir == "+TLT" then - list[size] = setmetatable({ },mt_lre) - elseif dir == "+TRT" then - list[size] = setmetatable({ },mt_rle) - elseif dir == "-TLT" or dir == "-TRT" then - list[size] = setmetatable({ },mt_pdf) + local dir, pop = getdirection(current) + if dir == lefttoright_code then + list[size] = setmetatable({ },pop and mt_pdf or mt_lre) + elseif dir == righttoleft_code then + list[size] = setmetatable({ },pop and mt_pdf or mt_rle) else list[size] = setmetatable({ id = id },mt_object) end @@ -351,6 +353,8 @@ end -- ש ( ל ( א ) כ ) 2-8,4-6 -- ש ( ל [ א ] כ ) 2-8,4-6 +local fencestack = table.setmetatableindex("table") + local function resolve_fences(list,size,start,limit) -- N0: funny effects, not always better, so it's an option local nofstack = 0 @@ -365,15 +369,14 @@ local function resolve_fences(list,size,start,limit) entry.class = class if class == "open" then nofstack = nofstack + 1 - local stacktop = stack[nofstack] + local stacktop = fencestack[nofstack] stacktop[1] = mirror stacktop[2] = i - stacktop[3] = false -- not used elseif nofstack == 0 then -- skip elseif class == "close" then while nofstack > 0 do - local stacktop = stack[nofstack] + local stacktop = fencestack[nofstack] if stacktop[1] == char then local open = stacktop[2] local close = i @@ -407,25 +410,31 @@ end -- the action local function get_baselevel(head,list,size,direction) - if not direction and getid(head) == localpar_code then - direction = getdir(head) + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true + elseif getid(head) == localpar_code and getsubtype(head) == 0 then + direction = getdirection(head) + if direction == lefttoright_code or direction == righttoleft_code then + return direction, true + end end - if direction == "TRT" then - return 1, "TRT", true - elseif direction == "TLT" then - return 0, "TLT", true + -- for old times sake we we handle strings too + if direction == "TLT" then + return lefttoright_code, true + elseif direction == "TRT" then + return righttoleft_code, true end - -- P2, P3: + -- P2, P3 for i=1,size do local entry = list[i] local direction = entry.direction if direction == "r" or direction == "al" then -- and an ? - return 1, "TRT", true + return righttoleft_code, true elseif direction == "l" then - return 0, "TLT", true + return lefttoright_code, true end end - return 0, "TLT", false + return lefttoright_code, false end local function resolve_explicit(list,size,baselevel) @@ -499,7 +508,7 @@ local function resolve_explicit(list,size,baselevel) end -- X7 elseif direction == "pdf" then - if nofstack < maximum_stack then + if nofstack > 0 then local stacktop = stack[nofstack] level = stacktop[1] override = stacktop[2] @@ -508,7 +517,11 @@ local function resolve_explicit(list,size,baselevel) entry.direction = "bn" entry.remove = true elseif trace_directions then - report_directions("stack overflow at position %a with direction %a",i,direction) + report_directions("stack underflow at position %a with direction %a", + i, direction) + else + report_directions("stack underflow at position %a with direction %a: %s", + i, direction, show_list(list,size)) end -- X6 else @@ -518,11 +531,6 @@ local function resolve_explicit(list,size,baselevel) end end end --- else --- for i=1,size do --- list[i].level = baselevel --- end --- end -- X8 (reset states and overrides after paragraph) end @@ -726,33 +734,6 @@ local function resolve_neutral(list,size,start,limit,orderbefore,orderafter) end end --- local function resolve_implicit(list,size,start,limit,orderbefore,orderafter) --- -- I1 --- for i=start,limit do --- local entry = list[i] --- local level = entry.level --- if level % 2 ~= 1 then -- not odd(level) --- local direction = entry.direction --- if direction == "r" then --- entry.level = level + 1 --- elseif direction == "an" or direction == "en" then --- entry.level = level + 2 --- end --- end --- end --- -- I2 --- for i=start,limit do --- local entry = list[i] --- local level = entry.level --- if level % 2 == 1 then -- odd(level) --- local direction = entry.direction --- if direction == "l" or direction == "en" or direction == "an" then --- entry.level = level + 1 --- end --- end --- end --- end - local function resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel) for i=start,limit do local entry = list[i] @@ -852,60 +833,6 @@ local function resolve_levels(list,size,baselevel,analyze_fences) end end --- local function insert_dir_points(list,size) --- -- L2, but no actual reversion is done, we simply annotate where --- -- begindir/endddir node will be inserted. --- local maxlevel = 0 --- local finaldir = false --- local toggle = true --- for i=1,size do --- local level = list[i].level --- if level > maxlevel then --- maxlevel = level --- end --- end --- for level=0,maxlevel do --- local started -- = false --- local begindir -- = nil --- local enddir -- = nil --- local prev -- = nil --- if toggle then --- begindir = "+TLT" --- enddir = "-TLT" --- toggle = false --- else --- begindir = "+TRT" --- enddir = "-TRT" --- toggle = true --- end --- for i=1,size do --- local entry = list[i] --- if entry.level >= level then --- if not started then --- entry.begindir = begindir --- started = true --- end --- else --- if started then --- prev.enddir = enddir --- started = false --- end --- end --- prev = entry --- end --- -- make sure to close the run at end of line --- if started then --- finaldir = enddir --- end --- end --- if finaldir then --- list[size].enddir = finaldir --- end --- for i=1,size do --- print("<",i,list[i].level,list[i].begindir,list[i].enddir) --- end --- end - local stack = { } local function insert_dir_points(list,size) @@ -925,12 +852,12 @@ local function insert_dir_points(list,size) local enddir -- = nil local prev -- = nil if toggle then - begindir = "+TLT" - enddir = "-TLT" + begindir = lefttoright_code + enddir = lefttoright_code toggle = false else - begindir = "+TRT" - enddir = "-TRT" + begindir = righttoleft_code + enddir = righttoleft_code toggle = true end for i=1,size do @@ -969,15 +896,18 @@ local function insert_dir_points(list,size) if trace_list and n > 1 then report_directions("unbalanced list") end - last.enddir = stack[n] == "+TRT" and "-TRT" or "-TLT" + last.enddir = stack[n] end end end +-- We flag nodes that can be skipped when we see them again but because whatever +-- mechanism can injetc dir nodes that then are not flagged, we don't flag dir +-- nodes that we inject here. + local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false if trace_list then report_directions("start run") end @@ -990,7 +920,12 @@ local function apply_to_list(list,size,head,pardir) local entry = list[index] local begindir = entry.begindir local enddir = entry.enddir - local p = properties[current] if p then p.directions = true else properties[current] = { directions = true } end + local p = properties[current] + if p then + p.directions = true + else + properties[current] = { directions = true } + end if id == glyph_code then local mirror = entry.mirror if mirror then @@ -1011,55 +946,43 @@ local function apply_to_list(list,size,head,pardir) setcolor(current,direction,false,mirror) end elseif id == hlist_code or id == vlist_code then - setdir(current,pardir) -- is this really needed? + setdirection(current,pardir) -- is this really needed? elseif id == glue_code then if enddir and getsubtype(current) == parfillskip_code then -- insert the last enddir before \parfillskip glue - local d = new_textdir(enddir) - local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end - -- setattrlist(d,current) - head = insert_node_before(head,current,d) + head = insert_node_before(head,current,new_direction(enddir,true)) enddir = false - done = true end elseif begindir then - if id == localpar_code then + if id == localpar_code and getsubtype(current) == 0 then -- localpar should always be the 1st node - local d = new_textdir(begindir) - local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end - -- setattrlist(d,current) - head, current = insert_node_after(head,current,d) + head, current = insert_node_after(head,current,new_direction(begindir)) begindir = nil - done = true end end if begindir then - local d = new_textdir(begindir) - local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end - -- setattrlist(d,current) - head = insert_node_before(head,current,d) - done = true + head = insert_node_before(head,current,new_direction(begindir)) end local skip = entry.skip if skip and skip > 0 then for i=1,skip do current = getnext(current) - local p = properties[current] if p then p.directions = true else properties[current] = { directions = true } end + local p = properties[current] + if p then + p.directions = true + else + properties[current] = { directions = true } + end end end if enddir then - local d = new_textdir(enddir) - local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end - -- setattrlist(d,current) - head, current = insert_node_after(head,current,d) - done = true + head, current = insert_node_after(head,current,new_direction(enddir,true)) end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end @@ -1068,7 +991,7 @@ local function apply_to_list(list,size,head,pardir) if trace_list then report_directions("stop run") end - return head, done + return head end -- If needed we can optimize for only_one. There is no need to do anything @@ -1077,16 +1000,15 @@ end -- have more than one node. Actually, we only enter this function when we -- do have a glyph! -local function process(head,direction,only_one) - head = tonut(head) +local function process(head,direction,only_one,where) -- for the moment a whole paragraph property local attr = getattr(head,a_directions) local analyze_fences = getfences(attr) -- - local list, size = build_list(head) - local baselevel, pardir, dirfound = get_baselevel(head,list,size,direction) -- we always have an inline dir node in context + local list, size = build_list(head,where) + local baselevel, dirfound = get_baselevel(head,list,size,direction) if trace_details then - report_directions("analyze: direction %a, baselevel %a",dirfound and pardir or "unknown",baselevel or 1) + report_directions("analyze: baselevel %a",baselevel == righttoleft_code and "r2l" or "l2r") report_directions("before : %s",show_list(list,size,"original")) end resolve_explicit(list,size,baselevel) @@ -1096,8 +1018,12 @@ local function process(head,direction,only_one) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,baselevel) end -directions.installhandler(interfaces.variables.three,process) +local variables = interfaces.variables + +directions.installhandler(variables.one, process) -- for old times sake +directions.installhandler(variables.two, process) -- for old times sake +directions.installhandler(variables.three, process) -- for old times sake +directions.installhandler(variables.unicode,process) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-fkr.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-fkr.lua index a1135d0f321..1fd08526c3a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-fkr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-fkr.lua @@ -7,12 +7,10 @@ if not modules then modules = { } end modules ['typo-fkr'] = { } local nuts = nodes.nuts -local tonut = nuts.tonut local getid = nuts.getid local getnext = nuts.getnext -local getchar = nuts.getchar -local getfont = nuts.getfont local getattr = nuts.getattr +local isglyph = nuts.isglyph local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph @@ -32,20 +30,15 @@ local a_extrakern = attributes.private("extrafontkern") typesetters.fontkerns = { } function typesetters.fontkerns.handler(head) - local kepthead = head - local head = tonut(head) local current = head local lastfont = nil local lastchar = nil local lastdata = nil - local done = false while current do - local id = getid(current) - if id == glyph_code then + local char, font = isglyph(current) + if char then local a = getattr(current,a_extrakern) if a then - local char = getchar(current) - local font = getfont(current) if font ~= lastfont then if a > 0 and lastchar then if not lastdata then @@ -64,7 +57,6 @@ function typesetters.fontkerns.handler(head) end if kern ~= 0 then head, current = insert_before(head,current,new_kern(kern)) - done = true end lastdata = data else @@ -77,7 +69,6 @@ function typesetters.fontkerns.handler(head) local kern = getkernpair(lastdata,lastchar,char) if kern ~= 0 then head, current = insert_before(head,current,new_kern(kern)) - done = true end end lastchar = char @@ -94,7 +85,7 @@ function typesetters.fontkerns.handler(head) end current = getnext(current) end - return kepthead, done + return head end if context then diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua index 4fb82ce4499..0489807327c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.lua @@ -30,7 +30,6 @@ local context = context local implement = interfaces.implement local nuts = nodes.nuts -local tonut = nuts.tonut local tonode = nuts.tonode local getnext = nuts.getnext @@ -38,7 +37,6 @@ local getprev = nuts.getprev local getboth = nuts.getboth local setboth = nuts.setboth local getid = nuts.getid -local getsubtype = nuts.getsubtype local getwidth = nuts.getwidth local getlist = nuts.getlist local setlist = nuts.setlist @@ -58,14 +56,16 @@ local glue_code = nodecodes.glue local spaceskip_code = nodes.gluecodes.spaceskip -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph +local nextdisc = nuts.traversers.disc + local flush_node_list = nuts.flush_list local flush_node = nuts.flush_node local copy_node_list = nuts.copy_list local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local remove_node = nuts.remove -local list_dimensions = nuts.dimensions +local getdimensions = nuts.dimensions local hpack_node_list = nuts.hpack local nodepool = nuts.pool @@ -136,7 +136,7 @@ actions[v_line] = function(head,setting) local linebreaks = { } local function set(head) - for g in traverse_id(glyph_code,head) do + for g in nextglyph, head do if dynamic > 0 then setattr(g,0,dynamic) end @@ -146,7 +146,7 @@ actions[v_line] = function(head,setting) set(temp) - for g in traverse_id(disc_code,temp) do + for g in nextdisc, temp do local pre, post, replace = getdisc(g) if pre then set(pre) @@ -173,17 +173,13 @@ actions[v_line] = function(head,setting) local function list_dimensions(list,start) local temp = copy_node_list(list,start) - temp = tonode(temp) temp = nodes.handlers.characters(temp) temp = nodes.injections.handler(temp) -- temp = typesetters.fontkerns.handler(temp) -- maybe when enabled - -- nodes.handlers.protectglyphs(temp) -- not needed as we discard + -- nodes.handlers.protectglyphs(temp) -- not needed as we discard -- temp = typesetters.spacings.handler(temp) -- maybe when enabled -- temp = typesetters.kerns.handler(temp) -- maybe when enabled - temp = tonut(temp) - temp = hpack_node_list(temp) - local width = getwidth(temp) - flush_node_list(temp) + local width = getdimensions(temp) return width end @@ -206,7 +202,7 @@ actions[v_line] = function(head,setting) while start do local id = getid(start) if id == glyph_code then - n = n + 1 + -- go on elseif id == disc_code then -- this could be an option n = n + 1 @@ -218,7 +214,8 @@ actions[v_line] = function(head,setting) end elseif id == kern_code then -- todo: fontkern -- this could be an option - elseif n > 0 then + elseif id == glue_code then + n = n + 1 if try() then break end @@ -255,7 +252,6 @@ actions[v_line] = function(head,setting) local id = getid(start) local ok = false if id == glyph_code then - n = n + 1 update(start) elseif id == disc_code then n = n + 1 @@ -264,7 +260,7 @@ actions[v_line] = function(head,setting) if linebreak == n then local p, n = getboth(start) if pre then - for current in traverse_id(glyph_code,pre) do + for current in nextglyph, pre do update(current) end setlink(pretail,n) @@ -284,7 +280,7 @@ actions[v_line] = function(head,setting) else local p, n = getboth(start) if replace then - for current in traverse_id(glyph_code,replace) do + for current in nextglyph, replace do update(current) end setlink(replacetail,n) @@ -299,22 +295,30 @@ actions[v_line] = function(head,setting) setdisc(disc,pre,post,replace) flush_node(disc) elseif id == glue_code then - head = insert_node_before(head,start,newpenalty(10000)) -- nobreak + n = n + 1 + if linebreak ~= n then + head = insert_node_before(head,start,newpenalty(10000)) -- nobreak + end end + local next = getnext(start) if linebreak == n then - if trace_firstlines then - head, start = insert_node_after(head,start,newpenalty(10000)) -- nobreak - head, start = insert_node_after(head,start,newkern(-65536)) - head, start = insert_node_after(head,start,tracerrule(65536,4*65536,2*65536,"darkblue")) + if start ~= head then + local where = id == glue_code and getprev(start) or start + if trace_firstlines then + head, where = insert_node_after(head,where,newpenalty(10000)) -- nobreak + head, where = insert_node_after(head,where,newkern(-65536)) + head, where = insert_node_after(head,where,tracerrule(65536,4*65536,2*65536,"darkblue")) + end + head, where = insert_node_after(head,where,newpenalty(-10000)) -- break end - head, start = insert_node_after(head,start,newpenalty(-10000)) -- break + start = next break end - start = getnext(start) + start = next end end - return head, true + return head end actions[v_word] = function(head,setting) @@ -359,13 +363,12 @@ actions[v_word] = function(head,setting) end start = getnext(start) end - return head, true + return head end actions[v_default] = actions[v_line] function firstlines.handler(head) - head = tonut(head) local start = head local attr = nil while start do @@ -388,11 +391,10 @@ function firstlines.handler(head) if trace_firstlines then report_firstlines("processing firstlines, alternative %a",alternative) end - local head, done = action(head,settings) - return tonode(head), done + return action(head,settings) end end - return tonode(head), false + return head end -- goodie @@ -401,7 +403,7 @@ local function applytofirstcharacter(box,what) local tbox = getbox(box) -- assumes hlist local list = getlist(tbox) local done = nil - for n in traverse_id(glyph_code,list) do + for n in nextglyph, list do list = remove_node(list,n) done = n break diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv index 37348be2940..533c197cd10 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-fln.mkiv @@ -91,7 +91,7 @@ \kern\zeropoint % we need a node % \hskip\zeropoint\s!plus\emwidth\relax % can be an option \endgroup - \globallet\typo_firstline_handle\relax} + \glet\typo_firstline_handle\relax} \let\typo_firstline_handle\relax diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua index 328bf14067e..2683eecc3e1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-itc.lua @@ -29,13 +29,9 @@ local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts local nodepool = nuts.pool -local tonode = nuts.tonode -local tonut = nuts.tonut - local getprev = nuts.getprev local getnext = nuts.getnext local getid = nuts.getid -local getfont = nuts.getfont local getchar = nuts.getchar local getdisc = nuts.getdisc local getattr = nuts.getattr @@ -128,14 +124,22 @@ local function okay(data,current,font,prevchar,previtalic,char,what) return false end if threshold then - local ht = getheight(current) - local ex = exheights[font] - local th = threshold * ex - if ht <= th then - if trace_italics then - report_italics("ignoring correction between %s italic %C and regular %C, height %p less than threshold %p",prevchar,what,char,ht,th) + -- if getid(current) == glyph_code then + while current and getid(current) ~= glyph_code do + current = getprev(current) + end + if current then + local ht = getheight(current) + local ex = exheights[font] + local th = threshold * ex + if ht <= th then + if trace_italics then + report_italics("ignoring correction between %s italic %C and regular %C, height %p less than threshold %p",prevchar,what,char,ht,th) + end + return false end - return false + else + -- maybe backtrack to glyph end end if trace_italics then @@ -177,7 +181,7 @@ local textokay = false local enablemath = false local enabletext = false -local function domath(head,current, done) +local function domath(head,current) current = end_of_math(current) local next = getnext(current) if next then @@ -200,8 +204,7 @@ local function domath(head,current, done) a = a + 100 end local i = getkern(kern) - local f = getfont(glyph) - local c = getchar(glyph) + local c, f = isglyph(glyph) if getheight(next) < 1.25*exheights[f] then if i == 0 then if trace_italics then @@ -212,7 +215,6 @@ local function domath(head,current, done) report_italics("%s italic between math %C and punctuation %C","removing",i,c,char) end setkern(kern,0) -- or maybe a small value or half the ic - done = true end elseif i == 0 then local d = chardata[f][c] @@ -226,7 +228,6 @@ local function domath(head,current, done) if trace_italics then report_italics("%s italic %p between math %C and punctuation %C","setting",i,c,char) end - done = true end elseif trace_italics then report_italics("%s italic %p between math %C and punctuation %C","keeping",k,c,char) @@ -251,34 +252,31 @@ local function domath(head,current, done) report_italics("%s italic %p between math %C and non punctuation %C","adding",a,getchar(glyph),char) end insert_node_after(head,glyph,correction_kern(a,glyph)) - done = true end end end end end end - return current, done + return current end local function mathhandler(head) - local nuthead = tonut(head) - local current = nuthead - local done = false + local current = head while current do if getid(current) == math_code then - current, done = domath(nuthead,current,done) + current = domath(head,current) end current = getnext(current) end - return head, done + return head end local function texthandler(head) local prev = nil local prevchar = nil - local prevhead = tonut(head) + local prevhead = head local previtalic = 0 local previnserted = nil @@ -300,20 +298,18 @@ local function texthandler(head) local replaceinserted = nil local current = prevhead - local done = false local lastfont = nil local lastattr = nil while current do local char, id = isglyph(current) if char then - local font = getfont(current) + local font = id local data = italicsdata[font] if font ~= lastfont then if previtalic ~= 0 then if okay(data,current,font,prevchar,previtalic,char,"glyph") then insert_node_after(prevhead,prev,correction_kern(previtalic,current)) - done = true end elseif previnserted and data then if trace_italics then @@ -325,7 +321,6 @@ local function texthandler(head) if replaceitalic ~= 0 then if okay(data,replace,font,replacechar,replaceitalic,char,"replace") then insert_node_after(replacehead,replace,correction_kern(replaceitalic,current)) - done = true end replaceitalic = 0 elseif replaceinserted and data then @@ -338,7 +333,6 @@ local function texthandler(head) if postitalic ~= 0 then if okay(data,post,font,postchar,postitalic,char,"post") then insert_node_after(posthead,post,correction_kern(postitalic,current)) - done = true end postitalic = 0 elseif postinserted and data then @@ -395,7 +389,7 @@ local function texthandler(head) while current do local char, id = isglyph(current) if char then - local font = getfont(current) + local font = id local data = italicsdata[font] if data then local attr = forcedvariant or getattr(current,a_italics) @@ -431,7 +425,7 @@ local function texthandler(head) while current do local char, id = isglyph(current) if char then - local font = getfont(current) + local font = id local data = italicsdata[font] if data then local attr = forcedvariant or getattr(current,a_italics) @@ -479,7 +473,6 @@ local function texthandler(head) end previnserted = correction_glue(previtalic,current) -- maybe just add ? else problem with penalties previtalic = 0 - done = true insert_node_after(prevhead,prev,previnserted) else if replaceitalic ~= 0 then @@ -488,7 +481,6 @@ local function texthandler(head) end replaceinserted = correction_kern(replaceitalic,current) -- needs to be a kern replaceitalic = 0 - done = true insert_node_after(replacehead,replace,replaceinserted) end if postitalic ~= 0 then @@ -497,7 +489,6 @@ local function texthandler(head) end postinserted = correction_kern(postitalic,current) -- needs to be a kern postitalic = 0 - done = true insert_node_after(posthead,post,postinserted) end end @@ -510,7 +501,7 @@ local function texthandler(head) postinserted = nil postitalic = 0 if mathokay then - current, done = domath(head,current,done) + current = domath(head,current) else current = end_of_math(current) end @@ -526,7 +517,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true else if replaceitalic ~= 0 then if trace_italics then @@ -539,7 +529,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true end if postitalic ~= 0 then if trace_italics then @@ -552,7 +541,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true end end end @@ -564,25 +552,22 @@ local function texthandler(head) report_italics("inserting %p between %s italic %C and end of list",previtalic,"glyph",prevchar) end insert_node_after(prevhead,prev,correction_kern(previtalic,current)) - done = true else if replaceitalic ~= 0 then if trace_italics then report_italics("inserting %p between %s italic %C and end of list",replaceitalic,"replace",replacechar) end insert_node_after(replacehead,replace,correction_kern(replaceitalic,current)) - done = true end if postitalic ~= 0 then if trace_italics then report_italics("inserting %p between %s italic %C and end of list",postitalic,"post",postchar) end insert_node_after(posthead,post,correction_kern(postitalic,current)) - done = true end end end - return head, done + return head end function italics.handler(head) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua index 71d9736a44b..c26004a49df 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-krn.lua @@ -21,9 +21,6 @@ local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts local nodepool = nuts.pool -local tonode = nuts.tonode -local tonut = nuts.tonut - -- check what is used local find_node_tail = nuts.tail @@ -32,6 +29,7 @@ local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local end_of_math = nuts.end_of_math local use_components = nuts.use_components +local copy_node = nuts.copy local getnext = nuts.getnext local getprev = nuts.getprev @@ -43,10 +41,12 @@ local getdisc = nuts.getdisc local getglue = nuts.getglue local getkern = nuts.getkern local isglyph = nuts.isglyph +local setchar = nuts.setchar local setfield = nuts.setfield local getattr = nuts.getattr local takeattr = nuts.takeattr +local setattr = nuts.setattr local setlink = nuts.setlink local setdisc = nuts.setdisc local setglue = nuts.setglue @@ -62,7 +62,7 @@ local new_glue = nodepool.glue local nodecodes = nodes.nodecodes local kerncodes = nodes.kerncodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes local disccodes = nodes.disccodes local listcodes = nodes.listcodes @@ -74,17 +74,18 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local math_code = nodecodes.math -local box_list_code = listcodes.box -local user_list_code = listcodes.unknown +local boxlist_code = listcodes.box +local unknownlist_code = listcodes.unknown -local discretionary_code = disccodes.discretionary -local automatic_code = disccodes.automatic +local discretionarydisc_code = disccodes.discretionary +local automaticdisc_code = disccodes.automatic local fontkern_code = kerncodes.fontkern local userkern_code = kerncodes.userkern -local userskip_code = skipcodes.userskip -local spaceskip_code = skipcodes.spaceskip -local xspaceskip_code = skipcodes.xspaceskip + +local userskip_code = gluecodes.userskip +local spaceskip_code = gluecodes.spaceskip +local xspaceskip_code = gluecodes.xspaceskip local fonthashes = fonts.hashes local chardata = fonthashes.characters @@ -132,9 +133,6 @@ local factors = kerns.factors local gluefactor = 4 -- assumes quad = .5 enspace -kerns.keepligature = false -- just for fun (todo: control setting with key/value) -kerns.keeptogether = false -- just for fun (todo: control setting with key/value) - -- red : kept by dynamic feature -- green : kept by static feature -- blue : keep by goodie @@ -257,7 +255,7 @@ end local function inject_end(boundary,next,keeptogether,krn,ok) local tail = find_node_tail(boundary) - local char, id = getid(tail) + local char, id = isglyph(tail) if id == kern_code then if getsubtype(tail) == fontkern_code then local inject = true @@ -301,7 +299,7 @@ local function process_list(head,keeptogether,krn,font,okay) local char, id = isglyph(start) if char then if not font then - font = getfont(start) + font = id -- getfont(start) mark = markdata[font] kern = quaddata[font]*krn end @@ -354,19 +352,223 @@ local function closest_bound(b,get) while b do if not getattr(b,a_kerns) then break - elseif getid(b) == glyph_code then - return b, getfont(b) else - b = get(b) + local c, f = isglyph(b) + if c then + return b, f + else + b = get(b) + end end end end end +-- function kerns.handler(head) +-- local start = head +-- local lastfont = nil +-- local keepligature = kerns.keepligature +-- local keeptogether = kerns.keeptogether +-- local fillup = false +-- local bound = false +-- local prev = nil +-- local previd = nil +-- local prevchar = nil +-- local prevfont = nil +-- local prevmark = nil +-- while start do +-- -- fontkerns don't get the attribute but they always sit between glyphs so +-- -- are always valid bound .. disc nodes also somtimes don't get them +-- local id = getid(start) +-- local attr = takeattr(start,a_kerns) +-- if attr and attr > 0 then +-- local krn = mapping[attr] +-- if krn == v_max then +-- krn = .25 +-- fillup = true +-- else +-- fillup = false +-- end +-- if not krn or krn == 0 then +-- bound = false +-- elseif id == glyph_code then +-- if keepligature and keepligature(start) then +-- -- keep 'm +-- else +-- -- we could use the subtype ligature but that's also a call +-- -- todo: check tounicode and use that information to split +-- head, start = use_components(head,start) +-- end +-- local char, font = isglyph(start) +-- local mark = markdata[font] +-- if not bound then +-- -- yet +-- elseif mark[char] then +-- -- skip +-- elseif previd == kern_code then +-- if getsubtype(prev) == fontkern_code then +-- local inject = true +-- if keeptogether then +-- if previd == glyph_code and keeptogether(prev,start) then +-- inject = false +-- end +-- end +-- if inject then +-- -- not yet ok, as injected kerns can be overlays (from node-inj.lua) +-- setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code) +-- end +-- end +-- elseif previd == glyph_code then +-- if prevfont == font then +-- if keeptogether and keeptogether(prev,start) then +-- -- keep 'm +-- else +-- local data = chardata[font][prevchar] +-- local kerns = data and data.kerns +-- local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn +-- insert_node_before(head,start,kern_injector(fillup,kern)) +-- end +-- else +-- insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn)) +-- end +-- end +-- prev = start +-- prevchar = char +-- prevfont = font +-- prevmark = mark +-- previd = id +-- bound = true +-- elseif id == disc_code then +-- local prev, next, pglyph, nglyph -- delayed till needed +-- local subtype = getsubtype(start) +-- -- if subtype == automaticdisc_code then +-- -- -- this is kind of special, as we have already injected the +-- -- -- previous kern +-- -- local prev = getprev(start) +-- -- local pglyph = prev and getid(prev) == glyph_code +-- -- languages.expand(start,pglyph and prev) +-- -- -- we can have a different start now +-- -- elseif subtype ~= discretionarydisc_code then +-- -- prev = getprev(start) +-- -- pglyph = prev and getid(prev) == glyph_code +-- -- languages.expand(start,pglyph and prev) +-- -- end +-- local pre, post, replace = getdisc(start) +-- local indeed = false +-- if pre then +-- local okay = false +-- if not prev then +-- prev = getprev(start) +-- pglyph = prev and getid(prev) == glyph_code +-- end +-- if pglyph then +-- pre, okay = inject_begin(pre,prev,keeptogether,krn,okay) +-- end +-- pre, okay = process_list(pre,keeptogether,krn,false,okay) +-- if okay then +-- indeed = true +-- end +-- end +-- if post then +-- local okay = false +-- if not next then +-- next = getnext(start) +-- nglyph = next and getid(next) == glyph_code +-- end +-- if nglyph then +-- post, okay = inject_end(post,next,keeptogether,krn,okay) +-- end +-- post, okay = process_list(post,keeptogether,krn,false,okay) +-- if okay then +-- indeed = true +-- end +-- end +-- if replace then +-- local okay = false +-- if not prev then +-- prev = getprev(start) +-- pglyph = prev and getid(prev) == glyph_code +-- end +-- if pglyph then +-- replace, okay = inject_begin(replace,prev,keeptogether,krn,okay) +-- end +-- if not next then +-- next = getnext(start) +-- nglyph = next and getid(next) == glyph_code +-- end +-- if nglyph then +-- replace, okay = inject_end(replace,next,keeptogether,krn,okay) +-- end +-- replace, okay = process_list(replace,keeptogether,krn,false,okay) +-- if okay then +-- indeed = true +-- end +-- elseif prevfont then +-- replace = new_kern(quaddata[prevfont]*krn) +-- indeed = true +-- end +-- if indeed then +-- setdisc(start,pre,post,replace) +-- end +-- bound = false +-- elseif id == kern_code then +-- bound = getsubtype(start) == fontkern_code +-- prev = start +-- previd = id +-- elseif id == glue_code then +-- local subtype = getsubtype(start) +-- if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then +-- local width, stretch, shrink, stretch_order, shrink_order = getglue(start) +-- if width > 0 then +-- local w = width + gluefactor * width * krn +-- stretch = stretch * w / width +-- shrink = shrink * w / width +-- if fillup then +-- stretch = 2 * stretch +-- shrink = 2 * shrink +-- stretch_order = 1 +-- -- shrink_order = 1 ? +-- end +-- setglue(start,w,stretch,shrink,stretch_order,shrink_order) +-- end +-- end +-- bound = false +-- elseif id == hlist_code or id == vlist_code then +-- local subtype = getsubtype(start) +-- if subtype == unknownlist_code or subtype == boxlist_code then +-- -- special case +-- local b, f = closest_bound(start,getprev) +-- if b then +-- insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn)) +-- end +-- local b, f = closest_bound(start,getnext) +-- if b then +-- insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn)) +-- end +-- end +-- bound = false +-- elseif id == math_code then +-- start = end_of_math(start) +-- bound = false +-- end +-- if start then +-- start = getnext(start) +-- end +-- elseif id == kern_code then +-- bound = getsubtype(start) == fontkern_code +-- prev = start +-- previd = id +-- start = getnext(start) +-- else +-- bound = false +-- start = getnext(start) +-- end +-- end +-- return head +-- end + function kerns.handler(head) - local head = tonut(head) local start = head - local done = false local lastfont = nil local keepligature = kerns.keepligature local keeptogether = kerns.keeptogether @@ -379,10 +581,10 @@ function kerns.handler(head) local prevmark = nil while start do -- fontkerns don't get the attribute but they always sit between glyphs so - -- are always valid bound .. disc nodes also somtimes don't get them - local id = getid(start) + -- are always valid bound .. disc nodes also sometimes don't get them local attr = takeattr(start,a_kerns) if attr and attr > 0 then + local char, id = isglyph(start) local krn = mapping[attr] if krn == v_max then krn = .25 @@ -392,17 +594,34 @@ function kerns.handler(head) end if not krn or krn == 0 then bound = false - elseif id == glyph_code then + elseif char then -- id == glyph_code + local font = id -- more readable + local mark = markdata[font] if keepligature and keepligature(start) then -- keep 'm else - -- we could use the subtype ligature but that's also a call - -- todo: check tounicode and use that information to split - head, start = use_components(head,start) + -- head, start = use_components(head,start) + -- beware, these are not kerned so we mighty need a kern only pass + -- maybe some day .. anyway, one should disable ligaturing + local data = chardata[font][char] + if data then + local unicode = data.unicode -- can be cached + if type(unicode) == "table" then + char = unicode[1] + local s = start + setchar(s,char) + for i=2,#unicode do + local n = copy_node(s) + if i == 2 then + setattr(n,a_kerns,attr) -- we took away the attr + end + setchar(n,unicode[i]) + insert_node_after(head,s,n) + s = n + end + end + end end - local char = getchar(start) - local font = getfont(start) - local mark = markdata[font] if not bound then -- yet elseif mark[char] then @@ -418,7 +637,6 @@ function kerns.handler(head) if inject then -- not yet ok, as injected kerns can be overlays (from node-inj.lua) setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code) - done = true end end elseif previd == glyph_code then @@ -426,34 +644,33 @@ function kerns.handler(head) if keeptogether and keeptogether(prev,start) then -- keep 'm else + -- hm, only basemode ... will go away ... local data = chardata[font][prevchar] local kerns = data and data.kerns local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn insert_node_before(head,start,kern_injector(fillup,kern)) - done = true end else insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn)) - done = true end end prev = start prevchar = char prevfont = font prevmark = mark - previd = id + previd = glyph_code -- id bound = true elseif id == disc_code then local prev, next, pglyph, nglyph -- delayed till needed local subtype = getsubtype(start) - -- if subtype == automatic_code then + -- if subtype == automaticdisc_code then -- -- this is kind of special, as we have already injected the -- -- previous kern -- local prev = getprev(start) -- local pglyph = prev and getid(prev) == glyph_code -- languages.expand(start,pglyph and prev) -- -- we can have a different start now - -- elseif subtype ~= discretionary_code then + -- elseif subtype ~= discretionarydisc_code then -- prev = getprev(start) -- pglyph = prev and getid(prev) == glyph_code -- languages.expand(start,pglyph and prev) @@ -514,7 +731,6 @@ function kerns.handler(head) end if indeed then setdisc(start,pre,post,replace) - done = true end bound = false elseif id == kern_code then @@ -536,23 +752,20 @@ function kerns.handler(head) -- shrink_order = 1 ? end setglue(start,w,stretch,shrink,stretch_order,shrink_order) - done = true end end bound = false elseif id == hlist_code or id == vlist_code then local subtype = getsubtype(start) - if subtype == user_list_code or subtype == box_list_code then + if subtype == unknownlist_code or subtype == boxlist_code then -- special case local b, f = closest_bound(start,getprev) if b then insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn)) - done = true end local b, f = closest_bound(start,getnext) if b then insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn)) - done = true end end bound = false @@ -563,17 +776,20 @@ function kerns.handler(head) if start then start = getnext(start) end - elseif id == kern_code then - bound = getsubtype(start) == fontkern_code - prev = start - previd = id - start = getnext(start) else - bound = false - start = getnext(start) + local id = getid(start) + if id == kern_code then + bound = getsubtype(start) == fontkern_code + prev = start + previd = id + start = getnext(start) + else + bound = false + start = getnext(start) + end end end - return tonode(head), done + return head end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua index ebf748a8294..8393ea65b34 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-lin.lua @@ -64,7 +64,7 @@ local listcodes = nodes.listcodes local hlist_code = nodecodes.hlist local glue_code = nodecodes.glue local kern_code = nodecodes.kern -local line_code = listcodes.line +local linelist_code = listcodes.line ----- localpar_code = nodecodes.localpar local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip @@ -73,7 +73,7 @@ local parfillskip_code = gluecodes.parfillskip local tonut = nodes.tonut local tonode = nodes.tonode -local traverse_id = nuts.traverse_id +local nexthlist = nuts.traversers.hlist local insert_before = nuts.insert_before local insert_after = nuts.insert_after local find_tail = nuts.tail @@ -90,7 +90,7 @@ local getboth = nuts.getboth local setlink = nuts.setlink local setkern = nuts.setkern local getkern = nuts.getkern -local getdir = nuts.getdir +local getdirection = nuts.getdirection local getshift = nuts.getshift local setshift = nuts.setshift local getwidth = nuts.getwidth @@ -109,6 +109,8 @@ local new_hlist = nodepool.hlist local new_rule = nodepool.rule local new_glue = nodepool.glue +local righttoleft_code = nodes.dirvalues.righttoleft + local texgetcount = tex.getcount local texgetglue = tex.getglue local setmetatableindex = table.setmetatableindex @@ -127,22 +129,12 @@ local noflines = 0 -- This is the third version, a mix between immediate (prestice lines) and delayed -- as we don't want anchors that are not used. --- if reverse then delta = - delta end --- head = insert_before(head,head,nodepool.textdir("-TLT")) --- .... --- head = insert_before(head,head,nodepool.textdir("TLT")) - --- todo: figure out metatable mess ... when we copy we also need to copy --- anchors ... use rawgets - --- problem: what if a box is copied ... we could check an attribute - local function finalize(prop,key) -- delayed calculations local line = prop.line local hsize = prop.hsize local width = prop.width local shift = getshift(line) -- dangerous as it can be vertical as well - local reverse = getdir(line) == "TRT" or false + local reverse = getdirection(line) == righttoleft_code or false local pack = new_hlist() local head = getlist(line) local delta = 0 @@ -248,49 +240,47 @@ function paragraphs.normalize(head,islocal) return head, false end -- this can become a separate handler but it makes sense to integrate it here - local l_width, l_stretch, l_shrink = texgetglue("parfillleftskip") - if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then - local last = nil -- a nut - local done = false - for line in traverse_id(hlist_code,tonut(head)) do - if getsubtype(line) == line_code and not getprop(line,"line") then - if done then - last = line - else - done = true + local mode = texgetcount("parfillleftmode") + if mode > 0 then + local l_width, l_stretch, l_shrink = texgetglue("parfillleftskip") + if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then + local last = nil -- a nut + local done = mode == 2 -- false + for line, subtype in nexthlist, head do + if subtype == linelist_code and not getprop(line,"line") then + if done then + last = line + else + done = true + end end end - end - if last then -- only if we have more than one line - local head = getlist(last) - local current = head - if current then - if getid(current) == glue_code and getsubtype(current,leftskip_code) then - current = getnext(current) - end + if last then -- only if we have more than one line + local head = getlist(last) + local current = head if current then - head, current = insert_before(head,current,new_glue(l_width,l_stretch,l_shrink)) - if head == current then - setlist(last,head) + if getid(current) == glue_code and getsubtype(current,leftskip_code) then + current = getnext(current) + end + if current then + head, current = insert_before(head,current,new_glue(l_width,l_stretch,l_shrink)) + if head == current then + setlist(last,head) + end + -- can be a 'rehpack(h )' + rehpack(last) end - -- can be a 'rehpack(h )' - rehpack(last) end end end end -- normalizer - for line in traverse_id(hlist_code,tonut(head)) do - if getsubtype(line) == line_code and not getprop(line,"line") then + for line, subtype in nexthlist, head do + if subtype == linelist_code and not getprop(line,"line") then normalize(line) - if done then - last = line - else - done = true - end end end - return head, true + return head, true -- true is obsolete end -- print(nodes.idstostring(head)) @@ -418,12 +408,17 @@ function paragraphs.moveinline(n,blob,dx,dy) end end -local lateluafunction = nodepool.lateluafunction -local setposition = job.positions.set -local t_anchor = { x = true, c = true } +local latelua = nodepool.latelua +local setposition = jobpositions.setspec +local t_anchor = { x = true, c = true } -- needs checking local function setanchor(h_anchor) - return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end) + return latelua { + action = setposition, + name = "md:h", + index = h_anchor, + value = t_anchor, -- really shared ? + } end function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua index bc9c408c19f..f8665e0b061 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.lua @@ -62,13 +62,11 @@ local nuts = nodes.nuts local nodepool = nuts.pool local tonode = nuts.tonode -local tonut = nuts.tonut local hpack_nodes = nuts.hpack local traverse_id = nuts.traverse_id local flush_node_list = nuts.flush_list -local getfield = nuts.getfield local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid @@ -84,6 +82,9 @@ local setshift = nuts.setshift local getwidth = nuts.getwidth local setwidth = nuts.setwidth local getheight = nuts.getheight +local getprop = nuts.getprop + +local setattrlist = nuts.setattrlist local getbox = nuts.getbox local takebox = nuts.takebox @@ -93,7 +94,6 @@ local getprop = nuts.getprop local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes -local gluecodes = nodes.gluecodes local whatsitcodes = nodes.whatsitcodes local hlist_code = nodecodes.hlist @@ -103,17 +103,17 @@ local userdefined_code = whatsitcodes.userdefined local nodepool = nuts.pool -local new_usernumber = nodepool.usernumber +local new_usernode = nodepool.usernode local new_hlist = nodepool.hlist -local lateluafunction = nodepool.lateluafunction +local latelua = nodepool.latelua local texgetdimen = tex.getdimen local texgetcount = tex.getcount local texget = tex.get local isleftpage = layouts.status.isleftpage -local registertogether = builders.paragraphs.registertogether -- tonode +local registertogether = builders.paragraphs.registertogether local paragraphs = typesetters.paragraphs local addtoline = paragraphs.addtoline @@ -299,7 +299,9 @@ function margins.save(t) -- -- t.realpageno = texgetcount("realpageno") if inline then - context(tonode(new_usernumber(inline_mark,nofsaved))) -- or use a normal node + local n = new_usernode(inline_mark,nofsaved) + setattrlist(n,true) + context(tonode(n)) -- or use a normal node store[nofsaved] = t -- no insert nofinlined = nofinlined + 1 else @@ -448,8 +450,9 @@ end -- anchors are only set for lines that have a note -local function sa(tag) -- maybe l/r keys ipv left/right keys - local p = cache[tag] +local function sa(specification) -- maybe l/r keys ipv left/right keys + local tag = specification.tag + local p = cache[tag] if p then if trace_marginstack then report_margindata("updating anchor %a",tag) @@ -462,11 +465,13 @@ local function sa(tag) -- maybe l/r keys ipv left/right keys end local function setanchor(v_anchor) -- freezes the global here - return lateluafunction(function() sa(v_anchor) end) + return latelua { action = sa, tag = v_anchor } end -local function aa(tag,n) -- maybe l/r keys ipv left/right keys - local p = jobpositions.gettobesaved('md:v',tag) +local function aa(specification) -- maybe l/r keys ipv left/right keys + local tag = specification.tag + local n = specification.n + local p = jobpositions.gettobesaved('md:v',tag) if p then if trace_marginstack then report_margindata("updating injected %a",tag) @@ -483,7 +488,7 @@ local function aa(tag,n) -- maybe l/r keys ipv left/right keys end local function addtoanchor(v_anchor,n) -- freezes the global here - return lateluafunction(function() aa(v_anchor,n) end) + return latelua { action = aa, tag = v_anchor, n = n } end local function markovershoot(current) -- todo: alleen als offset > line @@ -717,8 +722,8 @@ local function flushinline(parent,head) while current and nofinlined > 0 do local id = getid(current) if id == whatsit_code then - if getsubtype(current) == userdefined_code and getfield(current,"user_id") == inline_mark then - local n = getfield(current,"value") + if getsubtype(current) == userdefined_code and getprop(current,"id") == inline_mark then + local n = getprop(current,"data") local candidate = inlinestore[n] if candidate then -- no vpack, as we want to realign inlinestore[n] = nil @@ -812,9 +817,8 @@ local function handler(scope,head,group) if trace_margindata then report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group) end - head = tonut(head) local current = head - local done = false + local done = false -- for tracing only while current do local id = getid(current) if (id == vlist_code or id == hlist_code) and getprop(current,"margindata") == nil then @@ -839,11 +843,9 @@ local function handler(scope,head,group) report_margindata("flushing stage one, nothing done, %s left",nofstored) end end -resetstacked() - return tonode(head), done - else - return head, false + resetstacked() end + return head end local trialtypesetting = context.trialtypesetting @@ -854,7 +856,7 @@ local trialtypesetting = context.trialtypesetting function margins.localhandler(head,group) -- sometimes group is "" which is weird if trialtypesetting() then - return head, false + return head end local inhibit = conditionals.inhibitmargindata @@ -862,15 +864,15 @@ function margins.localhandler(head,group) -- sometimes group is "" which is weir if trace_margingroup then report_margindata("ignored 3, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false - elseif nofstored > 0 then + return head + end + if nofstored > 0 then return handler(v_local,head,group) - else - if trace_margingroup then - report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit) - end - return head, false end + if trace_margingroup then + report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit) + end + return head end function margins.globalhandler(head,group) -- check group @@ -884,7 +886,7 @@ function margins.globalhandler(head,group) -- check group if trace_margingroup then report_margindata("ignored 1, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false + return head elseif group == "hmode_par" then return handler(v_global,head,group) elseif group == "vmode_par" then -- experiment (for alignments) @@ -899,22 +901,20 @@ function margins.globalhandler(head,group) -- check group if trace_margingroup then report_margindata("ignored 2, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false + return head end end local function finalhandler(head) if nofdelayed > 0 then local current = head - local done = false - while current and nofdelayed > 0 do + while current and nofdelayed > 0 do -- traverse_list local id = getid(current) if id == hlist_code then -- only lines? local a = getprop(current,"margindata") if not a then finalhandler(getlist(current)) elseif realigned(current,a) then - done = true if nofdelayed == 0 then return head, true end @@ -924,10 +924,8 @@ local function finalhandler(head) end current = getnext(current) end - return head, done - else - return head, false end + return head end function margins.finalhandler(head) @@ -935,16 +933,12 @@ function margins.finalhandler(head) if trace_margindata then report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed) end - head = tonut(head) - local head, done = finalhandler(head) --- resetstacked(true) -resetstacked(nofdelayed==0) - head = tonode(head) - return head, done + head = finalhandler(head) + resetstacked(nofdelayed==0) else resetstacked() - return head, false end + return head end -- Somehow the vbox builder (in combinations) gets pretty confused and decides to @@ -996,6 +990,7 @@ interfaces.implement { { "align" }, { "option" }, { "line", "integer" }, + { "index", "integer" }, { "stackname" }, { "stack" }, } diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv index f265f173c9b..921f1f230c3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-mar.mkiv @@ -155,6 +155,7 @@ \forgetall \tf \resetallattributes % \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor + \pickupattributes \to \everymargindatacontent % trialtypesetting: no need for margin stuff while trialing as @@ -200,11 +201,17 @@ \let\margindatahbox\naturalhbox % \hbox +\newcount\c_typo_margins_n + +\ifdefined\dotagmarginanchor \else \let\dotagmarginanchor\gobbleoneargument \fi +\ifdefined\dotagmargintext \else \let\dotagmargintext \gobbleoneargument \fi + \unexpanded\def\typo_margins_data_yes_indeed[#dataparameters][#textparameters]#content% {\iffirstargument \setupcurrentmargindata[#dataparameters]% \fi \doifelsenothing{#content}\donefalse\donetrue + \global\advance\c_typo_margins_n\plusone \ifdone \edef\currentmarginreference{\margindataparameter\c!reference}% \ifx\currentmarginreference\empty \else @@ -212,6 +219,7 @@ \fi \edef\currentmargindatastrut{\margindataparameter\c!strut}% \dostarttaggedchained\t!margintext\currentmargindata\??margindata + \dotagmargintext\c_typo_margins_n \ifcsname\currentmarginframedhash\s!parent\endcsname \setbox\nextbox\margindatahbox \currentmarginreference \bgroup \the\everymargindatacontent @@ -271,6 +279,8 @@ \ifdone \edef\p_anchor{\margindataparameter\c!anchor}% \anch_positions_initialize % we use positions at the lua end + \dostarttagged\t!marginanchor\empty + \dotagmarginanchor\c_typo_margins_n \clf_savemargindata location {\margindataparameter\c!location}% method {\margindataparameter\c!method}% @@ -306,7 +316,9 @@ line \numexpr\margindataparameter\c!line\relax stackname {\margindataparameter\c!stackname}% stack {\margindataparameter\c!stack}% + index \c_typo_margins_n \relax + \dostoptagged \else \clf_savemargindata location {\margindataparameter\c!location}% diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua index b5759a097f7..05513e20c39 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-pag.lua @@ -26,7 +26,6 @@ local unsetvalue = attributes.unsetvalue local a_keeptogether = attributes.private("keeptogether") local nuts = nodes.nuts -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -187,8 +186,8 @@ end -- also look at first non glue/kern node e.g for a dropped caps function parbuilders.keeptogether(head) - local done = false - local current = tonut(head) + local done = false + local current = head while current do if getid(current) == hlist_code then local a = takeattr(current,a_keeptogether) diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv index 3db0ffa45a7..066dc6a6973 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-par.mkiv @@ -23,7 +23,7 @@ \unprotect -\registerctxluafile{node-ltp}{} +\registerctxluafile{node-ltp}{optimize} \registerctxluafile{trac-par}{} \protect \endinput diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-pnc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-pnc.lua index 1ed8d9940af..732970884f2 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-pnc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-pnc.lua @@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['typo-pnc'] = { local nodes = nodes local fonts = fonts -local prependaction = nodes.tasks.prependaction local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts @@ -23,7 +22,8 @@ local spaceskip_code = gluecodes.spaceskip local new_kern = nuts.pool.kern local insert_after = nuts.insert_after -local traverse_id = nuts.traverse_id + +local nextglyph = nuts.traversers.glyph local getchar = nuts.getchar local getfont = nuts.getfont @@ -68,10 +68,8 @@ local mapping = periodkerns.mapping local factors = periodkerns.factors function periodkerns.handler(head) - local done = false - local hnut = tonut(head) - for current in traverse_id(glyph_code,tonut(hnut)) do - if getchar(current) == period then + for current, char, font in nextglyph, head do + if char == period then local a = getattr(current,a_periodkern) if a then local factor = mapping[a] @@ -79,10 +77,10 @@ function periodkerns.handler(head) local prev, next = getboth(current) if prev and next and getid(prev) == glyph_code and getid(next) == glyph_code then local pchar = getchar(prev) - local pcode = categories[getchar(prev)] + local pcode = categories[pchar] if pcode == "lu" or pcode == "ll" then local nchar = getchar(next) - local ncode = categories[getchar(next)] + local ncode = categories[nchar] if ncode == "lu" or ncode == "ll" then local next2 = getnext(next) if next2 and getid(next2) == glyph_code and getchar(next2) == period then @@ -91,11 +89,10 @@ function periodkerns.handler(head) if factor ~= 0 then fontspace = parameters[getfont(current)].space -- can be sped up inserted = factor * fontspace - insert_after(hnut,current,new_kern(inserted)) + insert_after(head,current,new_kern(inserted)) if trace then report("inserting space at %C . [%p] %C .",pchar,inserted,nchar) end - done = true end local next3 = getnext(next2) if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then @@ -115,7 +112,6 @@ function periodkerns.handler(head) end end setwidth(next3,space) - done = true else if trace then if inserted then @@ -136,7 +132,7 @@ function periodkerns.handler(head) end end end - return head, done + return head end local enabled = false @@ -144,7 +140,6 @@ local enabled = false function periodkerns.set(factor) factor = tonumber(factor) or 0 if not enabled then - prependaction("processors","normalizers","typesetters.periodkerns.handler") enableaction("processors","typesetters.periodkerns.handler") enabled = true end diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua index b6aae0cae37..d29eb17b8f3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-rep.lua @@ -21,8 +21,6 @@ local nodes = nodes local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getchar = nuts.getchar @@ -81,9 +79,8 @@ local function process(what,head,current,char) return head, current end -function nodes.handlers.stripping(head) - head = tonut(head) - local current, done = head, false +function nodes.handlers.stripping(head) -- use loop + local current = head while current do local char, id = isglyph(current) if char then @@ -93,7 +90,6 @@ function nodes.handlers.stripping(head) local what = glyphs[char] if what then head, current = process(what,head,current,char) - done = true else -- handling of spacing etc has to be done elsewhere current = getnext(current) end @@ -104,7 +100,7 @@ function nodes.handlers.stripping(head) current = getnext(current) end end - return tonode(head), done + return head end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-rub.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-rub.lua index 8c41a561176..da63d7b64e9 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-rub.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-rub.lua @@ -33,8 +33,6 @@ local v_auto = variables.auto local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local getid = nuts.getid local getsubtype = nuts.getsubtype local getattr = nuts.getattr @@ -53,7 +51,9 @@ local setwidth = nuts.setwidth local hpack = nuts.hpack local insert_after = nuts.insert_after local takebox = nuts.takebox -local traverse_id = nuts.traverse_id + +local nexthlist = nuts.traversers.hlist +local nextvlist = nuts.traversers.vlist local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph @@ -63,14 +63,11 @@ local glue_code = nodecodes.glue local penalty_code = nodecodes.penalty local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local whatsit_code = nodecodes.whatsit local localpar_code = nodecodes.localpar - -local whatsitcodes = nodes.whatsitcodes ------ late_luacode = whatsitcodes.latelua +local dir_code = nodecodes.dir local kerncodes = nodes.kerncodes -local font_code = kerncodes.font +local fontkern_code = kerncodes.font local nodepool = nuts.pool local new_kern = nodepool.kern @@ -194,7 +191,6 @@ do end function rubies.check(head) - local head = tonut(head) local current = head local start = nil local stop = nil @@ -208,7 +204,7 @@ function rubies.check(head) setprev(start) setnext(stop) local h = hpack(start) - if prev == head then + if start == head then head = h else setlink(prev,h) @@ -247,20 +243,21 @@ function rubies.check(head) start = current stop = current end - elseif id == kern_code and getsubtype(current,font_code) then + -- go on + elseif id == kern_code and getsubtype(current,fontkern_code) then -- go on elseif found and id == disc_code then -- go on (todo: look into disc) elseif found then - flush("flush 4") + flush("flush 3") found = nil end current = nx end if found then - flush("flush 5") + flush("flush 4") end - return tonode(head), true + return head, true -- no need for true end local attach @@ -309,11 +306,11 @@ local function whatever(current) local c = getprev(current) while c do local id = getid(c) - if id == glue_code or id == penalty_code or id == kern_code or (id == whatsit_code and getsubtype(current,localpar_code)) then + if id == glue_code or id == penalty_code or id == kern_code then -- go on elseif id == hlist_code and getwidth(c) == 0 then -- go on - elseif id == whatsit_code or id == localpar_code then + elseif id == whatsit_code or id == localpar_code or id == dir_code then -- go on else l = false @@ -371,20 +368,17 @@ local function whatever(current) end end -attach = function(head) - for current in traverse_id(hlist_code,head) do +attach = function(head) -- traverse_list + for current in nexthlist, head do whatever(current) end - for current in traverse_id(vlist_code,head) do + for current in nextvlist, head do whatever(current) end - return head, true + return head end -function rubies.attach(head) - local h, d = attach(tonut(head)) - return tonode(h), d -end +rubies.attach = attach -- for now there is no need to be compact diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-rub.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-rub.mkiv index d51c53aa414..cc1571ad776 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-rub.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-rub.mkiv @@ -26,6 +26,7 @@ \installcorenamespace {ruby} \installcorenamespace {rubyanalyze} \installcorenamespace {rubyplacement} +\installcorenamespace {rubynumber} \installcommandhandler \??ruby {ruby} \??ruby @@ -135,6 +136,14 @@ \c!hoffset=\zeropoint, \c!voffset=-2\exheight] +%D Experiment too: + +\unexpanded\def\numberedruby[#1]#2% + {\doifnotcounter{\??rubynumber#1}{\definecounter[\??rubynumber#1]\setcounter[\??rubynumber#1][1]}% + \ruby[#1]{#2}{\convertedcounter[\??rubynumber#1]}% + \incrementcounter[\??rubynumber#1]% + \relax} + \protect \endinput % \usemodule[art-01]\setupbodyfont[dejavu,12pt] diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv index d4881b80a5d..0dfd111ae33 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-scr.mkiv @@ -142,8 +142,8 @@ \unexpanded\def\typo_scripts_lowhigh_indeed[#1]#2#3% todo: align .. [#1] is compatible hack {\dostarttagged\t!subsup\currentlowhigh - \setbox\plusfour\hbox{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}% - \setbox\plussix \hbox{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}% + \setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}% + \setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}% \doif{#1}{\v!left} {\ifdim\wd\plusfour<\wd\plussix \setbox\plusfour\hpack to \wd\plussix {\hss\box\plusfour}% @@ -166,7 +166,7 @@ {\dontleavehmode \begingroup \kern\lowhighparameter\c!distance\relax - \setbox\scratchbox\hbox\bgroup + \setbox\scratchbox\hpack\bgroup #1\lowhighparameter#2\hbox\bgroup \ifx\fontsize\empty \ifmmode diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua index bda1397197e..78fc2296443 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-spa.lua @@ -23,12 +23,9 @@ local unsetvalue = attributes.unsetvalue local v_reset = interfaces.variables.reset local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev -local getfont = nuts.getfont local takeattr = nuts.takeattr local isglyph = nuts.isglyph @@ -73,8 +70,6 @@ end -- todo cache lastattr function spacings.handler(head) - head = tonut(head) - local done = false local start = head -- head is always begin of par (whatsit), so we have at least two prev nodes -- penalty followed by glue @@ -87,10 +82,11 @@ function spacings.handler(head) if data then local map = data.characters[char] if map then + local font = id local left = map.left local right = map.right local alternative = map.alternative - local quad = quaddata[getfont(start)] + local quad = quaddata[font] local prev = getprev(start) if left and left ~= 0 and prev then local ok = false @@ -122,7 +118,6 @@ function spacings.handler(head) end insert_node_before(head,start,new_penalty(10000)) insert_node_before(head,start,new_glue(left*quad)) - done = true end end local next = getnext(start) @@ -159,7 +154,6 @@ function spacings.handler(head) end insert_node_after(head,start,new_glue(right*quad)) insert_node_after(head,start,new_penalty(10000)) - done = true end end end @@ -172,7 +166,7 @@ function spacings.handler(head) start = getnext(start) end end - return tonode(head), done + return head end local enabled = false diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua index 2d3037bdc91..6c02b929167 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-sus.lua @@ -40,8 +40,6 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local getid = nuts.getid local getprev = nuts.getprev @@ -164,7 +162,6 @@ local colors = { local found = 0 function typesetters.marksuspects(head) - local head = tonut(head) local current = head local lastdone = nil while current do @@ -254,7 +251,7 @@ function typesetters.marksuspects(head) current = getnext(current) end end - return tonode(head), found > 0 + return head end local function showsuspects(head) @@ -289,9 +286,9 @@ end function typesetters.showsuspects(head) if found > 0 then - return tonode(showsuspects(tonut(head))), true + return showsuspects(head) else - return head, false + return head end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua index 870d006ccf8..8cf29832971 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-tal.lua @@ -34,7 +34,6 @@ local v_number = variables.number local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -50,8 +49,8 @@ local setchar = nuts.setchar local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after -local traverse_list_by_id = nuts.traverse_id -local list_dimensions = nuts.dimensions +local nextglyph = nuts.traversers.glyph +local getdimensions = nuts.dimensions local first_glyph = nuts.first_glyph local setglue = nuts.setglue @@ -171,23 +170,22 @@ local function traced_kern(w) return tracedrule(w,nil,nil,"darkgray") end -function characteralign.handler(originalhead,where) +function characteralign.handler(head,where) if not datasets then - return originalhead, false + return head end - local head = tonut(originalhead) -- local first = first_glyph(head) -- we could do that once local first - for n in traverse_list_by_id(glyph_code,head) do + for n in nextglyph, head do first = n break end if not first then - return originalhead, false + return head end local a = getattr(first,a_characteralign) if not a or a == 0 then - return originalhead, false + return head end local column = div(a,0xFFFF) local row = a % 0xFFFF @@ -210,7 +208,7 @@ function characteralign.handler(originalhead,where) while current do local char, id = isglyph(current) if char then - local font = getfont(current) + local font = id --- nicer local data = fontcharacters[font][char] local unicode = data and data.unicode or char -- ignore tables if not unicode then -- type(unicode) ~= "number" @@ -234,8 +232,9 @@ function characteralign.handler(originalhead,where) if not b_start then if sign then b_start = sign - local new = validsigns[getchar(sign)] - if char == new or not fontcharacters[getfont(sign)][new] then + local c, f = isglyph(sign) + local new = validsigns[c] + if char == new or not fontcharacters[f][new] then if trace_split then setcolor(sign,"darkyellow") end @@ -285,7 +284,7 @@ function characteralign.handler(originalhead,where) while current do local char, id = isglyph(current) if char then - local font = getfont(current) + local font = id -- nicer -- local unicode = unicodes[font][char] local unicode = fontcharacters[font][char].unicode or char -- ignore tables if not unicode then @@ -322,21 +321,21 @@ function characteralign.handler(originalhead,where) local predefined = dataset.predefined local before, after if predefined then - before = b_start and list_dimensions(b_start,getnext(b_stop)) or 0 - after = a_start and list_dimensions(a_start,getnext(a_stop)) or 0 + before = b_start and getdimensions(b_start,getnext(b_stop)) or 0 + after = a_start and getdimensions(a_start,getnext(a_stop)) or 0 else local entry = list[row] if entry then before = entry.before or 0 after = entry.after or 0 else - before = b_start and list_dimensions(b_start,getnext(b_stop)) or 0 - after = a_start and list_dimensions(a_start,getnext(a_stop)) or 0 + before = b_start and getdimensions(b_start,getnext(b_stop)) or 0 + after = a_start and getdimensions(a_start,getnext(a_stop)) or 0 list[row] = { before = before, after = after, } - return tonode(head), true + return head, true end if not dataset.collected then -- print("[maxbefore] [maxafter]") @@ -404,5 +403,5 @@ function characteralign.handler(originalhead,where) insert_node_after(head,c,new_kern(maxafter)) end end - return tonode(head), true + return head end diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua index 07e34cd6c8f..9fb5441526c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.lua @@ -8,65 +8,80 @@ if not modules then modules = { } end modules ['typo-wrp'] = { -- begin/end par wrapping stuff ... more to come -local nodecodes = nodes.nodecodes +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local penaltycodes = nodes.penaltycodes +local boundarycodes = nodes.boundarycodes -local glue_code = nodecodes.glue -local penalty_code = nodecodes.penalty -local parfill_skip_code = nodes.gluecodes.parfillskip -local user_penalty_code = nodes.penaltycodes.userpenalty +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local boundary_code = nodecodes.boundary -local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode +local parfillskip_code = gluecodes.parfillskip -local find_node_tail = nuts.tail -local getprev = nuts.getprev -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getpenalty = nuts.getpenalty -local remove = nuts.remove +local userpenalty_code = penaltycodes.userpenalty +local linepenalty_code = penaltycodes.linepenalty +local linebreakpenalty_code = penaltycodes.linebreakpenalty -local enableaction = nodes.tasks.enableaction +local wordboundary_code = boundarycodes.word -local wrappers = { } -typesetters.wrappers = wrappers +local nuts = nodes.nuts -local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end) +local find_node_tail = nuts.tail +local getprev = nuts.getprev +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getpenalty = nuts.getpenalty +local remove = nuts.remove -local report = logs.reporter("paragraphs","wrappers") +local enableaction = nodes.tasks.enableaction + +local wrappers = { } +typesetters.wrappers = wrappers + +local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end) + +local report = logs.reporter("paragraphs","wrappers") -- we really need to pass tail too ... but then we need to check all the plugins -- bah ... slowdown +-- This check is very tight to the crlf definition. We check for: +-- +-- [break -10000] [wordboundary] [line(break)penalty] [parfillskip] +-- +-- If needed we can extend this checker for other cases but then we will also +-- use attributes. + local function remove_dangling_crlf(head,tail) - if tail and getid(tail) == glue_code and getsubtype(tail) == parfill_skip_code then + if head and tail and getid(tail) == glue_code and getsubtype(tail) == parfillskip_code then tail = getprev(tail) - if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == 10000 then - tail = getprev(tail) - if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == -10000 then - if tail == head then - -- can't happen - else - if trace_wrappers then - report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno) + if tail and getid(tail) == penalty_code then + local subtype = getsubtype(tail) + if subtype == linepenalty_code or subtype == linebreakpenalty_code then + tail = getprev(tail) + if tail and getid(tail) == boundary_code and getsubtype(tail) == wordboundary_code then + tail = getprev(tail) + if tail ~= head and getid(tail) == penalty_code and getsubtype(tail) == userpenalty_code and getpenalty(tail) == -10000 then + if trace_wrappers then + report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno) + end + remove(head,tail,true) + return head, tail end - remove(head,tail,true) - return head, tail, true end end end end - return head, tail, false + return head, tail end function wrappers.handler(head) - local head = tonut(head) if head then local tail = find_node_tail(head) - local done = false - head, tail, done = remove_dangling_crlf(head,tail) -- will be action chain + head, tail = remove_dangling_crlf(head,tail) -- will be action chain end - return head, true + return head end interfaces.implement { diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv index 0e010515b05..4e9ecf2e128 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv +++ b/Master/texmf-dist/tex/context/base/mkiv/typo-wrp.mkiv @@ -40,18 +40,21 @@ \unexpanded\def\spac_crlf {\clf_enablecrlf % once \unskip - \prewordbreak % here or in \spac_crlf_placeholder \spac_crlf_placeholder \ifcase\raggedstatus\hfil\or\or\or\hfil\fi + % in bad usage this can lead to: [break -10000] [wordboundary] [line(break)penalty] [parfillskip] \break - \hskip\zeropoint % new so that the next word also hyphenates + \wordboundary + % which we then remove (maybe we should flag the wordboundary with an attribute but not now \ignorespaces} \unexpanded\def\spac_crlf_placeholder {\strut} \unexpanded\def\spac_crlf_placeholder_show - {\hbox to \zeropoint{\strut{\infofont\kern.25\emwidth}\lohi{\infofont CR}{\infofont LF}\hss}} + {\wordboundary + %\nobreak + \hpack to \zeropoint{\strut{\infofont\kern.25\emwidth}\lohi{\infofont CR}{\infofont LF}\hss}} \unexpanded\def\settestcrlf {\let\spac_crlf_placeholder\spac_crlf_placeholder_show} diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua b/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua index b8db0c58345..6932e8804d3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-deb.lua @@ -10,9 +10,6 @@ if not modules then modules = { } end modules ['util-deb'] = { -- bound to a variable, like node.new, node.copy etc (contrary to for instance -- node.has_attribute which is bound to a has_attribute local variable in mkiv) -local debug = require "debug" - -local getinfo, sethook = debug.getinfo, debug.sethook local type, next, tostring, tonumber = type, next, tostring, tonumber local format, find, sub, gsub = string.format, string.find, string.sub, string.gsub local insert, remove, sort = table.insert, table.remove, table.sort @@ -98,7 +95,7 @@ end setmetatableindex(names,function(t,name) local v = setmetatableindex(function(t,source) local v = setmetatableindex(function(t,line) - local v = { total = 0, count = 0 } + local v = { total = 0, count = 0, nesting = 0 } t[line] = v return v end) @@ -109,6 +106,9 @@ setmetatableindex(names,function(t,name) return v end) +local getinfo = nil +local sethook = nil + local function hook(where) local f = getinfo(2,"nSl") if f then @@ -128,12 +128,24 @@ local function hook(where) end local data = names[name][source][line] if where == "call" then - data.count = data.count + 1 - insert(data,ticks()) + local nesting = data.nesting + if nesting == 0 then + data.count = data.count + 1 + insert(data,ticks()) + data.nesting = 1 + else + data.nesting = nesting + 1 + end elseif where == "return" then - local t = remove(data) - if t then - data.total = data.total + ticks() - t + local nesting = data.nesting + if nesting == 1 then + local t = remove(data) + if t then + data.total = data.total + ticks() - t + end + data.nesting = 0 + else + data.nesting = nesting - 1 end end end @@ -228,6 +240,27 @@ function debugger.showstats(printer,threshold) -- table.save("luatex-profile.lua",names) end +local function getdebug() + if sethook and getinfo then + return + end + if not debug then + local okay + okay, debug = pcall(require,"debug") + end + if type(debug) ~= "table" then + return + end + getinfo = debug.getinfo + sethook = debug.sethook + if type(getinfo) ~= "function" then + getinfo = nil + end + if type(sethook) ~= "function" then + sethook = nil + end +end + function debugger.savestats(filename,threshold) local f = io.open(filename,'w') if f then @@ -237,7 +270,8 @@ function debugger.savestats(filename,threshold) end function debugger.enable() - if nesting == 0 then + getdebug() + if sethook and getinfo and nesting == 0 then running = true if initialize then initialize() @@ -259,7 +293,7 @@ function debugger.disable() if nesting > 0 then nesting = nesting - 1 end - if nesting == 0 then + if sethook and getinfo and nesting == 0 then sethook() end end @@ -282,20 +316,25 @@ end -- from the lua book: local function showtraceback(rep) -- from lua site / adapted - local level = 2 -- we don't want this function to be reported - local reporter = rep or report - while true do - local info = getinfo(level, "Sl") - if not info then - break - elseif info.what == "C" then - reporter("%2i : %s",level-1,"C function") - else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + getdebug() + if getinfo then + local level = 2 -- we don't want this function to be reported + local reporter = rep or report + while true do + local info = getinfo(level, "Sl") + if not info then + break + elseif info.what == "C" then + reporter("%2i : %s",level-1,"C function") + else + reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + end + level = level + 1 end - level = level + 1 end end debugger.showtraceback = showtraceback -- debug.showtraceback = showtraceback + +-- showtraceback() diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-env.lua b/Master/texmf-dist/tex/context/base/mkiv/util-env.lua index 064bd513ad5..dde76587486 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-env.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-env.lua @@ -72,20 +72,16 @@ end -- dirty tricks (we will replace the texlua call by luatex --luaonly) local validengines = allocate { - ["luatex"] = true, - ["luajittex"] = true, - -- ["luatex.exe"] = true, - -- ["luajittex.exe"] = true, + ["luatex"] = true, + ["luajittex"] = true, } local basicengines = allocate { - ["luatex"] = "luatex", - ["texlua"] = "luatex", - ["texluac"] = "luatex", - ["luajittex"] = "luajittex", - ["texluajit"] = "luajittex", - -- ["texlua.exe"] = "luatex", - -- ["texluajit.exe"] = "luajittex", + ["luatex"] = "luatex", + ["texlua"] = "luatex", -- obsolete + ["texluac"] = "luatex", -- obsolete + ["luajittex"] = "luajittex", + ["texluajit"] = "luajittex", -- obsolete } local luaengines = allocate { @@ -154,8 +150,11 @@ environment.sortedflags = nil -- context specific arguments (in order not to confuse the engine) function environment.initializearguments(arg) - local arguments, files = { }, { } - environment.arguments, environment.files, environment.sortedflags = arguments, files, nil + local arguments = { } + local files = { } + environment.arguments = arguments + environment.files = files + environment.sortedflags = nil for index=1,#arg do local argument = arg[index] if index > 0 then @@ -174,6 +173,11 @@ function environment.initializearguments(arg) end end end + if not environment.ownname then + if os.selfpath and os.selfname then + environment.ownname = file.addsuffix(file.join(os.selfpath,os.selfname),"lua") + end + end environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua') end @@ -281,13 +285,20 @@ if arg then for index=1,#arg do local argument = arg[index] if find(argument,"^\"") then - newarg[#newarg+1] = gsub(argument,"^\"","") - if not find(argument,"\"$") then + if find(argument,"\"$") then + newarg[#newarg+1] = gsub(argument,"^\"(.-)\"$","%1") + instring = false + else + newarg[#newarg+1] = gsub(argument,"^\"","") instring = true end elseif find(argument,"\"$") then - newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","") - instring = false + if instring then + newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","") + instring = false + else + newarg[#newarg+1] = argument + end elseif instring then newarg[#newarg] = newarg[#newarg] .. " " .. argument else diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-evo.lua b/Master/texmf-dist/tex/context/base/mkiv/util-evo.lua index 7f0b59ac452..dfb395e082b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-evo.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-evo.lua @@ -161,15 +161,22 @@ local function loadedtable(filename) for i=1,10 do local t = loadtable(filename) if t then + report("file %a loaded",filename) return t else ossleep(1/4) end end end + report("file %a not loaded",filename) return { } end +local function savedtable(filename,data) + savetable(filename,data) + report("file %a saved",filename) +end + local function loadpresets(filename) local presets = loadtable(filename) if presets then @@ -194,6 +201,13 @@ local function loadeverything(filename) return loadedtable(filename) end +local function loadlatest(filename) + if type(filename) == "table" and validpresets(filename) then + filename = filename.files and filename.files.latest + end + return loadedtable(filename) +end + local function result(t,fmt,a,b,c) if t then report(fmt,a or "done",b or "done",c or "done","done") @@ -365,6 +379,21 @@ local function findzone(presets,name) return usedzones and usedzones[name] end +local function getzonenames(presets) + if not presets then + return { } + end + local data = presets.data + if not data then + return { } + end + local t = sortedkeys(data.zones or { }) + for i=1,#t do + t[i] = lower(t[i]) + end + return t +end + local function gettargets(zone) -- maybe also for a day local schedule = zone.schedule local min = false @@ -503,7 +532,7 @@ local function geteverything(presets,noschedules) end end end - savetable(presets.files.everything,data) + savedtable(presets.files.everything,data) return result(data,"getting everything, %s") end end @@ -521,26 +550,29 @@ local function gettemperatures(presets) for i=1,#data do local gateways = data[i].gateways local locationinfo = data[i].locationInfo - local locationid = locationinfo.locationId - if gateways then - local status = getstatus(presets,locationid,locationinfo.name) - if status then - for i=1,#gateways do - local g = status.gateways[i] - local gateway = gateways[i] - local systems = gateway.temperatureControlSystems - if systems then - local s = g.temperatureControlSystems - for i=1,#systems do - local zones = systems[i].zones - if zones then - local z = s[i].zones - for i=1,#zones do - if validzonetypes[zone.zoneType] then - local z = z[i] - if z.name == zone.name then - zone.temperatureStatus = z.temperatureStatus - updated = true + if locationinfo then + local locationid = locationinfo.locationId + if gateways then + local status = getstatus(presets,locationid,locationinfo.name) + if status then + for i=1,#gateways do + local g = status.gateways[i] + local gateway = gateways[i] + local systems = gateway.temperatureControlSystems + if systems then + local s = g.temperatureControlSystems + for i=1,#systems do + local zones = systems[i].zones + if zones then + local z = s[i].zones + for i=1,#zones do + local zone = zones[i] + if validzonetypes[zone.zoneType] then + local z = z[i] + if z.name == zone.name then + zone.temperatureStatus = z.temperatureStatus + updated = true + end end end end @@ -548,12 +580,16 @@ local function gettemperatures(presets) end end end + else + report("no gateways") end + else + report("no location info") end end if updated then data.time = ostime() - savetable(presets.files.latest,data) + savedtable(presets.files.latest,data) end return result(data,"getting temperatures, %s") end @@ -601,7 +637,10 @@ end local function loadtemperatures(presets) if validpresets(presets) then - local status = loadeverything(presets) + local status = loadlatest(presets) + if not status or not next(status) then + status = loadeverything(presets) + end if status then local usedgateways = presets.data.gateways for i=1,#status do @@ -637,9 +676,10 @@ end local function updatetemperatures(presets) if validpresets(presets) then local everythingname = presets.files.everything + local latestname = presets.files.latest local historyname = presets.files.history - if everythingname and historyname then - gettemperatures(presets,everythingname) + if (everythingname or latestname) and historyname then + gettemperatures(presets) local t = loadtemperatures(presets) if t then local data = { } @@ -649,7 +689,7 @@ local function updatetemperatures(presets) end local history = loadhistory(historyname) or { } setmoment(history,ostime(),data) - savetable(historyname,history) + savedtable(historyname,history) return result(t,"updating temperatures, %s") end end @@ -747,10 +787,10 @@ local function off(presets,name) end end -local function on(presets,name) +local function on(presets,name,temperature) local zone = presets and getzonestate(presets,name) if zone then - setzonestate(presets,name,zone.highest) + setzonestate(presets,name,temperature or zone.highest) end end @@ -787,7 +827,7 @@ local function settask(presets,when,tag,action) else list[tag] = nil end - savetable(presets.files.schedules,list) + savedtable(presets.files.schedules,list) end end @@ -832,7 +872,7 @@ local function checktasks(presets) for k, v in next, q do list[q] = nil end - savetable(presets.files.schedules,list) + savedtable(presets.files.schedules,list) end return list end @@ -954,10 +994,10 @@ end evohome = { helpers = { - getaccesstoken = getaccesstoken, -- presets - getuserinfo = getuserinfo, -- presets - getlocationinfo = getlocationinfo, -- presets - getschedule = getschedule, -- presets, name + getaccesstoken = getaccesstoken, -- presets + getuserinfo = getuserinfo, -- presets + getlocationinfo = getlocationinfo, -- presets + getschedule = getschedule, -- presets, name -- geteverything = geteverything, -- presets, noschedules gettemperatures = gettemperatures, -- presets @@ -965,6 +1005,7 @@ evohome = { setzonestate = setzonestate, -- presets, name, temperature resetzonestate = resetzonestate, -- presets, name getzonedata = findzone, -- presets, name + getzonenames = getzonenames, -- presets -- loadpresets = loadpresets, -- filename loadhistory = loadhistory, -- presets | filename diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua b/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua index 0e8ed4e5751..9f96a01b911 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-fil.lua @@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['util-fil'] = { license = "see context related readme files" } +local tonumber = tonumber local byte = string.byte local char = string.char @@ -196,41 +197,23 @@ function files.readinteger4le(f) end end --- function files.readfixed2(f) --- local a, b = byte(f:read(2),1,2) --- if a >= 0x80 then --- return (0x100 * a + b - 0x10000)/256.0 --- else --- return (0x100 * a + b)/256.0 --- end --- end - function files.readfixed2(f) local a, b = byte(f:read(2),1,2) if a >= 0x80 then - return (a - 0x100) + b/0x100 + tonumber((a - 0x100) .. "." .. b) else - return (a ) + b/0x100 + tonumber(( a ) .. "." .. b) end end --- (real) (n>>16) + ((n&0xffff)/65536.0)) - --- function files.readfixed4(f) --- local a, b, c, d = byte(f:read(4),1,4) --- if a >= 0x80 then --- return (0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000)/65536.0 --- else --- return (0x1000000 * a + 0x10000 * b + 0x100 * c + d)/65536.0 --- end --- end +-- (real) (n>>16) + ((n&0xffff)/65536.0)) but no cast in lua (we could use unpack) function files.readfixed4(f) local a, b, c, d = byte(f:read(4),1,4) if a >= 0x80 then - return (0x100 * a + b - 0x10000) + (0x100 * c + d)/0x10000 + tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d)) else - return (0x100 * a + b ) + (0x100 * c + d)/0x10000 + tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d)) end end @@ -343,3 +326,40 @@ if fio and fio.readcardinal1 then end end + +if fio and fio.readcardinaltable then + + files.readcardinaltable = fio.readcardinaltable + files.readintegertable = fio.readintegertable + +else + + local readcardinal1 = files.readcardinal1 + local readcardinal2 = files.readcardinal2 + local readcardinal3 = files.readcardinal3 + local readcardinal4 = files.readcardinal4 + + function files.readcardinaltable(f,n,b) + local t = { } + if b == 1 then for i=1,n do t[i] = readcardinal1(f) end + elseif b == 2 then for i=1,n do t[i] = readcardinal2(f) end + elseif b == 3 then for i=1,n do t[i] = readcardinal3(f) end + elseif b == 4 then for i=1,n do t[i] = readcardinal4(f) end end + return t + end + + local readinteger1 = files.readinteger1 + local readinteger2 = files.readinteger2 + local readinteger3 = files.readinteger3 + local readinteger4 = files.readinteger4 + + function files.readintegertable(f,n,b) + local t = { } + if b == 1 then for i=1,n do t[i] = readinteger1(f) end + elseif b == 2 then for i=1,n do t[i] = readinteger2(f) end + elseif b == 3 then for i=1,n do t[i] = readinteger3(f) end + elseif b == 4 then for i=1,n do t[i] = readinteger4(f) end end + return t + end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua b/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua index 371a5dfcece..fe80c64201e 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-fmt.lua @@ -35,10 +35,17 @@ function formatters.formatcolumns(result,between) for j=1,n do local rj = r[j] local tj = type(rj) +-- if tj == "number" then +-- numbers[j] = true +-- end +-- if tj ~= "string" then +-- rj = tostring(rj) +-- r[j] = rj +-- end if tj == "number" then numbers[j] = true - end - if tj ~= "string" then + rj = tostring(rj) + elseif tj ~= "string" then rj = tostring(rj) r[j] = rj end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua b/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua index e5f83e06c47..acbf160904d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-jsn.lua @@ -14,10 +14,12 @@ if not modules then modules = { } end modules ['util-jsn'] = { -- -- Reminder for me: check usage in framework and extend when needed. Also document -- it in the cld lib documentation. +-- +-- Upgraded for handling the somewhat more fax server templates. local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg local lpegmatch = lpeg.match -local format = string.format +local format, gsub = string.format, string.gsub local utfchar = utf.char local concat = table.concat @@ -26,9 +28,6 @@ local tonumber, tostring, rawset, type, next = tonumber, tostring, rawset, type, local json = utilities.json or { } utilities.json = json --- moduledata = moduledata or { } --- moduledata.json = json - -- \\ \/ \b \f \n \r \t \uHHHH local lbrace = P("{") @@ -43,16 +42,19 @@ local whitespace = lpeg.patterns.whitespace local optionalws = whitespace^0 local escapes = { - -- ["\\"] = "\\", -- lua will escape these - -- ["/"] = "/", -- no need to escape this one - ["b"] = "\010", - ["f"] = "\014", - ["n"] = "\n", - ["r"] = "\r", - ["t"] = "\t", + ["b"] = "\010", + ["f"] = "\014", + ["n"] = "\n", + ["r"] = "\r", + ["t"] = "\t", } -local escape_un = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end +-- todo: also handle larger utf16 + +local escape_un = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s) + return utfchar(tonumber(s,16)) +end) + local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote @@ -85,7 +87,9 @@ function json.tolua(str) return lpegmatch(jsonconverter,str) end -local function tojson(value,t) -- we could optimize #t +local escaper + +local function tojson(value,t,n) -- we could optimize #t local kind = type(value) if kind == "table" then local done = false @@ -93,60 +97,75 @@ local function tojson(value,t) -- we could optimize #t if size == 0 then for k, v in next, value do if done then - t[#t+1] = "," + n = n + 1 ; t[n] = "," else - t[#t+1] = "{" + n = n + 1 ; t[n] = "{" done = true end - t[#t+1] = format("%q:",k) - tojson(v,t) + n = n + 1 ; t[n] = format("%q:",k) + t, n = tojson(v,t,n) end if done then - t[#t+1] = "}" + n = n + 1 ; t[n] = "}" else - t[#t+1] = "{}" + n = n + 1 ; t[n] = "{}" end elseif size == 1 then -- we can optimize for non tables - t[#t+1] = "[" - tojson(value[1],t) - t[#t+1] = "]" + n = n + 1 ; t[n] = "[" + t, n = tojson(value[1],t,n) + n = n + 1 ; t[n] = "]" else for i=1,size do if done then - t[#t+1] = "," + n = n + 1 ; t[n] = "," else - t[#t+1] = "[" + n = n + 1 ; t[n] = "[" done = true end - tojson(value[i],t) + t, n = tojson(value[i],t,n) end - t[#t+1] = "]" + n = n + 1 ; t[n] = "]" end elseif kind == "string" then - t[#t+1] = format("%q",value) + n = n + 1 ; t[n] = '"' + n = n + 1 ; t[n] = lpegmatch(escaper,value) or value + n = n + 1 ; t[n] = '"' elseif kind == "number" then - t[#t+1] = value + n = n + 1 ; t[n] = value elseif kind == "boolean" then - t[#t+1] = tostring(value) + n = n + 1 ; t[n] = tostring(value) end - return t + return t, n end function json.tostring(value) -- todo optimize for non table local kind = type(value) if kind == "table" then - return concat(tojson(value,{}),"") + if not escaper then + local escapes = { + ["\\"] = "\\u005C", + ["\""] = "\\u0022", + } + for i=0,0x20 do + escapes[utfchar(i)] = format("\\u%04X",i) + end + escaper = Cs( ( + (R('\0\x20') + S('\"\\')) / escapes + + P(1) + )^1 ) + + end + return concat((tojson(value,{},0))) elseif kind == "string" or kind == "number" then - return value + return lpegmatch(escaper,value) or value else return tostring(value) end end --- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] - +-- local tmp = [[ { "t" : "foobar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] -- tmp = json.tolua(tmp) -- inspect(tmp) -- tmp = json.tostring(tmp) @@ -155,7 +174,6 @@ end -- inspect(tmp) -- tmp = json.tostring(tmp) -- inspect(tmp) - -- inspect(json.tostring(true)) function json.load(filename) @@ -165,4 +183,11 @@ function json.load(filename) end end +-- local s = [[\foo"bar"]] +-- local j = json.tostring { s = s } +-- local l = json.tolua(j) +-- inspect(j) +-- inspect(l) +-- print(s==l.s) + return json diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua index 714cfd4c77c..fb65a566e24 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-lib.lua @@ -237,7 +237,7 @@ local function locate(required,version,trace,report,action) report("stored library: %a",required) end end - return library + return library or nil end do @@ -352,7 +352,7 @@ We use the same lookup logic for ffi loading. trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end) -- pushlibpath(pathpart(name)) - -- local message, library = pcall(savedffiload,nameonly(name)) + -- local state, library = pcall(savedffiload,nameonly(name)) -- poplibpath() local loaded = { } @@ -361,11 +361,11 @@ We use the same lookup logic for ffi loading. name = removesuffix(name) local l = loaded[name] if l == nil then - local message, library = pcall(savedffiload,name) - if type(message) == "userdata" then - l = message - elseif type(library) == "userdata" then + local state, library = pcall(savedffiload,name) + if type(library) == "userdata" then l = library + elseif type(state) == "userdata" then + l = state else l = false end @@ -376,6 +376,20 @@ We use the same lookup logic for ffi loading. return l end + local function getlist(required) + local list = directives.value("system.librarynames" ) + if type(list) == "table" then + list = list[required] + if type(list) == "table" then + if trace then + report("using lookup list for library %a: % | t",required,list) + end + return list + end + end + return { required } + end + function ffilib(name,version) name = removesuffix(name) local l = loaded[name] @@ -384,23 +398,45 @@ We use the same lookup logic for ffi loading. report_ffilib("reusing already loaded %a",name) end return l - elseif version == "system" then - return locateindeed(name) + end + local list = getlist(name) + if version == "system" then + for i=1,#list do + local library = locateindeed(list[i]) + if type(library) == "userdata" then + return library + end + end else - return locate(name,version,trace_ffilib,report_ffilib,locateindeed) + for i=1,#list do + local library = locate(list[i],version,trace_ffilib,report_ffilib,locateindeed) + if type(library) == "userdata" then + return library + end + end end end function ffi.load(name) - local library = ffilib(name) - if type(library) == "userdata" then - return library + local list = getlist(name) + for i=1,#list do + local library = ffilib(list[i]) + if type(library) == "userdata" then + return library + end end if trace_ffilib then report_ffilib("trying to load %a using normal loader",name) end -- so here we don't store - return savedffiload(name) + for i=1,#list do + local state, library = pcall(savedffiload,list[i]) + if type(library) == "userdata" then + return library + elseif type(state) == "userdata" then + return library + end + end end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua b/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua index b7de119360c..1199301f42f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-lua.lua @@ -88,6 +88,7 @@ function luautilities.loadedluacode(fullname,forcestrip,name,macros) code() else report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message") + code, message = loadfile(fullname) end if forcestrip and luautilities.stripcode then if type(forcestrip) == "function" then @@ -114,7 +115,7 @@ function luautilities.strippedloadstring(code,name,forcestrip) -- not executed end if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then register(name) - return load(dump(code,true)), 0 -- not yet executes + return load(dump(code,true)), 0 -- not yet executed else return code, 0 end @@ -198,12 +199,12 @@ function luautilities.checkmemory(previous,threshold,trace) -- threshold in MB collectgarbage("collect") local afterwards = collectgarbage("count") if trace or tracememory then - report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB, afterwards %i MB", + report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB", previous/1024,current/1024,delta/1024,threshold,afterwards) end return afterwards elseif trace or tracememory then - report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB", + report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB", previous/1024,current/1024,delta/1024,threshold) end end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua b/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua index 690188ef879..bc835bf563a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-mrg.lua @@ -113,6 +113,7 @@ local pack = digit * space^1 * operator4 * optionalspacing + optionalspaces * separator * optionalspaces local lines = emptyline^2 / "\n" local spaces = (space * space) / " " +local spaces = (space * space * space * space) / " " ----- spaces = ((space+eol)^1 ) / " " local compact = Cs ( ( diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua b/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua index 48d59a9f3f7..08401f22275 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-prs.lua @@ -31,6 +31,7 @@ utilities.parsers.hashes = hashes local digit = R("09") local space = P(' ') local equal = P("=") +local colon = P(":") local comma = P(",") local lbrace = P("{") local rbrace = P("}") @@ -72,11 +73,13 @@ lpegpatterns.nested = nestedbraces -- no capture lpegpatterns.argument = argument -- argument after e.g. = lpegpatterns.content = content -- rest after e.g = -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) + C((nestedbraces + (1-comma))^0) +local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace + + C((nestedbraces + (1-comma))^0) local key = C((1-equal-comma)^1) local pattern_a = (space+comma)^0 * (key * equal * value + key * C("")) local pattern_c = (space+comma)^0 * (key * equal * value) +local pattern_d = (space+comma)^0 * (key * (equal+colon) * value + key * C("")) local key = C((1-space-equal-comma)^1) local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C(""))) @@ -92,10 +95,12 @@ end local pattern_a_s = (pattern_a/set)^1 local pattern_b_s = (pattern_b/set)^1 local pattern_c_s = (pattern_c/set)^1 +local pattern_d_s = (pattern_d/set)^1 patterns.settings_to_hash_a = pattern_a_s patterns.settings_to_hash_b = pattern_b_s patterns.settings_to_hash_c = pattern_c_s +patterns.settings_to_hash_d = pattern_d_s function parsers.make_settings_to_hash_pattern(set,how) if how == "strict" then @@ -126,6 +131,18 @@ function parsers.settings_to_hash(str,existing) end end +function parsers.settings_to_hash_colon_too(str) + if not str or str == "" then + return { } + elseif type(str) == "table" then + return str + else + hash = { } + lpegmatch(pattern_d_s,str) + return hash + end +end + function parsers.settings_to_hash_tolerant(str,existing) if not str or str == "" then return { } @@ -165,7 +182,7 @@ function parsers.settings_to_hash_strict(str,existing) end local separator = comma * space^0 -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) +local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace + C((nestedbraces + (1-comma))^0) local pattern = spaces * Ct(value*(separator*value)^0) @@ -210,7 +227,7 @@ function parsers.settings_to_numbers(str) return str end -local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) +local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace + C((nestedbraces + nestedbrackets + nestedparents + (1-comma))^0) local pattern = spaces * Ct(value*(separator*value)^0) @@ -242,7 +259,7 @@ function parsers.groupedsplitat(symbol,withaction) if not pattern then local symbols = S(symbol) local separator = space^0 * symbols * space^0 - local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) + local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace + C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0) if withaction then local withvalue = Carg(1) * value / function(f,s) return f(s) end @@ -291,7 +308,9 @@ end function parsers.hash_to_string(h,separator,yes,no,strict,omit) if h then - local t, tn, s = { }, 0, sortedkeys(h) + local t = { } + local tn = 0 + local s = sortedkeys(h) omit = omit and tohash(omit) for i=1,#s do local key = s[i] @@ -357,7 +376,8 @@ end) getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense) function parsers.simple_hash_to_string(h, separator) - local t, tn = { }, 0 + local t = { } + local tn = 0 for k, v in sortedhash(h) do if v then tn = tn + 1 @@ -398,7 +418,8 @@ local function repeater(n,str) if n == 1 then return unpack(s) else - local t, tn = { }, 0 + local t = { } + local tn = 0 for i=1,n do for j=1,#s do tn = tn + 1 diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua index b509d9a9b7c..dc8ba72f1c3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sac.lua @@ -10,15 +10,23 @@ if not modules then modules = { } end modules ['util-sac'] = { -- with bytes) local byte, sub = string.byte, string.sub -local extract = bit32 and bit32.extract +local tonumber = tonumber utilities = utilities or { } local streams = { } utilities.streams = streams function streams.open(filename,zerobased) - local f = io.loaddata(filename) - return { f, 1, #f, zerobased or false } + local f = filename and io.loaddata(filename) + if f then + return { f, 1, #f, zerobased or false } + end +end + +function streams.openstring(f,zerobased) + if f then + return { f, 1, #f, zerobased or false } + end end function streams.close() @@ -233,31 +241,31 @@ function streams.readinteger4le(f) end end -function streams.readfixed4(f) +function streams.readfixed2(f) local i = f[2] - local j = i + 3 + local j = i + 1 f[2] = j + 1 - local a, b, c, d = byte(f[1],i,j) + local a, b = byte(f[1],i,j) if a >= 0x80 then - return (0x100 * a + b - 0x10000) + (0x100 * c + d)/0x10000 + tonumber((a - 0x100) .. "." .. b) else - return (0x100 * a + b ) + (0x100 * c + d)/0x10000 + tonumber((a ) .. "." .. b) end end -function streams.readfixed2(f) +function streams.readfixed4(f) local i = f[2] - local j = i + 1 + local j = i + 3 f[2] = j + 1 - local a, b = byte(f[1],i,j) + local a, b, c, d = byte(f[1],i,j) if a >= 0x80 then - return (a - 0x100) + b/0x100 + tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d)) else - return (a ) + b/0x100 + tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d)) end end -if extract then +if bit32 then local extract = bit32.extract local band = bit32.band @@ -386,3 +394,80 @@ if sio and sio.readcardinal2 then streams.readinteger = streams.readinteger1 end + +if sio and sio.readcardinaltable then + + local readcardinaltable = sio.readcardinaltable + local readintegertable = sio.readintegertable + + function utilities.streams.readcardinaltable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + return readcardinaltable(f[1],i,n,b) + end + + function utilities.streams.readintegertable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + return readintegertable(f[1],i,n,b) + end + +else + + local readcardinal1 = streams.readcardinal1 + local readcardinal2 = streams.readcardinal2 + local readcardinal3 = streams.readcardinal3 + local readcardinal4 = streams.readcardinal4 + + function streams.readcardinaltable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + local t = { } + if b == 1 then for i=1,n do t[i] = readcardinal1(f[1],i) end + elseif b == 2 then for i=1,n do t[i] = readcardinal2(f[1],i) end + elseif b == 3 then for i=1,n do t[i] = readcardinal3(f[1],i) end + elseif b == 4 then for i=1,n do t[i] = readcardinal4(f[1],i) end end + return t + end + + local readinteger1 = streams.readinteger1 + local readinteger2 = streams.readinteger2 + local readinteger3 = streams.readinteger3 + local readinteger4 = streams.readinteger4 + + function streams.readintegertable(f,n,b) + local i = f[2] + local s = f[3] + local p = i + n * b + if p > s then + f[2] = s + 1 + else + f[2] = p + end + local t = { } + if b == 1 then for i=1,n do t[i] = readinteger1(f[1],i) end + elseif b == 2 then for i=1,n do t[i] = readinteger2(f[1],i) end + elseif b == 3 then for i=1,n do t[i] = readinteger3(f[1],i) end + elseif b == 4 then for i=1,n do t[i] = readinteger4(f[1],i) end end + return t + end + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua index d302ff276f1..e7a503fafcd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-seq.lua @@ -17,26 +17,39 @@ use locals to refer to them when compiling the chain.

-- todo: protect groups (as in tasks) -local gsub, concat, gmatch = string.gsub, table.concat, string.gmatch -local type, load = type, load +local gsub, gmatch = string.gsub, string.gmatch +local concat, sortedkeys = table.concat, table.sortedkeys +local type, load, next, tostring = type, load, next, tostring -utilities = utilities or { } -local tables = utilities.tables -local allocate = utilities.storage.allocate +utilities = utilities or { } +local tables = utilities.tables +local allocate = utilities.storage.allocate -local formatters = string.formatters +local formatters = string.formatters +local replacer = utilities.templates.replacer -local sequencers = { } -utilities.sequencers = sequencers +local trace_used = false +local trace_detail = false +local report = logs.reporter("sequencer") +local usedcount = 0 +local usednames = { } -local functions = allocate() -sequencers.functions = functions +trackers.register("sequencers.used", function(v) trace_used = true end) +trackers.register("sequencers.detail",function(v) trace_detail = true end) + +local sequencers = { } +utilities.sequencers = sequencers + +local functions = allocate() +sequencers.functions = functions local removevalue = tables.removevalue local replacevalue = tables.replacevalue local insertaftervalue = tables.insertaftervalue local insertbeforevalue = tables.insertbeforevalue +local usedsequences = { } + local function validaction(action) if type(action) == "string" then local g = _G @@ -63,9 +76,11 @@ function sequencers.new(t) -- was reset gskip = { }, dirty = true, runner = nil, + steps = 0, } if t then s.arguments = t.arguments + s.templates = t.templates s.returnvalues = t.returnvalues s.results = t.results local name = t.name @@ -86,120 +101,142 @@ function sequencers.new(t) -- was reset end function sequencers.prependgroup(t,group,where) - t = known[t] - if t then - local order = t.order - removevalue(order,group) - insertbeforevalue(order,where,group) - t.list[group] = { } - t.dirty = true - t.runner = nil + if t and group then + t = known[t] + if t then + local order = t.order + removevalue(order,group) + insertbeforevalue(order,where,group) + t.list[group] = { } + t.dirty = true + t.runner = nil + end end end function sequencers.appendgroup(t,group,where) - t = known[t] - if t then - local order = t.order - removevalue(order,group) - insertaftervalue(order,where,group) - t.list[group] = { } - t.dirty = true - t.runner = nil + if t and group then + t = known[t] + if t then + local order = t.order + removevalue(order,group) + insertaftervalue(order,where,group) + t.list[group] = { } + t.dirty = true + t.runner = nil + end end end function sequencers.prependaction(t,group,action,where,kind,force) - t = known[t] - if t then - local g = t.list[group] - if g and (force or validaction(action)) then - removevalue(g,action) - insertbeforevalue(g,where,action) - t.kind[action] = kind - t.dirty = true - t.runner = nil + if t and group and action then + t = known[t] + if t then + local g = t.list[group] + if g and (force or validaction(action)) then + removevalue(g,action) + insertbeforevalue(g,where,action) + t.kind[action] = kind + t.dirty = true + t.runner = nil + end end end end function sequencers.appendaction(t,group,action,where,kind,force) - t = known[t] - if t then - local g = t.list[group] - if g and (force or validaction(action)) then - removevalue(g,action) - insertaftervalue(g,where,action) - t.kind[action] = kind - t.dirty = true - t.runner = nil + if t and group and action then + t = known[t] + if t then + local g = t.list[group] + if g and (force or validaction(action)) then + removevalue(g,action) + insertaftervalue(g,where,action) + t.kind[action] = kind + t.dirty = true + t.runner = nil + end end end end function sequencers.enableaction(t,action) - t = known[t] - if t then - t.askip[action] = false - t.dirty = true - t.runner = nil + if t and action then + t = known[t] + if t then + t.askip[action] = false + t.dirty = true + t.runner = nil + end end end function sequencers.disableaction(t,action) - t = known[t] - if t then - t.askip[action] = true - t.dirty = true - t.runner = nil + if t and action then + t = known[t] + if t then + t.askip[action] = true + t.dirty = true + t.runner = nil + end end end function sequencers.enablegroup(t,group) - t = known[t] - if t then - t.gskip[action] = false - t.dirty = true - t.runner = nil + if t and group then + t = known[t] + if t then + t.gskip[group] = false + t.dirty = true + t.runner = nil + end end end function sequencers.disablegroup(t,group) - t = known[t] - if t then - t.gskip[action] = true - t.dirty = true - t.runner = nil + if t and group then + t = known[t] + if t then + t.gskip[group] = true + t.dirty = true + t.runner = nil + end end end function sequencers.setkind(t,action,kind) - t = known[t] - if t then - t.kind[action] = kind - t.dirty = true - t.runner = nil + if t and action then + t = known[t] + if t then + t.kind[action] = kind + t.dirty = true + t.runner = nil + end end end function sequencers.removeaction(t,group,action,force) - t = known[t] - local g = t and t.list[group] - if g and (force or validaction(action)) then - removevalue(g,action) - t.dirty = true - t.runner = nil + if t and group and action then + t = known[t] + local g = t and t.list[group] + if g and (force or validaction(action)) then + removevalue(g,action) + t.dirty = true + t.runner = nil + end end end function sequencers.replaceaction(t,group,oldaction,newaction,force) - t = known[t] - if t then - local g = t.list[group] - if g and (force or validaction(oldaction)) then - replacevalue(g,oldaction,newaction) - t.dirty = true - t.runner = nil + if t and group and oldaction and newaction then + t = known[t] + if t then + local g = t.list[group] + if g and (force or validaction(oldaction)) then + replacevalue(g,oldaction,newaction) + t.dirty = true + t.runner = nil + end end end end @@ -209,9 +246,19 @@ local function localize(str) end local function construct(t) - local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip - local arguments, returnvalues, results = t.arguments or "...", t.returnvalues, t.results - local variables, calls, n = { }, { }, 0 + local list = t.list + local order = t.order + local kind = t.kind + local gskip = t.gskip + local askip = t.askip + local name = t.name or "?" + local arguments = t.arguments or "..." + local returnvalues = t.returnvalues + local results = t.results + local variables = { } + local calls = { } + local n = 0 + usedcount = usedcount + 1 for i=1,#order do local group = order[i] if not gskip[group] then @@ -219,6 +266,11 @@ local function construct(t) for i=1,#actions do local action = actions[i] if not askip[action] then + if trace_used then + local action = tostring(action) + report("%02i: category %a, group %a, action %a",usedcount,name,group,action) + usednames[action] = true + end local localized if type(action) == "function" then local name = localize(tostring(action)) @@ -242,6 +294,7 @@ local function construct(t) end end t.dirty = false + t.steps = n if n == 0 then t.compiled = "" else @@ -253,30 +306,27 @@ local function construct(t) t.compiled = formatters["%s\nreturn function(%s)\n%s\nend"](variables,arguments,calls) end end --- print(t.compiled) return t.compiled -- also stored so that we can trace end sequencers.tostring = construct sequencers.localize = localize -compile = function(t,compiler,n) -- already referred to in sequencers.new +compile = function(t,compiler,...) -- already referred to in sequencers.new local compiled if not t or type(t) == "string" then - -- weird ... t.compiled = t .. so return false end if compiler then - compiled = compiler(t,n) + compiled = compiler(t,...) t.compiled = compiled else - compiled = construct(t,n) + compiled = construct(t,...) end local runner if compiled == "" then runner = false else --- inspect(compiled) runner = compiled and load(compiled)() -- we can use loadstripped here end t.runner = runner @@ -285,52 +335,45 @@ end sequencers.compile = compile --- we used to deal with tail as well but now that the lists are always --- double linked and the kernel function no longer expect tail as --- argument we stick to head and done (done can probably also go --- as luatex deals with return values efficiently now .. in the --- past there was some copying involved, but no longer) - --- todo: use sequencer (can have arguments and returnvalues etc now) - -local template_yes_state = [[ -%s -return function(head%s) - local ok, done = false, false -%s - return head, done -end]] - -local template_yes_nostate = [[ -%s -return function(head%s) -%s - return head, true -end]] - -local template_nop = [[ -return function() - return false, false -end]] - -function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug into tostring - local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip - local nostate = t.nostate - local vars, calls, args, n = { }, { }, nil, 0 - if nofarguments == 0 then - args = "" - elseif nofarguments == 1 then - args = ",one" - elseif nofarguments == 2 then - args = ",one,two" - elseif nofarguments == 3 then -- from here on probably slower than ... - args = ",one,two,three" - elseif nofarguments == 4 then - args = ",one,two,three,four" - elseif nofarguments == 5 then - args = ",one,two,three,four,five" - else - args = ",..." +function sequencers.nodeprocessor(t,nofarguments) + -- + local templates = nofarguments + -- + if type(templates) ~= "table" then + return "" + end + -- + local replacers = { } + for k, v in next, templates do + replacers[k] = replacer(v) + end + -- + local construct = replacers.process + local step = replacers.step + if not construct or not step then + return "" + end + -- + local calls = { } + local aliases = { } + local ncalls = 0 + local naliases = 0 + local f_alias = formatters["local %s = %s"] + -- + local list = t.list + local order = t.order + local kind = t.kind + local gskip = t.gskip + local askip = t.askip + local name = t.name or "?" + local steps = 0 + usedcount = usedcount + 1 + -- + if trace_detail then + naliases = naliases + 1 + aliases[naliases] = formatters["local report = logs.reporter('sequencer',%q)"](name) + ncalls = ncalls + 1 + calls[ncalls] = [[report("start")]] end for i=1,#order do local group = order[i] @@ -339,28 +382,47 @@ function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug for i=1,#actions do local action = actions[i] if not askip[action] then - local localized = localize(action) - n = n + 1 - vars[n] = formatters["local %s = %s"](localized,action) - -- only difference with tostring is kind and rets (why no return) - if nostate then - if kind[action] == "nohead" then - calls[n] = formatters[" %s(head%s)"](localized,args) - else - calls[n] = formatters[" head = %s(head%s)"](localized,args) - end - else - if kind[action] == "nohead" then - calls[n] = formatters[" ok = %s(head%s) if ok then done = true end"](localized,args) - else - calls[n] = formatters[" head, ok = %s(head%s) if ok then done = true end"](localized,args) - end + steps = steps + 1 + if trace_used or trace_detail then + local action = tostring(action) + report("%02i: category %a, group %a, action %a",usedcount,name,group,action) + usednames[action] = true end + if trace_detail then + ncalls = ncalls + 1 + calls[ncalls] = formatters[ [[report(" step %a, action %a")]] ](steps,tostring(action)) + end + local localized = localize(action) + local onestep = replacers[kind[action]] or step + naliases = naliases + 1 + ncalls = ncalls + 1 + aliases[naliases] = f_alias(localized,action) + calls [ncalls] = onestep { action = localized } end end end end - local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop + t.steps = steps + local processor + if steps == 0 then + processor = templates.default or construct { } + else + if trace_detail then + ncalls = ncalls + 1 + calls[ncalls] = [[report("stop")]] + end + processor = construct { + localize = concat(aliases,"\n"), + actions = concat(calls,"\n"), + } + end + -- processor = "print('running : " .. (t.name or "?") .. "')\n" .. processor -- print(processor) return processor end + +statistics.register("used sequences",function() + if next(usednames) then + return concat(sortedkeys(usednames)," ") + end +end) diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sha.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sha.lua index 3e786a834f6..d84e46975fa 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sha.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sha.lua @@ -8,6 +8,13 @@ if not modules then modules = { } end modules ['util-sha'] = { comment3 = "due to bit operators this code only works in lua(tex) 5.3", } +if sha2 then + if utilities then + utilities.sha2 = sha2 + end + return sha2 +end + -- This doesn't work in luajittex ... maybe some day it will have bit operators too. -- I'm not really in the mood for making this module aware (by compiling the -- function depending on the engine that I use but I probably won't use luajittex in @@ -277,10 +284,10 @@ digest[224] = digest[256] digest[384] = digest[512] local finalize = { - [224] = function(hash,tohex) return tohex(packstring(">I4I4I4I4I4I4I4", unpack(hash))) end, -- # 56 - [256] = function(hash,tohex) return tohex(packstring(">I4I4I4I4I4I4I4I4",unpack(hash))) end, -- # 64 - [384] = function(hash,tohex) return tohex(packstring(">I8I8I8I8I8I8", unpack(hash))) end, -- # 96 - [512] = function(hash,tohex) return tohex(packstring(">I8I8I8I8I8I8I8I8",unpack(hash))) end, -- # 128 + [224] = function(hash,tohex) local s = packstring(">I4I4I4I4I4I4I4", unpack(hash)) return tohex and tohex(s) or s end, -- # 56 + [256] = function(hash,tohex) local s = packstring(">I4I4I4I4I4I4I4I4",unpack(hash)) return tohex and tohex(s) or s end, -- # 64 + [384] = function(hash,tohex) local s = packstring(">I8I8I8I8I8I8", unpack(hash)) return tohex and tohex(s) or s end, -- # 96 + [512] = function(hash,tohex) local s = packstring(">I8I8I8I8I8I8I8I8",unpack(hash)) return tohex and tohex(s) or s end, -- # 128 } local hash = { } @@ -293,14 +300,18 @@ local function hashed(str,method,tohex) end local sha2 = { - hash224 = function(str) return hashed(str,224,tohex) end, - hash256 = function(str) return hashed(str,256,tohex) end, - hash384 = function(str) return hashed(str,384,tohex) end, - hash512 = function(str) return hashed(str,512,tohex) end, - HASH224 = function(str) return hashed(str,224,toHEX) end, - HASH256 = function(str) return hashed(str,256,toHEX) end, - HASH384 = function(str) return hashed(str,384,toHEX) end, - HASH512 = function(str) return hashed(str,512,toHEX) end, + digest224 = function(str) return hashed(str,224) end, + digest256 = function(str) return hashed(str,256) end, + digest384 = function(str) return hashed(str,384) end, + digest512 = function(str) return hashed(str,512) end, + hash224 = function(str) return hashed(str,224,tohex) end, + hash256 = function(str) return hashed(str,256,tohex) end, + hash384 = function(str) return hashed(str,384,tohex) end, + hash512 = function(str) return hashed(str,512,tohex) end, + HASH224 = function(str) return hashed(str,224,toHEX) end, + HASH256 = function(str) return hashed(str,256,toHEX) end, + HASH384 = function(str) return hashed(str,384,toHEX) end, + HASH512 = function(str) return hashed(str,512,toHEX) end, } -- local setmetatableindex = table.setmetatableindex diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-copas.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-copas.lua new file mode 100644 index 00000000000..3e66e588838 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-copas.lua @@ -0,0 +1,931 @@ +-- original file : copas.lua +-- for more into : see util-soc.lua + +local socket = socket or require("socket") +local ssl = ssl or nil -- only loaded upon demand + +local WATCH_DOG_TIMEOUT = 120 +local UDP_DATAGRAM_MAX = 8192 + +local type, next, pcall, getmetatable, tostring = type, next, pcall, getmetatable, tostring +local min, max, random = math.min, math.max, math.random +local find = string.find +local insert, remove = table.insert, table.remove + +local gettime = socket.gettime +local selectsocket = socket.select + +local createcoroutine = coroutine.create +local resumecoroutine = coroutine.resume +local yieldcoroutine = coroutine.yield +local runningcoroutine = coroutine.running + +-- Redefines LuaSocket functions with coroutine safe versions (this allows the use +-- of socket.http from within copas). + +-- Meta information is public even if beginning with an "_" + +local function report(fmt,first,...) + if logs then + report = logs and logs.reporter("copas") + report(fmt,first,...) + elseif fmt then + fmt = "copas: " .. fmt + if first then + print(format(fmt,first,...)) + else + print(fmt) + end + end +end + +local copas = { + + _COPYRIGHT = "Copyright (C) 2005-2016 Kepler Project", + _DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services", + _VERSION = "Copas 2.0.1", + + autoclose = true, + running = false, + + report = report, + +} + +local function statushandler(status, ...) + if status then + return ... + end + local err = (...) + if type(err) == "table" then + err = err[1] + end + report("error: %s",tostring(err)) + return nil, err +end + +function socket.protect(func) + return function(...) + return statushandler(pcall(func,...)) + end +end + +function socket.newtry(finalizer) + return function (...) + local status = (...) + if not status then + local detail = select(2,...) + pcall(finalizer,detail) + report("error: %s",tostring(detail)) + return + end + return ... + end +end + +-- Simple set implementation based on LuaSocket's tinyirc.lua example +-- adds a FIFO queue for each value in the set + +local function newset() + local reverse = { } + local set = { } + local queue = { } + setmetatable(set, { + __index = { + insert = + function(set, value) + if not reverse[value] then + local n = #set +1 + set[n] = value + reverse[value] = n + end + end, + remove = + function(set, value) + local index = reverse[value] + if index then + reverse[value] = nil + local n = #set + local top = set[n] + set[n] = nil + if top ~= value then + reverse[top] = index + set[index] = top + end + end + end, + push = + function (set, key, itm) + local entry = queue[key] + if entry == nil then -- hm can it be false then? + queue[key] = { itm } + else + entry[#entry + 1] = itm + end + end, + pop = + function (set, key) + local top = queue[key] + if top ~= nil then + local ret = remove(top,1) + if top[1] == nil then + queue[key] = nil + end + return ret + end + end + } + } ) + return set +end + +local _sleeping = { + times = { }, -- list with wake-up times + cos = { }, -- list with coroutines, index matches the 'times' list + lethargy = { }, -- list of coroutines sleeping without a wakeup time + + insert = + function() + end, + remove = + function() + end, + push = + function(self, sleeptime, co) + if not co then + return + end + if sleeptime < 0 then + --sleep until explicit wakeup through copas.wakeup + self.lethargy[co] = true + return + else + sleeptime = gettime() + sleeptime + end + local t = self.times + local c = self.cos + local i = 1 + local n = #t + while i <= n and t[i] <= sleeptime do + i = i + 1 + end + insert(t,i,sleeptime) + insert(c,i,co) + end, + getnext = + -- returns delay until next sleep expires, or nil if there is none + function(self) + local t = self.times + local delay = t[1] and t[1] - gettime() or nil + return delay and max(delay, 0) or nil + end, + pop = + -- find the thread that should wake up to the time + function(self, time) + local t = self.times + local c = self.cos + if #t == 0 or time < t[1] then + return + end + local co = c[1] + remove(t,1) + remove(c,1) + return co + end, + wakeup = + function(self, co) + local let = self.lethargy + if let[co] then + self:push(0, co) + let[co] = nil + else + local c = self.cos + local t = self.times + for i=1,#c do + if c[i] == co then + remove(c,i) + remove(t,i) + self:push(0, co) + return + end + end + end + end +} + +local _servers = newset() -- servers being handled +local _reading = newset() -- sockets currently being read +local _writing = newset() -- sockets currently being written + +local _reading_log = { } +local _writing_log = { } + +local _is_timeout = { -- set of errors indicating a timeout + timeout = true, -- default LuaSocket timeout + wantread = true, -- LuaSec specific timeout + wantwrite = true, -- LuaSec specific timeout +} + +-- Coroutine based socket I/O functions. + +local function isTCP(socket) + return not find(tostring(socket),"^udp") +end + +-- Reads a pattern from a client and yields to the reading set on timeouts UDP: a +-- UDP socket expects a second argument to be a number, so it MUST be provided as +-- the 'pattern' below defaults to a string. Will throw a 'bad argument' error if +-- omitted. + +local function copasreceive(client, pattern, part) + if not pattern or pattern == "" then + pattern = "*l" + end + local current_log = _reading_log + local s, err + repeat + s, err, part = client:receive(pattern, part) + if s or (not _is_timeout[err]) then + current_log[client] = nil + return s, err, part + end + if err == "wantwrite" then + current_log = _writing_log + current_log[client] = gettime() + yieldcoroutine(client, _writing) + else + current_log = _reading_log + current_log[client] = gettime() + yieldcoroutine(client, _reading) + end + until false +end + +-- Receives data from a client over UDP. Not available for TCP. (this is a copy of +-- receive() method, adapted for receivefrom() use). + +local function copasreceivefrom(client, size) + local s, err, port + if not size or size == 0 then + size = UDP_DATAGRAM_MAX + end + repeat + -- upon success err holds ip address + s, err, port = client:receivefrom(size) + if s or err ~= "timeout" then + _reading_log[client] = nil + return s, err, port + end + _reading_log[client] = gettime() + yieldcoroutine(client, _reading) + until false +end + +-- Same as above but with special treatment when reading chunks, unblocks on any +-- data received. + +local function copasreceivepartial(client, pattern, part) + if not pattern or pattern == "" then + pattern = "*l" + end + local logger = _reading_log + local queue = _reading + local s, err + repeat + s, err, part = client:receive(pattern, part) + if s or (type(pattern) == "number" and part ~= "" and part) or not _is_timeout[err] then + logger[client] = nil + return s, err, part + end + if err == "wantwrite" then + logger = _writing_log + queue = _writing + else + logger = _reading_log + queue = _reading + end + logger[client] = gettime() + yieldcoroutine(client, queue) + until false +end + +-- Sends data to a client. The operation is buffered and yields to the writing set +-- on timeouts Note: from and to parameters will be ignored by/for UDP sockets + +local function copassend(client, data, from, to) + if not from then + from = 1 + end + local lastIndex = from - 1 + local logger = _writing_log + local queue = _writing + local s, err + repeat + s, err, lastIndex = client:send(data, lastIndex + 1, to) + -- Adds extra coroutine swap and garantees that high throughput doesn't take + -- other threads to starvation. + if random(100) > 90 then + logger[client] = gettime() + yieldcoroutine(client, queue) + end + if s or not _is_timeout[err] then + logger[client] = nil + return s, err,lastIndex + end + if err == "wantread" then + logger = _reading_log + queue = _reading + else + logger = _writing_log + queue = _writing + end + logger[client] = gettime() + yieldcoroutine(client, queue) + until false +end + +-- Sends data to a client over UDP. Not available for TCP. (this is a copy of send() +-- method, adapted for sendto() use). + +local function copassendto(client, data, ip, port) + repeat + local s, err = client:sendto(data, ip, port) + -- Adds extra coroutine swap and garantees that high throughput doesn't + -- take other threads to starvation. + if random(100) > 90 then + _writing_log[client] = gettime() + yieldcoroutine(client, _writing) + end + if s or err ~= "timeout" then + _writing_log[client] = nil + return s, err + end + _writing_log[client] = gettime() + yieldcoroutine(client, _writing) + until false +end + +-- Waits until connection is completed. + +local function copasconnect(skt, host, port) + skt:settimeout(0) + local ret, err, tried_more_than_once + repeat + ret, err = skt:connect (host, port) + -- A non-blocking connect on Windows results in error "Operation already in + -- progress" to indicate that it is completing the request async. So + -- essentially it is the same as "timeout". + if ret or (err ~= "timeout" and err ~= "Operation already in progress") then + -- Once the async connect completes, Windows returns the error "already + -- connected" to indicate it is done, so that error should be ignored. + -- Except when it is the first call to connect, then it was already + -- connected to something else and the error should be returned. + if not ret and err == "already connected" and tried_more_than_once then + ret = 1 + err = nil + end + _writing_log[skt] = nil + return ret, err + end + tried_more_than_once = tried_more_than_once or true + _writing_log[skt] = gettime() + yieldcoroutine(skt, _writing) + until false +end + +-- Peforms an (async) ssl handshake on a connected TCP client socket. Replacec all +-- previous socket references, with the returned new ssl wrapped socket Throws error +-- and does not return nil+error, as that might silently fail in code like this. + +local function copasdohandshake(skt, sslt) -- extra ssl parameters + if not ssl then + ssl = require("ssl") + end + if not ssl then + report("error: no ssl library") + return + end + local nskt, err = ssl.wrap(skt, sslt) + if not nskt then + report("error: %s",tostring(err)) + return + end + nskt:settimeout(0) + local queue + repeat + local success, err = nskt:dohandshake() + if success then + return nskt + elseif err == "wantwrite" then + queue = _writing + elseif err == "wantread" then + queue = _reading + else + report("error: %s",tostring(err)) + return + end + yieldcoroutine(nskt, queue) + until false +end + +-- Flushes a client write buffer. + +local function copasflush(client) +end + +-- Public. + +copas.connect = copassconnect +copas.send = copassend +copas.sendto = copassendto +copas.receive = copasreceive +copas.receivefrom = copasreceivefrom +copas.copasreceivepartial = copasreceivepartial +copas.copasreceivePartial = copasreceivepartial +copas.dohandshake = copasdohandshake +copas.flush = copasflush + +-- Wraps a TCP socket to use Copas methods (send, receive, flush and settimeout). + +local function _skt_mt_tostring(self) + return tostring(self.socket) .. " (copas wrapped)" +end + +local _skt_mt_tcp_index = { + send = + function(self, data, from, to) + return copassend (self.socket, data, from, to) + end, + receive = + function (self, pattern, prefix) + if self.timeout == 0 then + return copasreceivePartial(self.socket, pattern, prefix) + else + return copasreceive(self.socket, pattern, prefix) + end + end, + + flush = + function (self) + return copasflush(self.socket) + end, + + settimeout = + function (self, time) + self.timeout = time + return true + end, + -- TODO: socket.connect is a shortcut, and must be provided with an alternative + -- if ssl parameters are available, it will also include a handshake + connect = + function(self, ...) + local res, err = copasconnect(self.socket, ...) + if res and self.ssl_params then + res, err = self:dohandshake() + end + return res, err + end, + close = + function(self, ...) + return self.socket:close(...) + end, + -- TODO: socket.bind is a shortcut, and must be provided with an alternative + bind = + function(self, ...) + return self.socket:bind(...) + end, + -- TODO: is this DNS related? hence blocking? + getsockname = + function(self, ...) + return self.socket:getsockname(...) + end, + getstats = + function(self, ...) + return self.socket:getstats(...) + end, + setstats = + function(self, ...) + return self.socket:setstats(...) + end, + listen = + function(self, ...) + return self.socket:listen(...) + end, + accept = + function(self, ...) + return self.socket:accept(...) + end, + setoption = + function(self, ...) + return self.socket:setoption(...) + end, + -- TODO: is this DNS related? hence blocking? + getpeername = + function(self, ...) + return self.socket:getpeername(...) + end, + shutdown = + function(self, ...) + return self.socket:shutdown(...) + end, + dohandshake = + function(self, sslt) + self.ssl_params = sslt or self.ssl_params + local nskt, err = copasdohandshake(self.socket, self.ssl_params) + if not nskt then + return nskt, err + end + self.socket = nskt + return self + end, +} + +local _skt_mt_tcp = { + __tostring = _skt_mt_tostring, + __index = _skt_mt_tcp_index, +} + +-- wraps a UDP socket, copy of TCP one adapted for UDP. + +local _skt_mt_udp_index = { + -- UDP sending is non-blocking, but we provide starvation prevention, so replace + -- anyway. + sendto = + function (self, ...) + return copassendto(self.socket,...) + end, + receive = + function (self, size) + return copasreceive(self.socket, size or UDP_DATAGRAM_MAX) + end, + receivefrom = + function (self, size) + return copasreceivefrom(self.socket, size or UDP_DATAGRAM_MAX) + end, + -- TODO: is this DNS related? hence blocking? + setpeername = + function(self, ...) + return self.socket:getpeername(...) + end, + setsockname = + function(self, ...) + return self.socket:setsockname(...) + end, + -- do not close client, as it is also the server for udp. + close = + function(self, ...) + return true + end +} + +local _skt_mt_udp = { + __tostring = _skt_mt_tostring, + __index = _skt_mt_udp_index, +} + +for k, v in next, _skt_mt_tcp_index do + if not _skt_mt_udp_index[k] then + _skt_mt_udp_index[k] = v + end +end + +-- Wraps a LuaSocket socket object in an async Copas based socket object. + +-- @param skt the socket to wrap +-- @sslt (optional) Table with ssl parameters, use an empty table to use ssl with defaults +-- @return wrapped socket object + +local function wrap(skt, sslt) + if getmetatable(skt) == _skt_mt_tcp or getmetatable(skt) == _skt_mt_udp then + return skt -- already wrapped + end + skt:settimeout(0) + if isTCP(skt) then + return setmetatable ({ socket = skt, ssl_params = sslt }, _skt_mt_tcp) + else + return setmetatable ({ socket = skt }, _skt_mt_udp) + end +end + +copas.wrap = wrap + +-- Wraps a handler in a function that deals with wrapping the socket and doing +-- the optional ssl handshake. + +function copas.handler(handler, sslparams) + return function (skt,...) + skt = wrap(skt) + if sslparams then + skt:dohandshake(sslparams) + end + return handler(skt,...) + end +end + +-- Error handling (a handler per coroutine). + +local _errhandlers = { } + +function copas.setErrorHandler(err) + local co = runningcoroutine() + if co then + _errhandlers[co] = err + end +end + +local function _deferror (msg, co, skt) + report("%s (%s) (%s)", msg, tostring(co), tostring(skt)) +end + +-- Thread handling + +local function _doTick (co, skt, ...) + if not co then + return + end + + local ok, res, new_q = resumecoroutine(co, skt, ...) + + if ok and res and new_q then + new_q:insert(res) + new_q:push(res, co) + else + if not ok then + pcall(_errhandlers[co] or _deferror, res, co, skt) + end + -- Do not auto-close UDP sockets, as the handler socket is also the server socket. + if skt and copas.autoclose and isTCP(skt) then + skt:close() + end + _errhandlers[co] = nil + end +end + +-- Accepts a connection on socket input. + +local function _accept(input, handler) + local client = input:accept() + if client then + client:settimeout(0) + local co = createcoroutine(handler) + _doTick (co, client) + -- _reading:insert(client) + end + return client +end + +-- Handle threads on a queue. + +local function _tickRead(skt) + _doTick(_reading:pop(skt), skt) +end + +local function _tickWrite(skt) + _doTick(_writing:pop(skt), skt) +end + +-- Adds a server/handler pair to Copas dispatcher. + +local function addTCPserver(server, handler, timeout) + server:settimeout(timeout or 0) + _servers[server] = handler + _reading:insert(server) +end + +local function addUDPserver(server, handler, timeout) + server:settimeout(timeout or 0) + local co = createcoroutine(handler) + _reading:insert(server) + _doTick(co, server) +end + +function copas.addserver(server, handler, timeout) + if isTCP(server) then + addTCPserver(server, handler, timeout) + else + addUDPserver(server, handler, timeout) + end +end + +function copas.removeserver(server, keep_open) + local s = server + local mt = getmetatable(server) + if mt == _skt_mt_tcp or mt == _skt_mt_udp then + s = server.socket + end + _servers[s] = nil + _reading:remove(s) + if keep_open then + return true + end + return server:close() +end + +-- Adds an new coroutine thread to Copas dispatcher. Create a coroutine that skips +-- the first argument, which is always the socket passed by the scheduler, but `nil` +-- in case of a task/thread + +function copas.addthread(handler, ...) + local thread = createcoroutine(function(_, ...) return handler(...) end) + _doTick(thread, nil, ...) + return thread +end + +-- tasks registering + +local _tasks = { } + +-- Lets tasks call the default _tick(). + +local function addtaskRead(task) + task.def_tick = _tickRead + _tasks[task] = true +end + +-- Lets tasks call the default _tick(). + +local function addtaskWrite(task) + task.def_tick = _tickWrite + _tasks[task] = true +end + +local function tasks() + return next, _tasks +end + +-- A task to check ready to read events. + +local _readable_t = { + events = + function(self) + local i = 0 + return function () + i = i + 1 + return self._evs[i] + end + end, + tick = + function(self, input) + local handler = _servers[input] + if handler then + input = _accept(input, handler) + else + _reading:remove(input) + self.def_tick(input) + end + end +} + +addtaskRead(_readable_t) + +-- A task to check ready to write events. + +local _writable_t = { + events = + function(self) + local i = 0 + return function() + i = i + 1 + return self._evs[i] + end + end, + tick = + function(self, output) + _writing:remove(output) + self.def_tick(output) + end +} + +addtaskWrite(_writable_t) + +--sleeping threads task + +local _sleeping_t = { + tick = function(self, time, ...) + _doTick(_sleeping:pop(time), ...) + end +} + +-- yields the current coroutine and wakes it after 'sleeptime' seconds. +-- If sleeptime<0 then it sleeps until explicitly woken up using 'wakeup' +function copas.sleep(sleeptime) + yieldcoroutine((sleeptime or 0), _sleeping) +end + +-- Wakes up a sleeping coroutine 'co'. + +function copas.wakeup(co) + _sleeping:wakeup(co) +end + +-- Checks for reads and writes on sockets + +local last_cleansing = 0 + +local function _select(timeout) + + local now = gettime() + + local r_evs, w_evs, err = selectsocket(_reading, _writing, timeout) + + _readable_t._evs = r_evs + _writable_t._evs = w_evs + + if (last_cleansing - now) > WATCH_DOG_TIMEOUT then + + last_cleansing = now + + -- Check all sockets selected for reading, and check how long they have been + -- waiting for data already, without select returning them as readable. + + for skt, time in next, _reading_log do + + if not r_evs[skt] and (time - now) > WATCH_DOG_TIMEOUT then + + -- This one timedout while waiting to become readable, so move it in + -- the readable list and try and read anyway, despite not having + -- been returned by select. + + local n = #r_evs + 1 + _reading_log[skt] = nil + r_evs[n] = skt + r_evs[skt] = n + end + end + + -- Do the same for writing. + + for skt, time in next, _writing_log do + if not w_evs[skt] and (time - now) > WATCH_DOG_TIMEOUT then + local n = #w_evs + 1 + _writing_log[skt] = nil + w_evs[n] = skt + w_evs[skt] = n + end + end + + end + + if err == "timeout" and #r_evs + #w_evs > 0 then + return nil + else + return err + end + +end + +-- Check whether there is something to do. It returns false if there are no sockets +-- for read/write nor tasks scheduled (which means Copas is in an empty spin). + +local function copasfinished() + return not (next(_reading) or next(_writing) or _sleeping:getnext()) +end + +-- Dispatcher loop step. It listens to client requests and handles them and returns +-- false if no data was handled (timeout), or true if there was data handled (or nil +-- + error message). + +local function copasstep(timeout) + _sleeping_t:tick(gettime()) + + local nextwait = _sleeping:getnext() + if nextwait then + timeout = timeout and min(nextwait,timeout) or nextwait + elseif copasfinished() then + return false + end + + local err = _select(timeout) + if err then + if err == "timeout" then + return false + end + return nil, err + end + + for task in tasks() do + for event in task:events() do + task:tick(event) + end + end + return true +end + +copas.finished = copasfinished +copas.step = copasstep + +-- Dispatcher endless loop. It listens to client requests and handles them forever. + +function copas.loop(timeout) + copas.running = true + while not copasfinished() do + copasstep(timeout) + end + copas.running = false +end + +-- _G.copas = copas + +package.loaded["copas"] = copas + +return copas diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ftp.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ftp.lua new file mode 100644 index 00000000000..124c8d4ee71 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ftp.lua @@ -0,0 +1,402 @@ +-- original file : ftp.lua +-- for more into : see util-soc.lua + +local setmetatable, type, next = setmetatable, type, next +local find, format, gsub, match = string.find, string.format, string.gsub, string.match +local concat = table.concat +local mod = math.mod + +local socket = socket or require("socket") +local url = socket.url or require("socket.url") +local tp = socket.tp or require("socket.tp") +local ltn12 = ltn12 or require("ltn12") + +local tcpsocket = socket.tcp +local trysocket = socket.try +local skipsocket = socket.skip +local sinksocket = socket.sink +local selectsocket = socket.select +local bindsocket = socket.bind +local newtrysocket = socket.newtry +local sourcesocket = socket.source +local protectsocket = socket.protect + +local parseurl = url.parse +local unescapeurl = url.unescape + +local pumpall = ltn12.pump.all +local pumpstep = ltn12.pump.step +local sourcestring = ltn12.source.string +local sinktable = ltn12.sink.table + +local ftp = { + TIMEOUT = 60, + USER = "ftp", + PASSWORD = "anonymous@anonymous.org", +} + +socket.ftp = ftp + +local PORT = 21 + +local methods = { } +local mt = { __index = methods } + +function ftp.open(server, port, create) + local tp = trysocket(tp.connect(server, port or PORT, ftp.TIMEOUT, create)) + local f = setmetatable({ tp = tp }, metat) + f.try = newtrysocket(function() f:close() end) + return f +end + +function methods.portconnect(self) + local try = self.try + local server = self.server + try(server:settimeout(ftp.TIMEOUT)) + self.data = try(server:accept()) + try(self.data:settimeout(ftp.TIMEOUT)) +end + +function methods.pasvconnect(self) + local try = self.try + self.data = try(tcpsocket()) + self(self.data:settimeout(ftp.TIMEOUT)) + self(self.data:connect(self.pasvt.address, self.pasvt.port)) +end + +function methods.login(self, user, password) + local try = self.try + local tp = self.tp + try(tp:command("user", user or ftp.USER)) + local code, reply = try(tp:check{"2..", 331}) + if code == 331 then + try(tp:command("pass", password or ftp.PASSWORD)) + try(tp:check("2..")) + end + return 1 +end + +function methods.pasv(self) + local try = self.try + local tp = self.tp + try(tp:command("pasv")) + local code, reply = try(self.tp:check("2..")) + local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" + local a, b, c, d, p1, p2 = skipsocket(2, find(reply, pattern)) + try(a and b and c and d and p1 and p2, reply) + local address = format("%d.%d.%d.%d", a, b, c, d) + local port = p1*256 + p2 + local server = self.server + self.pasvt = { + address = address, + port = port, + } + if server then + server:close() + self.server = nil + end + return address, port +end + +function methods.epsv(self) + local try = self.try + local tp = self.tp + try(tp:command("epsv")) + local code, reply = try(tp:check("229")) + local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)" + local d, prt, address, port = match(reply, pattern) + try(port, "invalid epsv response") + local address = tp:getpeername() + local server = self.server + self.pasvt = { + address = address, + port = port, + } + if self.server then + server:close() + self.server = nil + end + return address, port +end + +function methods.port(self, address, port) + local try = self.try + local tp = self.tp + self.pasvt = nil + if not address then + address, port = try(tp:getsockname()) + self.server = try(bindsocket(address, 0)) + address, port = try(self.server:getsockname()) + try(self.server:settimeout(ftp.TIMEOUT)) + end + local pl = mod(port,256) + local ph = (port - pl)/256 + local arg = gsub(format("%s,%d,%d", address, ph, pl), "%.", ",") + try(tp:command("port", arg)) + try(tp:check("2..")) + return 1 +end + +function methods.eprt(self, family, address, port) + local try = self.try + local tp = self.tp + self.pasvt = nil + if not address then + address, port = try(tp:getsockname()) + self.server = try(bindsocket(address, 0)) + address, port = try(self.server:getsockname()) + try(self.server:settimeout(ftp.TIMEOUT)) + end + local arg = format("|%s|%s|%d|", family, address, port) + try(tp:command("eprt", arg)) + try(tp:check("2..")) + return 1 +end + +function methods.send(self, sendt) + local try = self.try + local tp = self.tp + -- so we try a table or string ? + try(self.pasvt or self.server, "need port or pasv first") + if self.pasvt then + self:pasvconnect() + end + local argument = sendt.argument or unescapeurl(gsub(sendt.path or "", "^[/\\]", "")) + if argument == "" then + argument = nil + end + local command = sendt.command or "stor" + try(tp:command(command, argument)) + local code, reply = try(tp:check{"2..", "1.."}) + if not self.pasvt then + self:portconnect() + end + local step = sendt.step or pumpstep + local readt = { tp } + local checkstep = function(src, snk) + local readyt = selectsocket(readt, nil, 0) + if readyt[tp] then + code = try(tp:check("2..")) + end + return step(src, snk) + end + local sink = sinksocket("close-when-done", self.data) + try(pumpall(sendt.source, sink, checkstep)) + if find(code, "1..") then + try(tp:check("2..")) + end + self.data:close() + local sent = skipsocket(1, self.data:getstats()) + self.data = nil + return sent +end + +function methods.receive(self, recvt) + local try = self.try + local tp = self.tp + try(self.pasvt or self.server, "need port or pasv first") + if self.pasvt then self:pasvconnect() end + local argument = recvt.argument or unescapeurl(gsub(recvt.path or "", "^[/\\]", "")) + if argument == "" then + argument = nil + end + local command = recvt.command or "retr" + try(tp:command(command, argument)) + local code,reply = try(tp:check{"1..", "2.."}) + if code >= 200 and code <= 299 then + recvt.sink(reply) + return 1 + end + if not self.pasvt then + self:portconnect() + end + local source = sourcesocket("until-closed", self.data) + local step = recvt.step or pumpstep + try(pumpall(source, recvt.sink, step)) + if find(code, "1..") then + try(tp:check("2..")) + end + self.data:close() + self.data = nil + return 1 +end + +function methods.cwd(self, dir) + local try = self.try + local tp = self.tp + try(tp:command("cwd", dir)) + try(tp:check(250)) + return 1 +end + +function methods.type(self, typ) + local try = self.try + local tp = self.tp + try(tp:command("type", typ)) + try(tp:check(200)) + return 1 +end + +function methods.greet(self) + local try = self.try + local tp = self.tp + local code = try(tp:check{"1..", "2.."}) + if find(code, "1..") then + try(tp:check("2..")) + end + return 1 +end + +function methods.quit(self) + local try = self.try + try(self.tp:command("quit")) + try(self.tp:check("2..")) + return 1 +end + +function methods.close(self) + local data = self.data + if data then + data:close() + end + local server = self.server + if server then + server:close() + end + local tp = self.tp + if tp then + tp:close() + end +end + +local function override(t) + if t.url then + local u = parseurl(t.url) + for k, v in next, t do + u[k] = v + end + return u + else + return t + end +end + +local function tput(putt) + putt = override(putt) + local host = putt.host + trysocket(host, "missing hostname") + local f = ftp.open(host, putt.port, putt.create) + f:greet() + f:login(putt.user, putt.password) + local typ = putt.type + if typ then + f:type(typ) + end + f:epsv() + local sent = f:send(putt) + f:quit() + f:close() + return sent +end + +local default = { + path = "/", + scheme = "ftp", +} + +local function genericform(u) + local t = trysocket(parseurl(u, default)) + trysocket(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") + trysocket(t.host, "missing hostname") + local pat = "^type=(.)$" + if t.params then + local typ = skipsocket(2, find(t.params, pat)) + t.type = typ + trysocket(typ == "a" or typ == "i", "invalid type '" .. typ .. "'") + end + return t +end + +ftp.genericform = genericform + +local function sput(u, body) + local putt = genericform(u) + putt.source = sourcestring(body) + return tput(putt) +end + +ftp.put = protectsocket(function(putt, body) + if type(putt) == "string" then + return sput(putt, body) + else + return tput(putt) + end +end) + +local function tget(gett) + gett = override(gett) + local host = gett.host + trysocket(host, "missing hostname") + local f = ftp.open(host, gett.port, gett.create) + f:greet() + f:login(gett.user, gett.password) + if gett.type then + f:type(gett.type) + end + f:epsv() + f:receive(gett) + f:quit() + return f:close() +end + +local function sget(u) + local gett = genericform(u) + local t = { } + gett.sink = sinktable(t) + tget(gett) + return concat(t) +end + +ftp.command = protectsocket(function(cmdt) + cmdt = override(cmdt) + local command = cmdt.command + local argument = cmdt.argument + local check = cmdt.check + local host = cmdt.host + trysocket(host, "missing hostname") + trysocket(command, "missing command") + local f = ftp.open(host, cmdt.port, cmdt.create) + local try = f.try + local tp = f.tp + f:greet() + f:login(cmdt.user, cmdt.password) + if type(command) == "table" then + local argument = argument or { } + for i=1,#command do + local cmd = command[i] + try(tp:command(cmd, argument[i])) + if check and check[i] then + try(tp:check(check[i])) + end + end + else + try(tp:command(command, argument)) + if check then + try(tp:check(check)) + end + end + f:quit() + return f:close() +end) + +ftp.get = protectsocket(function(gett) + if type(gett) == "string" then + return sget(gett) + else + return tget(gett) + end +end) + +package.loaded["socket.ftp"] = ftp + +return ftp diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-headers.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-headers.lua new file mode 100644 index 00000000000..ef51910a5f3 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-headers.lua @@ -0,0 +1,145 @@ +-- original file : headers.lua +-- for more into : see util-soc.lua + +local next = next +local lower = string.lower +local concat = table.concat + +local socket = socket or require("socket") + +local headers = { } +socket.headers = headers + +local canonic = { + ["accept"] = "Accept", + ["accept-charset"] = "Accept-Charset", + ["accept-encoding"] = "Accept-Encoding", + ["accept-language"] = "Accept-Language", + ["accept-ranges"] = "Accept-Ranges", + ["action"] = "Action", + ["alternate-recipient"] = "Alternate-Recipient", + ["age"] = "Age", + ["allow"] = "Allow", + ["arrival-date"] = "Arrival-Date", + ["authorization"] = "Authorization", + ["bcc"] = "Bcc", + ["cache-control"] = "Cache-Control", + ["cc"] = "Cc", + ["comments"] = "Comments", + ["connection"] = "Connection", + ["content-description"] = "Content-Description", + ["content-disposition"] = "Content-Disposition", + ["content-encoding"] = "Content-Encoding", + ["content-id"] = "Content-ID", + ["content-language"] = "Content-Language", + ["content-length"] = "Content-Length", + ["content-location"] = "Content-Location", + ["content-md5"] = "Content-MD5", + ["content-range"] = "Content-Range", + ["content-transfer-encoding"] = "Content-Transfer-Encoding", + ["content-type"] = "Content-Type", + ["cookie"] = "Cookie", + ["date"] = "Date", + ["diagnostic-code"] = "Diagnostic-Code", + ["dsn-gateway"] = "DSN-Gateway", + ["etag"] = "ETag", + ["expect"] = "Expect", + ["expires"] = "Expires", + ["final-log-id"] = "Final-Log-ID", + ["final-recipient"] = "Final-Recipient", + ["from"] = "From", + ["host"] = "Host", + ["if-match"] = "If-Match", + ["if-modified-since"] = "If-Modified-Since", + ["if-none-match"] = "If-None-Match", + ["if-range"] = "If-Range", + ["if-unmodified-since"] = "If-Unmodified-Since", + ["in-reply-to"] = "In-Reply-To", + ["keywords"] = "Keywords", + ["last-attempt-date"] = "Last-Attempt-Date", + ["last-modified"] = "Last-Modified", + ["location"] = "Location", + ["max-forwards"] = "Max-Forwards", + ["message-id"] = "Message-ID", + ["mime-version"] = "MIME-Version", + ["original-envelope-id"] = "Original-Envelope-ID", + ["original-recipient"] = "Original-Recipient", + ["pragma"] = "Pragma", + ["proxy-authenticate"] = "Proxy-Authenticate", + ["proxy-authorization"] = "Proxy-Authorization", + ["range"] = "Range", + ["received"] = "Received", + ["received-from-mta"] = "Received-From-MTA", + ["references"] = "References", + ["referer"] = "Referer", + ["remote-mta"] = "Remote-MTA", + ["reply-to"] = "Reply-To", + ["reporting-mta"] = "Reporting-MTA", + ["resent-bcc"] = "Resent-Bcc", + ["resent-cc"] = "Resent-Cc", + ["resent-date"] = "Resent-Date", + ["resent-from"] = "Resent-From", + ["resent-message-id"] = "Resent-Message-ID", + ["resent-reply-to"] = "Resent-Reply-To", + ["resent-sender"] = "Resent-Sender", + ["resent-to"] = "Resent-To", + ["retry-after"] = "Retry-After", + ["return-path"] = "Return-Path", + ["sender"] = "Sender", + ["server"] = "Server", + ["smtp-remote-recipient"] = "SMTP-Remote-Recipient", + ["status"] = "Status", + ["subject"] = "Subject", + ["te"] = "TE", + ["to"] = "To", + ["trailer"] = "Trailer", + ["transfer-encoding"] = "Transfer-Encoding", + ["upgrade"] = "Upgrade", + ["user-agent"] = "User-Agent", + ["vary"] = "Vary", + ["via"] = "Via", + ["warning"] = "Warning", + ["will-retry-until"] = "Will-Retry-Until", + ["www-authenticate"] = "WWW-Authenticate", + ["x-mailer"] = "X-Mailer", +} + +headers.canonic = setmetatable(canonic, { + __index = function(t,k) + socket.report("invalid header: %s",k) + t[k] = k + return k + end +}) + +function headers.normalize(headers) + if not headers then + return { } + end + local normalized = { } + for k, v in next, headers do + normalized[#normalized+1] = canonic[k] .. ": " .. v + end + normalized[#normalized+1] = "" + normalized[#normalized+1] = "" + return concat(normalized,"\r\n") +end + +function headers.lower(lowered,headers) + if not lowered then + return { } + end + if not headers then + lowered, headers = { }, lowered + end + for k, v in next, headers do + lowered[lower(k)] = v + end + return lowered +end + +socket.headers = headers + +package.loaded["socket.headers"] = headers + +return headers diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-http.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-http.lua new file mode 100644 index 00000000000..c3a28be822a --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-http.lua @@ -0,0 +1,436 @@ +-- original file : http.lua +-- for more into : see util-soc.lua + +local tostring, tonumber, setmetatable, next, type = tostring, tonumber, setmetatable, next, type +local find, lower, format, gsub, match = string.find, string.lower, string.format, string.gsub, string.match +local concat = table.concat + +local socket = socket or require("socket") +local url = socket.url or require("socket.url") +local ltn12 = ltn12 or require("ltn12") +local mime = mime or require("mime") +local headers = socket.headers or require("socket.headers") + +local normalizeheaders = headers.normalize + +local parseurl = url.parse +local buildurl = url.build +local absoluteurl = url.absolute +local unescapeurl = url.unescape + +local skipsocket = socket.skip +local sinksocket = socket.sink +local sourcesocket = socket.source +local trysocket = socket.try +local tcpsocket = socket.tcp +local newtrysocket = socket.newtry +local protectsocket = socket.protect + +local emptysource = ltn12.source.empty +local stringsource = ltn12.source.string +local rewindsource = ltn12.source.rewind +local pumpstep = ltn12.pump.step +local pumpall = ltn12.pump.all +local sinknull = ltn12.sink.null +local sinktable = ltn12.sink.table + +local lowerheaders = headers.lower + +local mimeb64 = mime.b64 + +-- todo: localize ltn12 + +local http = { + TIMEOUT = 60, -- connection timeout in seconds + USERAGENT = socket._VERSION, -- user agent field sent in request +} + +socket.http = http + +local PORT = 80 +local SCHEMES = { + http = true, +} + +-- Reads MIME headers from a connection, unfolding where needed + +local function receiveheaders(sock, headers) + if not headers then + headers = { } + end + -- get first line + local line, err = sock:receive() + if err then + return nil, err + end + -- headers go until a blank line is found + while line ~= "" do + -- get field-name and value + local name, value = skipsocket(2, find(line, "^(.-):%s*(.*)")) + if not (name and value) then + return nil, "malformed reponse headers" + end + name = lower(name) + -- get next line (value might be folded) + line, err = sock:receive() + if err then + return nil, err + end + -- unfold any folded values + while find(line, "^%s") do + value = value .. line + line = sock:receive() + if err then + return nil, err + end + end + -- save pair in table + local found = headers[name] + if found then + value = found .. ", " .. value + end + headers[name] = value + end + return headers +end + +-- Extra sources and sinks + +socket.sourcet["http-chunked"] = function(sock, headers) + return setmetatable ( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, { + __call = function() + local line, err = sock:receive() + if err then + return nil, err + end + local size = tonumber(gsub(line, ";.*", ""), 16) + if not size then + return nil, "invalid chunk size" + end + if size > 0 then + local chunk, err, part = sock:receive(size) + if chunk then + sock:receive() + end + return chunk, err + else + headers, err = receiveheaders(sock, headers) + if not headers then + return nil, err + end + end + end + } + ) +end + +socket.sinkt["http-chunked"] = function(sock) + return setmetatable( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, + { + __call = function(self, chunk, err) + if not chunk then + chunk = "" + end + return sock:send(format("%X\r\n%s\r\n",#chunk,chunk)) + end + }) +end + +-- Low level HTTP API + +local methods = { } +local mt = { __index = methods } + +local function openhttp(host, port, create) + local c = trysocket((create or tcpsocket)()) + local h = setmetatable({ c = c }, mt) + local try = newtrysocket(function() h:close() end) + h.try = try + try(c:settimeout(http.TIMEOUT)) + try(c:connect(host, port or PORT)) + return h +end + +http.open = openhttp + +function methods.sendrequestline(self, method, uri) + local requestline = format("%s %s HTTP/1.1\r\n", method or "GET", uri) + return self.try(self.c:send(requestline)) +end + +function methods.sendheaders(self,headers) + self.try(self.c:send(normalizeheaders(headers))) + return 1 +end + +function methods.sendbody(self, headers, source, step) + if not source then + source = emptysource() + end + if not step then + step = pumpstep + end + local mode = "http-chunked" + if headers["content-length"] then + mode = "keep-open" + end + return self.try(pumpall(source, sinksocket(mode, self.c), step)) +end + +function methods.receivestatusline(self) + local try = self.try + local status = try(self.c:receive(5)) + if status ~= "HTTP/" then + return nil, status -- HTTP/0.9 + end + status = try(self.c:receive("*l", status)) + local code = skipsocket(2, find(status, "HTTP/%d*%.%d* (%d%d%d)")) + return try(tonumber(code), status) +end + +function methods.receiveheaders(self) + return self.try(receiveheaders(self.c)) +end + +function methods.receivebody(self, headers, sink, step) + if not sink then + sink = sinknull() + end + if not step then + step = pumpstep + end + local length = tonumber(headers["content-length"]) + local encoding = headers["transfer-encoding"] -- shortcut + local mode = "default" -- connection close + if encoding and encoding ~= "identity" then + mode = "http-chunked" + elseif length then + mode = "by-length" + end + --hh: so length can be nil + return self.try(pumpall(sourcesocket(mode, self.c, length), sink, step)) +end + +function methods.receive09body(self, status, sink, step) + local source = rewindsource(sourcesocket("until-closed", self.c)) + source(status) + return self.try(pumpall(source, sink, step)) +end + +function methods.close(self) + return self.c:close() +end + +-- High level HTTP API + +local function adjusturi(request) + if not request.proxy and not http.PROXY then + request = { + path = trysocket(request.path, "invalid path 'nil'"), + params = request.params, + query = request.query, + fragment = request.fragment, + } + end + return buildurl(request) +end + +local function adjustheaders(request) + local headers = { + ["user-agent"] = http.USERAGENT, + ["host"] = gsub(request.authority, "^.-@", ""), + ["connection"] = "close, TE", + ["te"] = "trailers" + } + local username = request.user + local password = request.password + if username and password then + headers["authorization"] = "Basic " .. (mimeb64(username .. ":" .. unescapeurl(password))) + end + local proxy = request.proxy or http.PROXY + if proxy then + proxy = parseurl(proxy) + local username = proxy.user + local password = proxy.password + if username and password then + headers["proxy-authorization"] = "Basic " .. (mimeb64(username .. ":" .. password)) + end + end + local requestheaders = request.headers + if requestheaders then + headers = lowerheaders(headers,requestheaders) + end + return headers +end + +-- default url parts + +local default = { + host = "", + port = PORT, + path = "/", + scheme = "http" +} + +local function adjustrequest(originalrequest) + local url = originalrequest.url + local request = url and parseurl(url,default) or { } + for k, v in next, originalrequest do + request[k] = v + end + local host = request.host + local port = request.port + local uri = request.uri + if not host or host == "" then + trysocket(nil, "invalid host '" .. tostring(host) .. "'") + end + if port == "" then + request.port = PORT + end + if not uri or uri == "" then + request.uri = adjusturi(request) + end + request.headers = adjustheaders(request) + local proxy = request.proxy or http.PROXY + if proxy then + proxy = parseurl(proxy) + request.host = proxy.host + request.port = proxy.port or 3128 + end + return request +end + +local maxredericts = 4 +local validredirects = { [301] = true, [302] = true, [303] = true, [307] = true } +local validmethods = { [false] = true, GET = true, HEAD = true } + +local function shouldredirect(request, code, headers) + local location = headers.location + if not location then + return false + end + location = gsub(location, "%s", "") + if location == "" then + return false + end + local scheme = match(location, "^([%w][%w%+%-%.]*)%:") + if scheme and not SCHEMES[scheme] then + return false + end + local method = request.method + local redirect = request.redirect + local redirects = request.nredirects or 0 + return redirect and validredirects[code] and validmethods[method] and redirects <= maxredericts +end + +local function shouldreceivebody(request, code) + if request.method == "HEAD" then + return nil + end + if code == 204 or code == 304 then + return nil + end + if code >= 100 and code < 200 then + return nil + end + return 1 +end + +local tredirect, trequest, srequest + +tredirect = function(request, location) + local result, code, headers, status = trequest { + url = absoluteurl(request.url,location), + source = request.source, + sink = request.sink, + headers = request.headers, + proxy = request.proxy, + nredirects = (request.nredirects or 0) + 1, + create = request.create, + } + if not headers then + headers = { } + end + if not headers.location then + headers.location = location + end + return result, code, headers, status +end + +trequest = function(originalrequest) + local request = adjustrequest(originalrequest) + local connection = openhttp(request.host, request.port, request.create) + local headers = request.headers + connection:sendrequestline(request.method, request.uri) + connection:sendheaders(headers) + if request.source then + connection:sendbody(headers, request.source, request.step) + end + local code, status = connection:receivestatusline() + if not code then + connection:receive09body(status, request.sink, request.step) + return 1, 200 + end + while code == 100 do + headers = connection:receiveheaders() + code, status = connection:receivestatusline() + end + headers = connection:receiveheaders() + if shouldredirect(request, code, headers) and not request.source then + connection:close() + return tredirect(originalrequest,headers.location) + end + if shouldreceivebody(request, code) then + connection:receivebody(headers, request.sink, request.step) + end + connection:close() + return 1, code, headers, status +end + +-- turns an url and a body into a generic request + +local function genericform(url, body) + local buffer = { } + local request = { + url = url, + sink = sinktable(buffer), + target = buffer, + } + if body then + request.source = stringsource(body) + request.method = "POST" + request.headers = { + ["content-length"] = #body, + ["content-type"] = "application/x-www-form-urlencoded" + } + end + return request +end + +http.genericform = genericform + +srequest = function(url, body) + local request = genericform(url, body) + local _, code, headers, status = trequest(request) + return concat(request.target), code, headers, status +end + +http.request = protectsocket(function(request, body) + if type(request) == "string" then + return srequest(request, body) + else + return trequest(request) + end +end) + +package.loaded["socket.http"] = http + +return http diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ltn12.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ltn12.lua new file mode 100644 index 00000000000..54110ab7a30 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-ltn12.lua @@ -0,0 +1,387 @@ +-- original file : ltn12.lua +-- for more into : see util-soc.lua + +local select, unpack = select, unpack +local insert, remove = table.insert, table.remove +local sub = string.sub + +local function report(fmt,first,...) + if logs then + report = logs and logs.reporter("ltn12") + report(fmt,first,...) + elseif fmt then + fmt = "ltn12: " .. fmt + if first then + print(format(fmt,first,...)) + else + print(fmt) + end + end +end + +local filter = { } +local source = { } +local sink = { } +local pump = { } + +local ltn12 = { + + _VERSION = "LTN12 1.0.3", + + BLOCKSIZE = 2048, + + filter = filter, + source = source, + sink = sink, + pump = pump, + + report = report, + +} + +-- returns a high level filter that cycles a low-level filter + +function filter.cycle(low, ctx, extra) + if low then + return function(chunk) + return (low(ctx, chunk, extra)) + end + end +end + +-- chains a bunch of filters together + +function filter.chain(...) + local arg = { ... } + local n = select('#',...) + local top = 1 + local index = 1 + local retry = "" + return function(chunk) + retry = chunk and retry + while true do + local action = arg[index] + if index == top then + chunk = action(chunk) + if chunk == "" or top == n then + return chunk + elseif chunk then + index = index + 1 + else + top = top + 1 + index = top + end + else + chunk = action(chunk or "") + if chunk == "" then + index = index - 1 + chunk = retry + elseif chunk then + if index == n then + return chunk + else + index = index + 1 + end + else + report("error: filter returned inappropriate 'nil'") + return + end + end + end + end +end + +-- create an empty source + +local function empty() + return nil +end + +function source.empty() + return empty +end + +-- returns a source that just outputs an error + +local function sourceerror(err) + return function() + return nil, err + end +end + +source.error = sourceerror + +-- creates a file source + +function source.file(handle, io_err) + if handle then + local blocksize = ltn12.BLOCKSIZE + return function() + local chunk = handle:read(blocksize) + if not chunk then + handle:close() + end + return chunk + end + else + return sourceerror(io_err or "unable to open file") + end +end + +-- turns a fancy source into a simple source + +function source.simplify(src) + return function() + local chunk, err_or_new = src() + if err_or_new then + src = err_or_new + end + if chunk then + return chunk + else + return nil, err_or_new + end + end +end + +-- creates string source + +function source.string(s) + if s then + local blocksize = ltn12.BLOCKSIZE + local i = 1 + return function() + local nexti = i + blocksize + local chunk = sub(s, i, nexti - 1) + i = nexti + if chunk ~= "" then + return chunk + else + return nil + end + end + else return source.empty() end +end + +-- creates rewindable source + +function source.rewind(src) + local t = { } + return function(chunk) + if chunk then + insert(t, chunk) + else + chunk = remove(t) + if chunk then + return chunk + else + return src() + end + end + end +end + +-- chains a source with one or several filter(s) + +function source.chain(src, f, ...) + if ... then + f = filter.chain(f, ...) + end + local last_in = "" + local last_out = "" + local state = "feeding" + local err + return function() + if not last_out then + report("error: source is empty") + return + end + while true do + if state == "feeding" then + last_in, err = src() + if err then + return nil, err + end + last_out = f(last_in) + if not last_out then + if last_in then + report("error: filter returned inappropriate 'nil'") + end + return nil + elseif last_out ~= "" then + state = "eating" + if last_in then + last_in = "" + end + return last_out + end + else + last_out = f(last_in) + if last_out == "" then + if last_in == "" then + state = "feeding" + else + report("error: filter returned nothing") + return + end + elseif not last_out then + if last_in then + report("filter returned inappropriate 'nil'") + end + return nil + else + return last_out + end + end + end + end +end + +-- creates a source that produces contents of several sources, one after the +-- other, as if they were concatenated + +function source.cat(...) + local arg = { ... } + local src = remove(arg,1) + return function() + while src do + local chunk, err = src() + if chunk then + return chunk + end + if err then + return nil, err + end + src = remove(arg,1) + end + end +end + +-- creates a sink that stores into a table + +function sink.table(t) + if not t then + t = { } + end + local f = function(chunk, err) + if chunk then + insert(t, chunk) + end + return 1 + end + return f, t +end + +-- turns a fancy sink into a simple sink + +function sink.simplify(snk) + return function(chunk, err) + local ret, err_or_new = snk(chunk, err) + if not ret then + return nil, err_or_new + end + if err_or_new then + snk = err_or_new + end + return 1 + end +end + +-- creates a sink that discards data + +local function null() + return 1 +end + +function sink.null() + return null +end + +-- creates a sink that just returns an error + +local function sinkerror(err) + return function() + return nil, err + end +end + +sink.error = sinkerror + +-- creates a file sink + +function sink.file(handle, io_err) + if handle then + return function(chunk, err) + if not chunk then + handle:close() + return 1 + else + return handle:write(chunk) + end + end + else + return sinkerror(io_err or "unable to open file") + end +end + +-- chains a sink with one or several filter(s) + +function sink.chain(f, snk, ...) + if ... then + local args = { f, snk, ... } + snk = remove(args, #args) + f = filter.chain(unpack(args)) + end + return function(chunk, err) + if chunk ~= "" then + local filtered = f(chunk) + local done = chunk and "" + while true do + local ret, snkerr = snk(filtered, err) + if not ret then + return nil, snkerr + end + if filtered == done then + return 1 + end + filtered = f(done) + end + else + return 1 + end + end +end + +-- pumps one chunk from the source to the sink + +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then + return 1 + else + return nil, src_err or snk_err + end +end + +-- pumps all data from a source to a sink, using a step function + +function pump.all(src, snk, step) + if not step then + step = pump.step + end + while true do + local ret, err = step(src, snk) + if not ret then + if err then + return nil, err + else + return 1 + end + end + end +end + +package.loaded["ltn12"] = ltn12 + +return ltn12 diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-mime.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-mime.lua new file mode 100644 index 00000000000..4b5d2baff10 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-mime.lua @@ -0,0 +1,104 @@ +-- original file : mime.lua +-- for more into : see util-soc.lua + +local type, tostring = type, tostring + +local mime = require("mime.core") +local ltn12 = ltn12 or require("ltn12") + +local filtercycle = ltn12.filter.cycle + +local function report(fmt,first,...) + if logs then + report = logs and logs.reporter("mime") + report(fmt,first,...) + elseif fmt then + fmt = "mime: " .. fmt + if first then + print(format(fmt,first,...)) + else + print(fmt) + end + end +end + +mime.report = report + +local encodet = { } +local decodet = { } +local wrapt = { } + +mime.encodet = encodet +mime.decodet = decodet +mime.wrapt = wrapt + +local mime_b64 = mime.b64 +local mime_qp = mime.qp +local mime_unb64 = mime.unb64 +local mime_unqp = mime.unqp +local mime_wrp = mime.wrp +local mime_qpwrp = mime.qpwrp +local mime_eol = mime_eol +local mime_dot = mime_dot + +encodet['base64'] = function() + return filtercycle(mime_b64,"") +end + +encodet['quoted-printable'] = function(mode) + return filtercycle(mime_qp, "", mode == "binary" and "=0D=0A" or "\r\n") +end + +decodet['base64'] = function() + return filtercycle(mime_unb64, "") +end + +decodet['quoted-printable'] = function() + return filtercycle(mime_unqp, "") +end + +local wraptext = function(length) + if not length then + length = 76 + end + return filtercycle(mime_wrp, length, length) +end + +local wrapquoted = function() + return filtercycle(mime_qpwrp, 76, 76) +end + +wrapt['text'] = wraptext +wrapt['base64'] = wraptext +wrapt['default'] = wraptext +wrapt['quoted-printable'] = wrapquoted + +function mime.normalize(marker) + return filtercycle(mime_eol, 0, marker) +end + +function mime.stuff() + return filtercycle(mime_dot, 2) +end + +local function choose(list) + return function(name, opt1, opt2) + if type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local filter = list[name or "nil"] + if filter then + return filter(opt1, opt2) + else + report("error: unknown key '%s'",tostring(name)) + end + end +end + +mime.encode = choose(encodet) +mime.decode = choose(decodet) +mime.wrap = choose(wrapt) + +package.loaded["mime"] = mime + +return mime diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-reset.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-reset.lua new file mode 100644 index 00000000000..a4a489b0f90 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-reset.lua @@ -0,0 +1,13 @@ +local loaded = package.loaded + +loaded["socket"] = nil +loaded["copas"] = nil +loaded["ltn12"] = nil +loaded["mbox"] = nil +loaded["mime"] = nil +loaded["socket.url"] = nil +loaded["socket.headers"] = nil +loaded["socket.tp"] = nil +loaded["socket.http"] = nil +loaded["socket.ftp"] = nil +loaded["socket.smtp"] = nil diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-smtp.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-smtp.lua new file mode 100644 index 00000000000..621d1b6e39e --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-smtp.lua @@ -0,0 +1,267 @@ +-- original file : smtp.lua +-- for more into : see util-soc.lua + +local type, setmetatable, next = type, setmetatable, next +local find, lower, format = string.find, string.lower, string.format +local osdate, osgetenv = os.date, os.getenv +local random = math.random + +local socket = socket or require("socket") +local headers = socket.headers or require("socket.headers") +local ltn12 = ltn12 or require("ltn12") +local tp = socket.tp or require("socket.tp") +local mime = mime or require("mime") + +local mimeb64 = mime.b64 +local mimestuff = mime.stuff + +local skipsocket = socket.skip +local trysocket = socket.try +local newtrysocket = socket.newtry +local protectsocket = socket.protect + +local normalizeheaders = headers.normalize +local lowerheaders = headers.lower + +local createcoroutine = coroutine.create +local resumecoroutine = coroutine.resume +local yieldcoroutine = coroutine.resume + +local smtp = { + TIMEOUT = 60, + SERVER = "localhost", + PORT = 25, + DOMAIN = osgetenv("SERVER_NAME") or "localhost", + ZONE = "-0000", +} + +socket.smtp = smtp + +local methods = { } +local mt = { __index = methods } + +function methods.greet(self, domain) + local try = self.try + local tp = self.tp + try(tp:check("2..")) + try(tp:command("EHLO", domain or _M.DOMAIN)) + return skipsocket(1, try(tp:check("2.."))) +end + +function methods.mail(self, from) + local try = self.try + local tp = self.tp + try(tp:command("MAIL", "FROM:" .. from)) + return try(tp:check("2..")) +end + +function methods.rcpt(self, to) + local try = self.try + local tp = self.tp + try(tp:command("RCPT", "TO:" .. to)) + return try(tp:check("2..")) +end + +function methods.data(self, src, step) + local try = self.try + local tp = self.tp + try(tp:command("DATA")) + try(tp:check("3..")) + try(tp:source(src, step)) + try(tp:send("\r\n.\r\n")) + return try(tp:check("2..")) +end + +function methods.quit(self) + local try = self.try + local tp = self.tp + try(tp:command("QUIT")) + return try(tp:check("2..")) +end + +function methods.close(self) + return self.tp:close() +end + +function methods.login(self, user, password) + local try = self.try + local tp = self.tp + try(tp:command("AUTH", "LOGIN")) + try(tp:check("3..")) + try(tp:send(mimeb64(user) .. "\r\n")) + try(tp:check("3..")) + try(tp:send(mimeb64(password) .. "\r\n")) + return try(tp:check("2..")) +end + +function methods.plain(self, user, password) + local try = self.try + local tp = self.tp + local auth = "PLAIN " .. mimeb64("\0" .. user .. "\0" .. password) + try(tp:command("AUTH", auth)) + return try(tp:check("2..")) +end + +function methods.auth(self, user, password, ext) + if not user or not password then + return 1 + end + local try = self.try + if find(ext, "AUTH[^\n]+LOGIN") then + return self:login(user,password) + elseif find(ext, "AUTH[^\n]+PLAIN") then + return self:plain(user,password) + else + try(nil, "authentication not supported") + end +end + +function methods.send(self, mail) + self:mail(mail.from) + local receipt = mail.rcpt + if type(receipt) == "table" then + for i=1,#receipt do + self:rcpt(receipt[i]) + end + elseif receipt then + self:rcpt(receipt) + end + self:data(ltn12.source.chain(mail.source, mimestuff()), mail.step) +end + +local function opensmtp(self, server, port, create) + if not server or server == "" then + server = smtp.SERVER + end + if not port or port == "" then + port = smtp.PORT + end + local s = { + tp = trysocket(tp.connect(server, port, smtp.TIMEOUT, create)), + try = newtrysocket(function() + s:close() + end), + } + setmetatable(s, mt) + return s +end + +smtp.open = opensmtp + +local nofboundaries = 0 + +local function newboundary() + nofboundaries = nofboundaries + 1 + return format('%s%05d==%05u', osdate('%d%m%Y%H%M%S'), random(0,99999), nofboundaries) +end + +local send_message + +local function send_headers(headers) + yieldcoroutine(normalizeheaders(headers)) +end + +local function send_multipart(message) + local boundary = newboundary() + local headers = lowerheaders(message.headers) + local body = message.body + local preamble = body.preamble + local epilogue = body.epilogue + local content = headers['content-type'] or 'multipart/mixed' + headers['content-type'] = content .. '; boundary="' .. boundary .. '"' + send_headers(headers) + if preamble then + yieldcoroutine(preamble) + yieldcoroutine("\r\n") + end + for i=1,#body do + yieldcoroutine("\r\n--" .. boundary .. "\r\n") + send_message(body[i]) + end + yieldcoroutine("\r\n--" .. boundary .. "--\r\n\r\n") + if epilogue then + yieldcoroutine(epilogue) + yieldcoroutine("\r\n") + end +end + +local default_content_type = 'text/plain; charset="UTF-8"' + +local function send_source(message) + local headers = lowerheaders(message.headers) + if not headers['content-type'] then + headers['content-type'] = default_content_type + end + send_headers(headers) + local getchunk = message.body + while true do + local chunk, err = getchunk() + if err then + yieldcoroutine(nil, err) + elseif chunk then + yieldcoroutine(chunk) + else + break + end + end +end + +local function send_string(message) + local headers = lowerheaders(message.headers) + if not headers['content-type'] then + headers['content-type'] = default_content_type + end + send_headers(headers) + yieldcoroutine(message.body) +end + +function send_message(message) + local body = message.body + if type(body) == "table" then + send_multipart(message) + elseif type(body) == "function" then + send_source(message) + else + send_string(message) + end +end + +local function adjust_headers(message) + local headers = lowerheaders(message.headers) + if not headers["date"] then + headers["date"] = osdate("!%a, %d %b %Y %H:%M:%S ") .. (message.zone or smtp.ZONE) + end + if not headers["x-mailer"] then + headers["x-mailer"] = socket._VERSION + end + headers["mime-version"] = "1.0" + return headers +end + +function smtp.message(message) + message.headers = adjust_headers(message) + local action = createcoroutine(function() + send_message(message) + end) + return function() + local ret, a, b = resumecoroutine(action) + if ret then + return a, b + else + return nil, a + end + end +end + +smtp.send = protectsocket(function(mail) + local snd = opensmtp(smtp,mail.server, mail.port, mail.create) + local ext = snd:greet(mail.domain) + snd:auth(mail.user, mail.password, ext) + snd:send(mail) + snd:quit() + return snd:close() +end) + +package.loaded["socket.smtp"] = smtp + +return smtp diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-socket.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-socket.lua new file mode 100644 index 00000000000..3da155749fd --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-socket.lua @@ -0,0 +1,193 @@ +-- original file : socket.lua +-- for more into : see util-soc.lua + +local type, tostring, setmetatable = type, tostring, setmetatable +local min = math.min +local format = string.format + +local socket = require("socket.core") + +local connect = socket.connect +local tcp4 = socket.tcp4 +local tcp6 = socket.tcp6 +local getaddrinfo = socket.dns.getaddrinfo + +local defaulthost = "0.0.0.0" + +local function report(fmt,first,...) + if logs then + report = logs and logs.reporter("socket") + report(fmt,first,...) + elseif fmt then + fmt = "socket: " .. fmt + if first then + print(format(fmt,first,...)) + else + print(fmt) + end + end +end + +socket.report = report + +function socket.connect4(address, port, laddress, lport) + return connect(address, port, laddress, lport, "inet") +end + +function socket.connect6(address, port, laddress, lport) + return connect(address, port, laddress, lport, "inet6") +end + +function socket.bind(host, port, backlog) + if host == "*" or host == "" then + host = defaulthost + end + local addrinfo, err = getaddrinfo(host) + if not addrinfo then + return nil, err + end + for i=1,#addrinfo do + local alt = addrinfo[i] + local sock, err = (alt.family == "inet" and tcp4 or tcp6)() + if not sock then + return nil, err or "unknown error" + end + sock:setoption("reuseaddr", true) + local res, err = sock:bind(alt.addr, port) + if res then + res, err = sock:listen(backlog) + if res then + return sock + else + sock:close() + end + else + sock:close() + end + end + return nil, "invalid address" +end + +socket.try = socket.newtry() + +function socket.choose(list) + return function(name, opt1, opt2) + if type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local f = list[name or "nil"] + if f then + return f(opt1, opt2) + else + report("error: unknown key '%s'",tostring(name)) + end + end +end + +local sourcet = { } +local sinkt = { } + +socket.sourcet = sourcet +socket.sinkt = sinkt + +socket.BLOCKSIZE = 2048 + +sinkt["close-when-done"] = function(sock) + return setmetatable ( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, + { + __call = function(self, chunk, err) + if chunk then + return sock:send(chunk) + else + sock:close() + return 1 -- why 1 + end + end + } + ) +end + +sinkt["keep-open"] = function(sock) + return setmetatable ( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, { + __call = function(self, chunk, err) + if chunk then + return sock:send(chunk) + else + return 1 -- why 1 + end + end + } + ) +end + +sinkt["default"] = sinkt["keep-open"] + +socket.sink = socket.choose(sinkt) + +sourcet["by-length"] = function(sock, length) + local blocksize = socket.BLOCKSIZE + return setmetatable ( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, + { + __call = function() + if length <= 0 then + return nil + end + local chunk, err = sock:receive(min(blocksize,length)) + if err then + return nil, err + end + length = length - #chunk + return chunk + end + } + ) +end + +sourcet["until-closed"] = function(sock) + local blocksize = socket.BLOCKSIZE + local done = false + return setmetatable ( + { + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end, + }, { + __call = function() + if done then + return nil + end + local chunk, status, partial = sock:receive(blocksize) + if not status then + return chunk + elseif status == "closed" then + sock:close() + done = true + return partial + else + return nil, status + end + end + } + ) +end + +sourcet["default"] = sourcet["until-closed"] + +socket.source = socket.choose(sourcet) + +_G.socket = socket -- for now global + +package.loaded["socket"] = socket + +return socket diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-tp.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-tp.lua new file mode 100644 index 00000000000..e651e44f7fe --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-tp.lua @@ -0,0 +1,144 @@ +-- original file : tp.lua +-- for more into : see util-soc.lua + +local setmetatable, next, type, tonumber = setmetatable, next, type, tonumber +local find, upper = string.find, string.upper + +local socket = socket or require("socket") +local ltn12 = ltn12 or require("ltn12") + +local skipsocket = socket.skip +local sinksocket = socket.sink +local tcpsocket = socket.tcp + +local ltn12pump = ltn12.pump +local pumpall = ltn12pump.all +local pumpstep = ltn12pump.step + +local tp = { + TIMEOUT = 60, +} + +socket.tp = tp + +local function get_reply(c) + local line, err = c:receive() + local reply = line + if err then return + nil, err + end + local code, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)")) + if not code then + return nil, "invalid server reply" + end + if sep == "-" then + local current + repeat + line, err = c:receive() + if err then + return nil, err + end + current, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)")) + reply = reply .. "\n" .. line + until code == current and sep == " " + end + return code, reply +end + +local methods = { } +local mt = { __index = methods } + +function methods.getpeername(self) + return self.c:getpeername() +end + +function methods.getsockname(self) + return self.c:getpeername() +end + +function methods.check(self, ok) + local code, reply = get_reply(self.c) + if not code then + return nil, reply + end + local c = tonumber(code) + local t = type(ok) + if t == "function" then + return ok(c,reply) + elseif t == "table" then + for i=1,#ok do + if find(code,ok[i]) then + return c, reply + end + end + return nil, reply + elseif find(code, ok) then + return c, reply + else + return nil, reply + end +end + +function methods.command(self, cmd, arg) + cmd = upper(cmd) + if arg then + cmd = cmd .. " " .. arg .. "\r\n" + else + cmd = cmd .. "\r\n" + end + return self.c:send(cmd) +end + +function methods.sink(self, snk, pat) + local chunk, err = self.c:receive(pat) + return snk(chunk, err) +end + +function methods.send(self, data) + return self.c:send(data) +end + +function methods.receive(self, pat) + return self.c:receive(pat) +end + +function methods.getfd(self) + return self.c:getfd() +end + +function methods.dirty(self) + return self.c:dirty() +end + +function methods.getcontrol(self) + return self.c +end + +function methods.source(self, source, step) + local sink = sinksocket("keep-open", self.c) + local ret, err = pumpall(source, sink, step or pumpstep) + return ret, err +end + +function methods.close(self) + self.c:close() + return 1 +end + +function tp.connect(host, port, timeout, create) + local c, e = (create or tcpsocket)() + if not c then + return nil, e + end + c:settimeout(timeout or tp.TIMEOUT) + local r, e = c:connect(host, port) + if not r then + c:close() + return nil, e + end + return setmetatable({ c = c }, mt) +end + +package.loaded["socket.tp"] = tp + +return tp diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-url.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-url.lua new file mode 100644 index 00000000000..fa472b65041 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc-imp-url.lua @@ -0,0 +1,268 @@ +-- original file : url.lua +-- for more into : see util-soc.lua + +local tonumber, tostring, type = tonumber, tostring, type + +local gsub, sub, match, find, format, byte, char = string.gsub, string.sub, string.match, string.find, string.format, string.byte, string.char +local insert = table.insert + +local socket = socket or require("socket") + +local url = { + _VERSION = "URL 1.0.3", +} + +socket.url = url + +function url.escape(s) + return (gsub(s, "([^A-Za-z0-9_])", function(c) + return format("%%%02x", byte(c)) + end)) +end + +local function make_set(t) -- table.tohash + local s = { } + for i=1,#t do + s[t[i]] = true + end + return s +end + +local segment_set = make_set { + "-", "_", ".", "!", "~", "*", "'", "(", + ")", ":", "@", "&", "=", "+", "$", ",", +} + +local function protect_segment(s) + return gsub(s, "([^A-Za-z0-9_])", function(c) + if segment_set[c] then + return c + else + return format("%%%02X", byte(c)) + end + end) +end + +function url.unescape(s) + return (gsub(s, "%%(%x%x)", function(hex) + return char(tonumber(hex,16)) + end)) +end + +local function absolute_path(base_path, relative_path) + if find(relative_path,"^/") then + return relative_path + end + local path = gsub(base_path, "[^/]*$", "") + path = path .. relative_path + path = gsub(path, "([^/]*%./)", function (s) + if s ~= "./" then + return s + else + return "" + end + end) + path = gsub(path, "/%.$", "/") + local reduced + while reduced ~= path do + reduced = path + path = gsub(reduced, "([^/]*/%.%./)", function (s) + if s ~= "../../" then + return "" + else + return s + end + end) + end + path = gsub(reduced, "([^/]*/%.%.)$", function (s) + if s ~= "../.." then + return "" + else + return s + end + end) + return path +end + +function url.parse(url, default) + local parsed = { } + for k, v in next, default or parsed do + parsed[k] = v + end + if not url or url == "" then + return nil, "invalid url" + end + url = gsub(url, "#(.*)$", function(f) + parsed.fragment = f + return "" + end) + url = gsub(url, "^([%w][%w%+%-%.]*)%:", function(s) + parsed.scheme = s + return "" + end) + url = gsub(url, "^//([^/]*)", function(n) + parsed.authority = n + return "" + end) + url = gsub(url, "%?(.*)", function(q) + parsed.query = q + return "" + end) + url = gsub(url, "%;(.*)", function(p) + parsed.params = p + return "" + end) + if url ~= "" then + parsed.path = url + end + local authority = parsed.authority + if not authority then + return parsed + end + authority = gsub(authority,"^([^@]*)@", function(u) + parsed.userinfo = u + return "" + end) + authority = gsub(authority, ":([^:%]]*)$", function(p) + parsed.port = p + return "" + end) + if authority ~= "" then + parsed.host = match(authority, "^%[(.+)%]$") or authority + end + local userinfo = parsed.userinfo + if not userinfo then + return parsed + end + userinfo = gsub(userinfo, ":([^:]*)$", function(p) + parsed.password = p + return "" + end) + parsed.user = userinfo + return parsed +end + +function url.build(parsed) + local url = parsed.path or "" + if parsed.params then + url = url .. ";" .. parsed.params + end + if parsed.query then + url = url .. "?" .. parsed.query + end + local authority = parsed.authority + if parsed.host then + authority = parsed.host + if find(authority, ":") then -- IPv6? + authority = "[" .. authority .. "]" + end + if parsed.port then + authority = authority .. ":" .. tostring(parsed.port) + end + local userinfo = parsed.userinfo + if parsed.user then + userinfo = parsed.user + if parsed.password then + userinfo = userinfo .. ":" .. parsed.password + end + end + if userinfo then authority = userinfo .. "@" .. authority end + end + if authority then + url = "//" .. authority .. url + end + if parsed.scheme then + url = parsed.scheme .. ":" .. url + end + if parsed.fragment then + url = url .. "#" .. parsed.fragment + end + return url +end + +function url.absolute(base_url, relative_url) + local base_parsed + if type(base_url) == "table" then + base_parsed = base_url + base_url = url.build(base_parsed) + else + base_parsed = url.parse(base_url) + end + local relative_parsed = url.parse(relative_url) + if not base_parsed then + return relative_url + elseif not relative_parsed then + return base_url + elseif relative_parsed.scheme then + return relative_url + else + relative_parsed.scheme = base_parsed.scheme + if not relative_parsed.authority then + relative_parsed.authority = base_parsed.authority + if not relative_parsed.path then + relative_parsed.path = base_parsed.path + if not relative_parsed.params then + relative_parsed.params = base_parsed.params + if not relative_parsed.query then + relative_parsed.query = base_parsed.query + end + end + else + relative_parsed.path = absolute_path(base_parsed.path or "", relative_parsed.path) + end + end + return url.build(relative_parsed) + end +end + +function url.parse_path(path) + local parsed = { } + path = path or "" + gsub(path, "([^/]+)", function (s) + insert(parsed, s) + end) + for i=1,#parsed do + parsed[i] = url.unescape(parsed[i]) + end + if sub(path, 1, 1) == "/" then + parsed.is_absolute = 1 + end + if sub(path, -1, -1) == "/" then + parsed.is_directory = 1 + end + return parsed +end + +function url.build_path(parsed, unsafe) + local path = "" + local n = #parsed + if unsafe then + for i = 1, n-1 do + path = path .. parsed[i] .. "/" + end + if n > 0 then + path = path .. parsed[n] + if parsed.is_directory then + path = path .. "/" + end + end + else + for i = 1, n-1 do + path = path .. protect_segment(parsed[i]) .. "/" + end + if n > 0 then + path = path .. protect_segment(parsed[n]) + if parsed.is_directory then + path = path .. "/" + end + end + end + if parsed.is_absolute then + path = "/" .. path + end + return path +end + +package.loaded["socket.url"] = url + +return url diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua b/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua index 3a52ee86de3..590287a25b1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-soc.lua @@ -6,6 +6,29 @@ if not modules then modules = { } end modules ['util-soc'] = { license = "see context related readme files" } +--[[-- + +In LuaTeX we provide the socket library that is more or less the standard one for +Lua. It has been around for a while and seems to be pretty stable. The binary +module is copmpiled into LuaTeX and the accompanying .lua files are preloaded. +These files are mostly written by Diego Nehab, Andre Carregal, Javier Guerra, and +Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall, David Burgess, +Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals are part of and +copyrighted by the Kepler project. + +Here we reload a slightly reworked version of these .lua files. We keep the same +(documented) interface but streamlined some fo the code. No more modules, no more +pre 5.2 Lua, etc. Also, as it loads into the ConTeXt ecosystem, we plug in some +logging. (and maybe tracing in the future). As we don't support serial ports in +LuaTeX, related code has been dropped. + +The files are reformatted so that we can more easilly add additional features +and/or tracing options. Any error introduced there is our fault! The url module +might be replaced by the one in ConTeXt. When we need mbox a suitable variant +will be provided. + +--]]-- + local format = string.format local smtp = require("socket.smtp") @@ -95,3 +118,12 @@ function mail.send(specification) return true end end + +-- for now we have this here: + +if socket then + + math.initialseed = tonumber(string.sub(string.reverse(tostring(math.ceil(socket.gettime()*10000))),1,6)) + math.randomseed(math.initialseed) + +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua index 2a2bc656934..3731933f1e1 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['util-sql-imp-ffi'] = { -- I looked at luajit-mysql to see how the ffi mapping was done but it didn't work -- out that well (at least not on windows) but I got the picture. As I have somewhat --- different demands I simplified / redid the ffi bti and just took the swiglib +-- different demands I simplified / redid the ffi bit and just took the swiglib -- variant and adapted that. local tonumber = tonumber @@ -17,6 +17,7 @@ local format, byte = string.format, string.byte local lpegmatch = lpeg.match local setmetatable, type = setmetatable, type local sleep = os.sleep +local formatters = string.formatters local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end) local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end) @@ -33,6 +34,9 @@ ffi.cdef [[ a query. The rest is handled already in the Lua code elsewhere. */ + void free(void*ptr); + void * malloc(size_t size); + typedef void MYSQL_instance; typedef void MYSQL_result; typedef char **MYSQL_row; @@ -115,6 +119,14 @@ ffi.cdef [[ MYSQL_result *result ); + unsigned int mysql_affected_rows ( + MYSQL_instance *mysql + ); + + unsigned int mysql_field_count ( + MYSQL_instance *mysql + ); + unsigned int mysql_num_fields ( MYSQL_result *res ); @@ -163,12 +175,14 @@ local dataprepared = helpers.preparetemplate local serialize = sql.serialize local deserialize = sql.deserialize -local mysql_initialize = mysql.mysql_init +local mysql_open_session = mysql.mysql_init local mysql_open_connection = mysql.mysql_real_connect local mysql_execute_query = mysql.mysql_real_query local mysql_close_connection = mysql.mysql_close +local mysql_affected_rows = mysql.mysql_affected_rows +local mysql_field_count = mysql.mysql_field_count local mysql_field_seek = mysql.mysql_field_seek local mysql_num_fields = mysql.mysql_num_fields local mysql_fetch_fields = mysql.mysql_fetch_fields @@ -180,6 +194,7 @@ local mysql_init = mysql.mysql_init local mysql_store_result = mysql.mysql_store_result local mysql_free_result = mysql.mysql_free_result +local mysql_error_number = mysql.mysql_errno local mysql_error_message = mysql.mysql_error local NULL = ffi.cast("MYSQL_result *",0) @@ -187,325 +202,361 @@ local NULL = ffi.cast("MYSQL_result *",0) local ffi_tostring = ffi.string local ffi_gc = ffi.gc ------ mysqldata = ffi.cast("MYSQL_instance*",mysql.malloc(1024*1024)) -local instance = mysql.mysql_init(nil) -- (mysqldata) +local instance = mysql.mysql_init(nil) local mysql_constant_false = false local mysql_constant_true = true -local function finish(t) - local r = t._result_ - if r then - ffi_gc(r,mysql_free_result) +local wrapresult do + + local function collect(t) + local result = t._result_ + if result then + ffi_gc(result,mysql_free_result) + end end -end -local function getcolnames(t) - return t.names -end + local function finish(t) + local result = t._result_ + if result then + t._result_ = nil + ffi_gc(result,mysql_free_result) + end + end -local function getcoltypes(t) - return t.types -end + local function getcoldata(t) + local result = t._result_ + local nofrows = t.nofrows + local noffields = t.noffields + local names = { } + local types = { } + local fields = mysql_fetch_fields(result) + for i=1,noffields do + local field = fields[i-1] + names[i] = ffi_tostring(field.name) + types[i] = tonumber(field.type) -- todo + end + t.names = names + t.types = types + end -local function numrows(t) - return tonumber(t.nofrows) -end + local function getcolnames(t) + local names = t.names + if names then + return names + end + getcoldata(t) + return t.names + end -local function list(t) - local result = t._result_ - if result then - local row = mysql_fetch_row(result) - -- local len = mysql_fetch_lengths(result) - local result = { } - for i=1,t.noffields do - result[i] = ffi_tostring(row[i-1]) + local function getcoltypes(t) + local types = t.types + if types then + return types end - return result + getcoldata(t) + return t.types end -end -local function hash(t) - local result = t._result_ - local fields = t.names - if result then - local row = mysql_fetch_row(result) - -- local len = mysql_fetch_lengths(result) - local result = { } - for i=1,t.noffields do - result[fields[i]] = ffi_tostring(row[i-1]) + local function numrows(t) + return t.nofrows + end + + -- local function fetch(t) + -- local + -- local row = mysql_fetch_row(result) + -- local result = { } + -- for i=1,t.noffields do + -- result[i] = ffi_tostring(row[i-1]) + -- end + -- return unpack(result) + -- end + + local mt = { + __gc = collect, + __index = { + _result_ = nil, + close = finish, + numrows = numrows, + getcolnames = getcolnames, + getcoltypes = getcoltypes, + -- fetch = fetch, -- not efficient + } + } + + wrapresult = function(connection) + local result = mysql_store_result(connection) + if result ~= NULL then + mysql_field_seek(result,0) + local t = { + _result_ = result, + nofrows = tonumber(mysql_num_rows (result) or 0) or 0, + noffields = tonumber(mysql_num_fields(result) or 0) or 0, + } + return setmetatable(t,mt) + elseif tonumber(mysql_field_count(connection) or 0) or 0 > 0 then + return tonumber(mysql_affected_rows(connection)) end - return result end -end -local function wholelist(t) - return fetch_all_rows(t._result_) end -local mt = { __index = { - -- regular - finish = finish, - list = list, - hash = hash, - wholelist = wholelist, - -- compatibility - numrows = numrows, - getcolnames = getcolnames, - getcoltypes = getcoltypes, - -- fallback - _result_ = nil, - names = { }, - types = { }, - noffields = 0, - nofrows = 0, - } -} +local initializesession do -local nt = setmetatable({},mt) + -- timeouts = [ connect_timeout |wait_timeout | interactive_timeout ] --- session + local timeout -- = 3600 -- to be tested -local function close(t) - mysql_close_connection(t._connection_) -end + -- connection -local function execute(t,query) - if query and query ~= "" then - local connection = t._connection_ - local result = mysql_execute_query(connection,query,#query) - if result == 0 then - local result = mysql_store_result(connection) - if result ~= NULL then - mysql_field_seek(result,0) - local nofrows = tonumber(mysql_num_rows(result) or 0) - local noffields = tonumber(mysql_num_fields(result)) - local names = { } - local types = { } - local fields = mysql_fetch_fields(result) - for i=1,noffields do - local field = fields[i-1] - names[i] = ffi_tostring(field.name) - types[i] = tonumber(field.type) -- todo - end - local t = { - _result_ = result, - names = names, - types = types, - noffields = noffields, - nofrows = nofrows, - } - return setmetatable(t,mt) + local function close(t) + -- just a struct ? + end + + local function execute(t,query) + if query and query ~= "" then + local connection = t._connection_ + local result = mysql_execute_query(connection,query,#query) + if result == 0 then + return wrapresult(connection) else - return nt + -- mysql_error_number(connection) + return false, ffi_tostring(mysql_error_message(connection)) end end + return false end - return false -end -local mt = { __index = { - close = close, - execute = execute, + local mt = { + __index = { + close = close, + execute = execute, + } } -} -local function open(t,database,username,password,host,port) - local connection = mysql_open_connection( - t._session_, - host or "localhost", - username or "", - password or "", - database or "", - port or 0, - NULL, - 0 - ) - if connection ~= NULL then - local t = { - _connection_ = connection, - } - return setmetatable(t,mt) + -- session + + local function open(t,database,username,password,host,port) + local connection = mysql_open_connection( + t._session_, + host or "localhost", + username or "", + password or "", + database or "", + port or 0, + NULL, + 0 + ) + if connection ~= NULL then + if timeout then + execute(connection,formatters["SET SESSION connect_timeout=%s ;"](timeout)) + end + local t = { + _connection_ = connection, + } + return setmetatable(t,mt) + end end -end -local function message(t) - return mysql_error_message(t._session_) -end - -local function close(t) - -- dummy, as we have a global session -end + local function message(t) + return mysql_error_message(t._session_) + end -local mt = { - __index = { - connect = open, - close = close, - message = message, - } -} + local function close(t) + local connection = t._connection_ + if connection and connection ~= NULL then + ffi_gc(connection, mysql_close) + t.connection = nil + end + end -local function initialize() - local session = { - _session_ = mysql_initialize(instance) -- maybe share, single thread anyway + local mt = { + __index = { + connect = open, + close = close, + message = message, + }, } - return setmetatable(session,mt) -end --- -- -- -- + initializesession = function() + local session = { + _session_ = mysql_open_session(instance) -- maybe share, single thread anyway + } + return setmetatable(session,mt) + end -local function connect(session,specification) - return session:connect( - specification.database or "", - specification.username or "", - specification.password or "", - specification.host or "", - specification.port - ) end -local function error_in_connection(specification,action) - report_state("error in connection: [%s] user %s into %s at %s:%s", - action or "unknown", - specification.username or "no username", - specification.database or "no database", - specification.host or "no host", - specification.port or "no port" - ) -end +local executequery do -local function datafetched(specification,query,converter) - if not query or query == "" then - report_state("no valid query") - return { }, { } + local function connect(session,specification) + return session:connect( + specification.database or "", + specification.username or "", + specification.password or "", + specification.host or "", + specification.port + ) end - local id = specification.id - local session, connection - if id then - local c = cache[id] - if c then - session = c.session - connection = c.connection + + local function fetched(specification,query,converter) + if not query or query == "" then + report_state("no valid query") + return false end - if not connection then - session = initialize() - connection = connect(session,specification) + local id = specification.id + local session, connection + if id then + local c = cache[id] + if c then + session = c.session + connection = c.connection + end if not connection then - for i=1,nofretries do - sleep(retrydelay) - report_state("retrying to connect: [%s.%s] %s@%s to %s:%s", - id,i, - specification.database or "no database", - specification.username or "no username", - specification.host or "no host", - specification.port or "no port" - ) - connection = connect(session,specification) - if connection then - break - end + session = initializesession() + if not session then + return formatters["no session for %a"](id) end - end - if connection then - cache[id] = { session = session, connection = connection } - end - end - else - session = initialize() - connection = connect(session,specification) - if not connection then - for i=1,nofretries do - sleep(retrydelay) - report_state("retrying to connect: [%s] %s@%s to %s:%s", - i, - specification.database or "no database", - specification.username or "no username", - specification.host or "no host", - specification.port or "no port" - ) connection = connect(session,specification) - if connection then - break + if not connection then + return formatters["no connection for %a"](id) end + cache[id] = { session = session, connection = connection } + end + else + session = initializesession() + if not session then + return "no session" + end + connection = connect(session,specification) + if not connection then + return "no connection" end end - end - if not connection then - report_state("error in connection: %s@%s to %s:%s", + if not connection then + report_state("error in connection: %s@%s to %s:%s", specification.database or "no database", specification.username or "no username", specification.host or "no host", specification.port or "no port" ) - return { }, { } - end - query = lpegmatch(querysplitter,query) - local result, message, okay - for i=1,#query do - local q = query[i] - local r, m = connection:execute(q) - if m then - report_state("error in query, stage: %s",string.collapsespaces(q or "?")) - message = message and format("%s\n%s",message,m) or m + return "no connection" end - if type(r) == "table" then - result = r - okay = true - elseif not m then - okay = true + query = lpegmatch(querysplitter,query) + local result, okay + for i=1,#query do + local q = query[i] + local r, m = connection:execute(q) + if m then + report_state("error in query to host %a: %s",specification.host,string.collapsespaces(q or "?")) + if m then + report_state("message: %s",m) + end + end + local t = type(r) + if t == "table" then + result = r + okay = true + elseif t == "number" then + okay = true + end end - end - local data, keys - if result then - if converter then - data = converter.ffi(result) - else - keys = result.names - data = { } - for i=1,result.nofrows do - data[i] = result:hash() + if not okay then -- can go + -- why do we close a session + if connection then + connection:close() + end + if session then + session:close() end + if id then + cache[id] = nil + end + return "execution error" end - result:finish() -- result:close() - elseif message then - report_state("message %s",message) - end - if not keys then - keys = { } - end - if not data then - data = { } - end - if not id then - connection:close() - session:close() + local data, keys + if result then + if converter then + data = converter.ffi(result) + else + local _result_ = result._result_ + local noffields = result.noffields + local nofrows = result.nofrows + keys = result:getcolnames() + data = { } + if noffields > 0 and nofrows > 0 then + for i=1,nofrows do + local cells = { } + local row = mysql_fetch_row(_result_) + for j=1,noffields do + local s = row[j-1] + local k = keys[j] + if s == NULL then + cells[k] = "" + else + cells[k] = ffi_tostring(s) + end + end + data[i] = cells + end + end + end + result:close() + end + -- + if not id then + if connection then + connection:close() + end + if session then + session:close() + end + end + return false, data, keys end - return data, keys -end -local function execute(specification) - if trace_sql then - report_state("executing library") - end - if not validspecification(specification) then - report_state("error in specification") - return - end - local query = dataprepared(specification) - if not query then - report_state("error in preparation") - return - end - local data, keys = datafetched(specification,query,specification.converter) - if not data then - report_state("error in fetching") - return + local function datafetched(specification,query,converter) + local callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter) + if not callokay then + report_state("call error, retrying") + callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter) + elseif connectionerror then + report_state("error: %s, retrying",connectionerror) + callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter) + end + if not callokay then + report_state("persistent call error") + elseif connectionerror then + report_state("persistent error: %s",connectionerror) + end + return data or { }, keys or { } end - local one = data[1] - if one then - setmetatable(data,{ __index = one } ) + + executequery = function(specification) + if trace_sql then + report_state("executing library") + end + if not validspecification(specification) then + report_state("error in specification") + return + end + local query = dataprepared(specification) + if not query then + report_state("error in preparation") + return + end + local data, keys = datafetched(specification,query,specification.converter) + if not data then + report_state("error in fetching") + return + end + local one = data[1] + if one then + setmetatable(data,{ __index = one } ) + end + return data, keys end - return data, keys + end local wraptemplate = [[ @@ -530,13 +581,14 @@ return function(result) if not result then return { } end - local nofrows = result.nofrows or 0 + local nofrows = result.nofrows if nofrows == 0 then return { } end - local noffields = result.noffields or 0 - local _result_ = result._result_ + local noffields = result.noffields local target = { } -- no %s needed here + local _result_ = result._result_ + -- we can share cells for i=1,nofrows do local cells = { } local row = mysql_fetch_row(_result_) @@ -552,7 +604,7 @@ return function(result) %s } end - result:finish() -- result:close() + result:close() return target end ]] @@ -560,9 +612,9 @@ end local celltemplate = "cells[%s]" methods.ffi = { - runner = function() end, -- never called - execute = execute, - initialize = initialize, -- returns session + runner = function() end, -- never called + execute = executequery, + initialize = initializesession, -- returns session usesfiles = false, wraptemplate = wraptemplate, celltemplate = celltemplate, diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua index a2b692e4588..dbbeb32cc46 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua @@ -156,13 +156,13 @@ local function fetched(specification,query,converter) okay = true end end - if not okay then -- can go - if session then - session:close() - end + if not okay then if connection then connection:close() end + if session then + session:close() + end if id then cache[id] = nil end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua index 04d5ced3a25..cf4a3a8b04d 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua @@ -132,7 +132,6 @@ setmetatable(cache, { local f_preamble = formatters[ [[ ATTACH `%s` AS `%s` ; PRAGMA `%s`.synchronous = normal ; -PRAGMA journal_mode = truncate ; ]] ] local function execute(specification) @@ -211,17 +210,19 @@ local function execute(specification) else local column = { } callback = function(data,nofcolumns,values,fields) - for i=0,nofcolumns-1 do + for i=1,nofcolumns do local field if keysdone then - field = keys[i+1] + field = keys[i] else -- field = get_list_item(fields,i) - field = ffi_tostring(fields[i]) + field = ffi_tostring(fields[i-1]) keys[i+1] = field end - -- column[field] = get_list_item(values,i) - column[field] = ffi_tostring(values[i]) + if field then + -- column[field] = get_list_item(values,i) + column[field] = ffi_tostring(values[i-1]) + end end nofrows = nofrows + 1 keysdone = true diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-logins.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-logins.lua index dcb48fb356a..c19bfbdf81f 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-logins.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-logins.lua @@ -211,9 +211,10 @@ end logins.userpurge = userpurge local function verdict(okay,...) - if not trace_logins then - -- no tracing - elseif okay then +-- if not trace_logins then +-- -- no tracing +-- else + if okay then report_logins("%s, granted",formatter(...)) else report_logins("%s, blocked",formatter(...)) @@ -244,6 +245,11 @@ function logins.userpermitted(db,name) } end if not data or not data.name then + if not data then + report_logins("no user data for %a",name) + else + report_logins("no name entry for %a",name) + end local d = { name = name, state = 0, diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua index 7204fb310da..57c99b2a776 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-users.lua @@ -25,12 +25,16 @@ local trace_sql = false trackers.register("sql.users.trace", function(v) trace_ local report = logs.reporter("sql","users") local split = lpeg.splitat(":") + local valid = nil local hash = function(s) return "MD5:" .. sumHEXA(s) end +local sha2 = sha2 or (utilities and utilities.sha2) -if LUAVERSION >= 5.3 then +if not sha2 and LUAVERSION >= 5.3 then + sha2 = require("util-sha") +end - local sha2 = require("util-sha") +if sha2 then local HASH224 = sha2.HASH224 local HASH256 = sha2.HASH256 @@ -238,9 +242,7 @@ function users.valid(db,username,password,address) name = username, }, } - local data = data and data[1] - if not data then return false, "unknown user" elseif not data.enabled then diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua index d140cacdcd8..7819395f69c 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sta.lua @@ -289,24 +289,24 @@ end -- -- local concat = table.concat -- --- local pdfpageliteral = nodes.pool.pdfpageliteral +-- local pageliteral = nodes.pool.pageliteral -- -- function demostacker.start(s,t,first,last) -- local n = whatever[t[last]] -- -- s.report("start: %s",n) --- return pdfpageliteral(n) +-- return pageliteral(n) -- end -- -- function demostacker.stop(s,t,first,last) -- local n = whatever[false] -- -- s.report("stop: %s",n) --- return pdfpageliteral(n) +-- return pageliteral(n) -- end -- -- function demostacker.change(s,t1,first1,last1,t2,first2,last2) -- local n = whatever[t2[last2]] -- -- s.report("change: %s",n) --- return pdfpageliteral(n) +-- return pageliteral(n) -- end -- -- demostacker.mode = "switch" @@ -325,7 +325,7 @@ end -- r[#r+1] = whatever[t[i]] -- end -- -- s.report("start: %s",concat(r," ")) --- return pdfpageliteral(concat(r," ")) +-- return pageliteral(concat(r," ")) -- end -- -- function demostacker.stop(s,t,first,last) @@ -334,7 +334,7 @@ end -- r[#r+1] = whatever[false] -- end -- -- s.report("stop: %s",concat(r," ")) --- return pdfpageliteral(concat(r," ")) +-- return pageliteral(concat(r," ")) -- end -- -- function demostacker.change(s,t1,first1,last1,t2,first2,last2) @@ -346,7 +346,7 @@ end -- r[#r+1] = whatever[t2[i]] -- end -- -- s.report("change: %s",concat(r," ")) --- return pdfpageliteral(concat(r," ")) +-- return pageliteral(concat(r," ")) -- end -- -- demostacker.mode = "stack" diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua index 5b6915eaf01..a08d25ced18 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-sto.lua @@ -196,6 +196,19 @@ function table.getmetatablekey(t,key,value) return m and m[key] end +function table.makeweak(t) + if not t then + t = { } + end + local m = getmetatable(t) + if m then + m.__mode = "v" + else + setmetatable(t,{ __mode = "v" }) + end + return t +end + -- Problem: we have no __next (which is ok as it would probably slow down lua) so -- we cannot loop over the keys. diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-str.lua b/Master/texmf-dist/tex/context/base/mkiv/util-str.lua index 05ff9f304d7..713c294ebe7 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-str.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-str.lua @@ -22,46 +22,72 @@ local utfchar, utfbyte, utflen = utf.char, utf.byte, utf.len ----- loadstripped = utilities.lua.loadstripped ----- setmetatableindex = table.setmetatableindex -local loadstripped = nil -local oldfashioned = LUAVERSION < 5.2 - -if oldfashioned then - - loadstripped = function(str,shortcuts) - return load(str) - end - -else - - loadstripped = function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end +local loadstripped = function(str,shortcuts) + if shortcuts then + return load(dump(load(str),true),nil,nil,shortcuts) + else + return load(dump(load(str),true)) end - end -- todo: make a special namespace for the formatter if not number then number = { } end -- temp hack for luatex-fonts -local stripper = patterns.stripzeros +local stripzero = patterns.stripzero +local stripzeros = patterns.stripzeros local newline = patterns.newline local endofstring = patterns.endofstring +local anything = patterns.anything local whitespace = patterns.whitespace +local space = patterns.space local spacer = patterns.spacer local spaceortab = patterns.spaceortab +local digit = patterns.digit +local sign = patterns.sign +local period = patterns.period + +-- local function points(n) +-- n = tonumber(n) +-- return (not n or n == 0) and "0pt" or lpegmatch(stripzeros,format("%.5fpt",n/65536)) +-- end + +-- local function basepoints(n) +-- n = tonumber(n) +-- return (not n or n == 0) and "0bp" or lpegmatch(stripzeros,format("%.5fbp", n*(7200/7227)/65536)) +-- end + +local ptf = 1 / 65536 +local bpf = (7200/7227) / 65536 local function points(n) + if n == 0 then + return "0pt" + end n = tonumber(n) - return (not n or n == 0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) + if not n or n == 0 then + return "0pt" + end + n = n * ptf + if n % 1 == 0 then + return format("%ipt",n) + end + return lpegmatch(stripzeros,format("%.5fpt",n)) -- plural as we need to keep the pt end local function basepoints(n) + if n == 0 then + return "0pt" + end n = tonumber(n) - return (not n or n == 0) and "0bp" or lpegmatch(stripper,format("%.5fbp", n*(7200/7227)/65536)) + if not n or n == 0 then + return "0pt" + end + n = n * bpf + if n % 1 == 0 then + return format("%ibp",n) + end + return lpegmatch(stripzeros,format("%.5fbp",n)) -- plural as we need to keep the pt end number.points = points @@ -72,7 +98,6 @@ number.basepoints = basepoints local rubish = spaceortab^0 * newline local anyrubish = spaceortab + newline -local anything = patterns.anything local stripped = (spaceortab^1 / "") * newline local leading = rubish^0 / "" local trailing = (anyrubish^1 * endofstring) / "" @@ -140,7 +165,7 @@ local pattern = + newline * Cp() / function(position) extra, start = 0, position end - + patterns.anything + + anything )^1) function strings.tabtospace(str,tab) @@ -183,27 +208,31 @@ end -- return str -- end -local space = spacer^0 -local nospace = space/"" -local endofline = nospace * newline +local optionalspace = spacer^0 +local nospace = optionalspace/"" +local endofline = nospace * newline -local stripend = (whitespace^1 * endofstring)/"" +local stripend = (whitespace^1 * endofstring)/"" -local normalline = (nospace * ((1-space*(newline+endofstring))^1) * nospace) +local normalline = (nospace * ((1-optionalspace*(newline+endofstring))^1) * nospace) -local stripempty = endofline^1/"" -local normalempty = endofline^1 -local singleempty = endofline * (endofline^0/"") -local doubleempty = endofline * endofline^-1 * (endofline^0/"") +local stripempty = endofline^1/"" +local normalempty = endofline^1 +local singleempty = endofline * (endofline^0/"") +local doubleempty = endofline * endofline^-1 * (endofline^0/"") +local stripstart = stripempty^0 -local stripstart = stripempty^0 +local intospace = whitespace^1/" " +local noleading = whitespace^1/"" +local notrailing = noleading * endofstring -local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 ) -local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 ) -local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 ) -local p_retain_normal = Cs ( ( normalline + normalempty )^0 ) -local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 ) -local p_retain_noempty = Cs ( ( normalline + singleempty )^0 ) +local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 ) +local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 ) +local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 ) +local p_prune_intospace = Cs ( noleading * ( notrailing + intospace + 1 )^0 ) +local p_retain_normal = Cs ( ( normalline + normalempty )^0 ) +local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 ) +local p_retain_noempty = Cs ( ( normalline + singleempty )^0 ) -- function striplines(str,prune,collapse,noempty) -- if prune then @@ -229,10 +258,11 @@ local striplinepatterns = { ["prune"] = p_prune_normal, ["prune and collapse"] = p_prune_collapse, -- default ["prune and no empty"] = p_prune_noempty, + ["prune and to space"] = p_prune_intospace, ["retain"] = p_retain_normal, ["retain and collapse"] = p_retain_collapse, ["retain and no empty"] = p_retain_noempty, - ["collapse"] = patterns.collapser, -- how about: stripper fullstripper + ["collapse"] = patterns.collapser, } setmetatable(striplinepatterns,{ __index = function(t,k) return p_prune_collapse end }) @@ -243,6 +273,10 @@ function strings.striplines(str,how) return str and lpegmatch(striplinepatterns[how],str) or str end +function strings.collapse(str) -- maybe also in strings + return str and lpegmatch(p_prune_intospace,str) or str +end + -- also see: string.collapsespaces strings.striplong = strings.striplines -- for old times sake @@ -258,13 +292,14 @@ strings.striplong = strings.striplines -- for old times sake -- " zus wim jet", -- " ", -- }, "\n") - +-- -- local str = table.concat( { -- " aaaa", -- " bb", -- " cccccc", +-- " ", -- }, "\n") - +-- -- for k, v in table.sortedhash(utilities.strings.striplinepatterns) do -- logs.report("stripper","method: %s, result: [[%s]]",k,utilities.strings.striplines(str,k)) -- end @@ -335,6 +370,7 @@ end -- automatic %...a 'whatever' (string, table, ...) -- automatic %...A "whatever" (string, table, ...) -- zap %...z skip +-- stripped %...N %...N -- comma/period real %...m -- period/comma real %...M -- formatted float %...k n.m @@ -410,27 +446,45 @@ end -- maybe to util-num -local digit = patterns.digit -local period = patterns.period -local three = digit * digit * digit +local two = digit * digit +local three = two * digit +local prefix = (Carg(1) * three)^1 local splitter = Cs ( - (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1)) - * (P(1)/"" * Carg(2)) * C(2) + (((1 - (three^1 * period))^1 + C(three)) * prefix + C((1-period)^1)) + * (anything/"" * Carg(2)) * C(2) +) + +local splitter3 = Cs ( + three * prefix * endofstring + + two * prefix * endofstring + + digit * prefix * endofstring + + three + + two + + digit ) patterns.formattednumber = splitter function number.formatted(n,sep1,sep2) - local s = type(s) == "string" and n or format("%0.2f",n) - if sep1 == true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1 == "." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1 == "," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") + if sep1 == false then + if type(n) == "number" then + n = tostring(n) + end + return lpegmatch(splitter3,n,1,sep2 or ".") else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") + if type(n) == "number" then + n = format("%0.2f",n) + end + if sep1 == true then + return lpegmatch(splitter,n,1,".",",") + elseif sep1 == "." then + return lpegmatch(splitter,n,1,sep1,sep2 or ",") + elseif sep1 == "," then + return lpegmatch(splitter,n,1,sep1,sep2 or ".") + else + return lpegmatch(splitter,n,1,sep1 or ",",sep2 or ".") + end end end @@ -443,14 +497,22 @@ end -- print(number.formatted(1234567)) -- print(number.formatted(12345678)) -- print(number.formatted(12345678,true)) +-- print(number.formatted(1,false)) +-- print(number.formatted(12,false)) +-- print(number.formatted(123,false)) +-- print(number.formatted(1234,false)) +-- print(number.formatted(12345,false)) +-- print(number.formatted(123456,false)) +-- print(number.formatted(1234567,false)) +-- print(number.formatted(12345678,false)) -- print(number.formatted(1234.56,"!","?")) local p = Cs( P("-")^0 * (P("0")^1/"")^0 - * (1-P("."))^0 - * (P(".") * P("0")^1 * P(-1)/"" + P(".")^0) - * P(1-P("0")^1*P(-1))^0 + * (1-period)^0 + * (period * P("0")^1 * endofstring/"" + period^0) + * P(1-P("0")^1*endofstring)^0 ) function number.compactfloat(n,fmt) @@ -469,12 +531,11 @@ end local zero = P("0")^1 / "" local plus = P("+") / "" local minus = P("-") -local separator = S(".") -local digit = R("09") +local separator = period local trailing = zero^1 * #S("eE") -local exponent = (S("eE") * (plus + Cs((minus * zero^0 * P(-1))/"") + minus) * zero^0 * (P(-1) * Cc("0") + P(1)^1)) +local exponent = (S("eE") * (plus + Cs((minus * zero^0 * endofstring)/"") + minus) * zero^0 * (endofstring * Cc("0") + anything^1)) local pattern_a = Cs(minus^0 * digit^1 * (separator/"" * trailing + separator * (trailing + digit)^0) * exponent) -local pattern_b = Cs((exponent + P(1))^0) +local pattern_b = Cs((exponent + anything)^0) function number.sparseexponent(f,n) if not n then @@ -524,62 +585,36 @@ local template = [[ return function(%s) return %s end ]] -local preamble, environment = "", { } - -if oldfashioned then - - preamble = [[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local utfpadding=string.utfpadding -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent -local formattedfloat=number.formattedfloat - ]] - -else - - environment = { - global = global or _G, - lpeg = lpeg, - type = type, - tostring = tostring, - tonumber = tonumber, - format = string.format, - concat = table.concat, - signed = number.signed, - points = number.points, - basepoints = number.basepoints, - utfchar = utf.char, - utfbyte = utf.byte, - lpegmatch = lpeg.match, - nspaces = string.nspaces, - utfpadding = string.utfpadding, - tracedchar = string.tracedchar, - autosingle = string.autosingle, - autodouble = string.autodouble, - sequenced = table.sequenced, - formattednumber = number.formatted, - sparseexponent = number.sparseexponent, - formattedfloat = number.formattedfloat, - } - -end +local preamble = "" + +local environment = { + global = global or _G, + lpeg = lpeg, + type = type, + tostring = tostring, + tonumber = tonumber, + format = string.format, + concat = table.concat, + signed = number.signed, + points = number.points, + basepoints = number.basepoints, + utfchar = utf.char, + utfbyte = utf.byte, + lpegmatch = lpeg.match, + nspaces = string.nspaces, + utfpadding = string.utfpadding, + tracedchar = string.tracedchar, + autosingle = string.autosingle, + autodouble = string.autodouble, + sequenced = table.sequenced, + formattednumber = number.formatted, + sparseexponent = number.sparseexponent, + formattedfloat = number.formattedfloat, + stripzero = lpeg.patterns.stripzero, + stripzeros = lpeg.patterns.stripzeros, + + FORMAT = string.f9, +} -- -- -- @@ -593,10 +628,10 @@ setmetatable(arguments, { __index = end }) -local prefix_any = C((S("+- .") + R("09"))^0) -local prefix_sub = (C((S("+-") + R("09"))^0) + Cc(0)) - * P(".") - * (C((S("+-") + R("09"))^0) + Cc(0)) +local prefix_any = C((sign + space + period + digit)^0) +local prefix_sub = (C((sign + digit)^0) + Cc(0)) + * period + * (C((sign + digit)^0) + Cc(0)) local prefix_tab = P("{") * C((1-P("}"))^0) * P("}") + C((1-R("az","AZ","09","%%"))^0) -- we've split all cases as then we can optimize them (let's omit the fuzzy u) @@ -697,6 +732,17 @@ local format_F = function(f) -- beware, no cast to number end end +-- if string.f9 then +-- format_F = function(f) -- beware, no cast to number +-- n = n + 1 +-- if not f or f == "" then +-- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or FORMAT(a%s))",n,n,n,n,n) +-- else +-- return format("((a%s %% 1 == 0) and format('%%i',a%s) or FORMAT(a%s,'%%%sf'))",n,n,n,f) +-- end +-- end +-- end + local format_k = function(b,a) -- slow n = n + 1 return format("formattedfloat(a%s,%i,%i)",n,b or 0, a or 0) @@ -840,9 +886,43 @@ local format_L = function() return format("(a%s and 'TRUE' or 'FALSE')",n) end -local format_N = function() -- strips leading zeros +local format_n = function() -- strips leading and trailing zeros and removes .0 + n = n + 1 + return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) +end + +-- local format_N = function() -- strips leading and trailing zeros (also accepts string) +-- n = n + 1 +-- return format("tostring(tonumber(a%s) or a%s)",n,n) +-- end + +-- local format_N = function(f) -- strips leading and trailing zeros +-- n = n + 1 +-- -- stripzero (singular) as we only have a number +-- if not f or f == "" then +-- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or ((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%.9f',a%s)))",n,n,n,n,n) +-- else +-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) +-- end +-- end + +-- local format_N = function(f) -- strips leading and trailing zeros +-- n = n + 1 +-- -- stripzero (singular) as we only have a number +-- if not f or f == "" then +-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or ((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or lpegmatch(stripzero,format('%%.9f',a%s)))",n,n,n,n,n) +-- else +-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) +-- end +-- end + +local format_N = function(f) -- strips leading and trailing zeros n = n + 1 - return format("tostring(tonumber(a%s) or a%s)",n,n) + -- stripzero (singular) as we only have a number + if not f or f == "" then + f = ".9" + end -- always a leading number ! + return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) end local format_a = function(f) @@ -882,7 +962,11 @@ local format_m = function(f) if not f or f == "" then f = "," end - return format([[formattednumber(a%s,%q,".")]],n,f) + if f == "0" then + return format([[formattednumber(a%s,false)]],n) + else + return format([[formattednumber(a%s,%q,".")]],n,f) + end end local format_M = function(f) @@ -890,7 +974,11 @@ local format_M = function(f) if not f or f == "" then f = "." end - return format([[formattednumber(a%s,%q,",")]],n,f) + if f == "0" then + return format([[formattednumber(a%s,false)]],n) + else + return format([[formattednumber(a%s,%q,",")]],n,f) + end end -- @@ -902,42 +990,100 @@ end -- +-- local strip +-- +-- local format_Z = function(f) +-- n = n + 1 +-- if not f or f == "" then +-- f = ".9" +-- end +-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or (strip and lpegmatch(stripzero,format('%%%sf',a%s))) or format('%%%sf',a%s))",n,n,f,n,f,n) +-- end +-- +-- function strings.stripformatterzeros() +-- strip = true +-- end + +-- add(formatters,"texexp", [[texexp(...)]], "local texexp = metapost.texexp") +-- +-- add(formatters,"foo:bar",[[foo(...)]], { foo = function(...) print(...) return "!" end }) +-- print(string.formatters["foo %3!foo:bar! bar"](1,2,3)) + + local format_rest = function(s) return format("%q",s) -- catches " and \n and such end +-- local format_extension = function(extensions,f,name) +-- local extension = extensions[name] or "tostring(%s)" +-- local f = tonumber(f) or 1 +-- local w = find(extension,"%.%.%.") +-- if f == 0 then +-- if w then +-- extension = gsub(extension,"%.%.%.","") +-- end +-- return extension +-- elseif f == 1 then +-- if w then +-- extension = gsub(extension,"%.%.%.","%%s") +-- end +-- n = n + 1 +-- local a = "a" .. n +-- return format(extension,a,a) -- maybe more times? +-- elseif f < 0 then +-- local a = "a" .. (n + f + 1) +-- return format(extension,a,a) +-- else +-- if w then +-- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") +-- end +-- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we +-- -- cache we don't save much and there are hardly any extensions anyway +-- local t = { } +-- for i=1,f do +-- n = n + 1 +-- -- t[#t+1] = "a" .. n +-- t[i] = "a" .. n +-- end +-- return format(extension,unpack(t)) +-- end +-- end + local format_extension = function(extensions,f,name) local extension = extensions[name] or "tostring(%s)" local f = tonumber(f) or 1 local w = find(extension,"%.%.%.") - if f == 0 then - if w then + if w then + -- we have a wildcard + if f == 0 then extension = gsub(extension,"%.%.%.","") - end - return extension - elseif f == 1 then - if w then + return extension + elseif f == 1 then extension = gsub(extension,"%.%.%.","%%s") - end - n = n + 1 - local a = "a" .. n - return format(extension,a,a) -- maybe more times? - elseif f < 0 then - local a = "a" .. (n + f + 1) - return format(extension,a,a) - else - if w then + n = n + 1 + local a = "a" .. n + return format(extension,a,a) -- maybe more times? + elseif f < 0 then + local a = "a" .. (n + f + 1) + return format(extension,a,a) + else extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") + -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we + -- cache we don't save much and there are hardly any extensions anyway + local t = { } + for i=1,f do + n = n + 1 + -- t[#t+1] = "a" .. n + t[i] = "a" .. n + end + return format(extension,unpack(t)) end - -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we - -- cache we don't save much and there are hardly any extensions anyway - local t = { } - for i=1,f do + else + extension = gsub(extension,"%%s",function() n = n + 1 - -- t[#t+1] = "a" .. n - t[i] = "a" .. n - end - return format(extension,unpack(t)) + return "a" .. n + end) + return extension end end @@ -962,6 +1108,7 @@ local builder = Cs { "start", + V("C") + V("S") -- new + V("Q") -- new + + V("n") -- new + V("N") -- new + V("k") -- new -- @@ -986,7 +1133,7 @@ local builder = Cs { "start", ) + V("*") ) - * (P(-1) + Carg(1)) + * (endofstring + Carg(1)) )^0, -- ["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string) @@ -1005,7 +1152,8 @@ local builder = Cs { "start", -- ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring) ["Q"] = (prefix_any * P("Q")) / format_Q, -- %Q => %q (tostring) - ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros) + ["n"] = (prefix_any * P("n")) / format_n, -- %n => tonumber (strips leading and trailing zeros, as well as .0, expects number) + ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading and trailing zeros, also takes string) ["k"] = (prefix_sub * P("k")) / format_k, -- %k => like f but with n.m ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character @@ -1029,10 +1177,11 @@ local builder = Cs { "start", ["j"] = (prefix_any * P("j")) / format_j, -- %j => %e (float) stripped exponent (irrational) ["J"] = (prefix_any * P("J")) / format_J, -- %J => %E (float) stripped exponent (irrational) -- - ["m"] = (prefix_tab * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .) - ["M"] = (prefix_tab * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) + ["m"] = (prefix_any * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .) + ["M"] = (prefix_any * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,) -- ["z"] = (prefix_any * P("z")) / format_z, -- %z => skip n arguments + -- ["Z"] = (prefix_any * P("Z")) / format_Z, -- %Z => optionally strip zeros -- ["a"] = (prefix_any * P("a")) / format_a, -- %a => '...' (forces tostring) ["A"] = (prefix_any * P("A")) / format_A, -- %A => "..." (forces tostring) @@ -1057,7 +1206,7 @@ local preset = { } local direct = - P("%") * (S("+- .") + R("09"))^0 * S("sqidfgGeExXo") * P(-1) + P("%") * (sign + space + period + digit)^0 * S("sqidfgGeExXo") * endofstring / [[local format = string.format return function(str) return format("%0",str) end]] local function make(t,str) @@ -1134,36 +1283,22 @@ strings.formatters = { } -- _connector_ is an experiment -if oldfashioned then - - function strings.formatters.new(noconcat) - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = preamble, _environment_ = { } } - setmetatable(t, { __index = make, __call = use }) - return t +function strings.formatters.new(noconcat) + local e = { } -- better make a copy as we can overload + for k, v in next, environment do + e[k] = v end - -else - - function strings.formatters.new(noconcat) - local e = { } -- better make a copy as we can overload - for k, v in next, environment do - e[k] = v - end - local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = "", _environment_ = e } - setmetatable(t, { __index = make, __call = use }) - return t - end - + local t = { + _type_ = "formatter", + _connector_ = noconcat and "," or "..", + _extensions_ = { }, + _preamble_ = "", + _environment_ = e, + } + setmetatable(t, { __index = make, __call = use }) + return t end --- function strings.formatters.new() --- local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter", _n_ = 0 } --- local m = { _t_ = t } --- setmetatable(t, { __index = m, __call = use }) --- setmetatable(m, { __index = make }) --- return t --- end - local formatters = strings.formatters.new() -- the default instance string.formatters = formatters -- in the main string namespace @@ -1186,27 +1321,17 @@ strings.formatters.add = add -- registered in the default instance (should we fall back on this one?) -patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + P(1))^0) -patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0) +patterns.xmlescape = Cs((P("<")/"<" + P(">")/">" + P("&")/"&" + P('"')/""" + anything)^0) +patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + anything)^0) patterns.luaescape = Cs(((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0) -- maybe also \0 patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0 * Cc('"')) -- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but -- faster again when other q-escapables are found (the ones we don't need to escape) -if oldfashioned then - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") - -else - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape }) - -end +add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape }) +add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape }) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape }) -- -- yes or no: -- @@ -1243,7 +1368,6 @@ end local dquote = patterns.dquote -- P('"') local equote = patterns.escaped + dquote / '\\"' + 1 -local space = patterns.space local cquote = Cc('"') local pattern = @@ -1277,3 +1401,11 @@ function strings.newcollector() end end end + +-- + +local f_16_16 = formatters["%0.5N"] + +function number.to16dot16(n) + return f_16_16(n/65536.0) +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua b/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua index 1b069e2ae21..b51c6589a07 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-tab.lua @@ -22,7 +22,8 @@ local utftoeight = utf.toeight local splitter = lpeg.tsplitat(".") function utilities.tables.definetable(target,nofirst,nolast) -- defines undefined tables - local composed, t = nil, { } + local composed = nil + local t = { } local snippets = lpegmatch(splitter,target) for i=1,#snippets - (nolast and 1 or 0) do local name = snippets[i] @@ -819,3 +820,54 @@ if setinspector then end end) end + +-- ordered hashes (for now here but in the table namespace): + +-- local t = table.orderedhash() +-- +-- t["1"] = { "a", "b" } +-- t["2"] = { } +-- t["2a"] = { "a", "c", "d" } +-- +-- for k, v in table.ordered(t) do +-- ... +-- end + +local mt = { + __newindex = function(t,k,v) + local n = t.last + 1 + t.last = n + t.list[n] = k + t.hash[k] = v + end, + __index = function(t,k) + return t.hash[k] + end, + __len = function(t) + return t.last + end, +} + +function table.orderedhash() + return setmetatable({ list = { }, hash = { }, last = 0 }, mt) +end + +function table.ordered(t) + local n = t.last + if n > 0 then + local l = t.list + local i = 1 + local h = t.hash + local f = function() + if i <= n then + local k = i + local v = h[l[k]] + i = i + 1 + return k, v + end + end + return f, 1, h[l[1]] + else + return function() end + end +end diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-you.lua b/Master/texmf-dist/tex/context/base/mkiv/util-you.lua index 32a7e07d4e9..5802e7d7afd 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/util-you.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/util-you.lua @@ -30,7 +30,6 @@ utilities.youless = youless local lpegmatch = lpeg.match local formatters = string.formatters -local sortedhash = table.sortedhash local tonumber, type, next = tonumber, type, next -- cgit v1.2.3