diff options
author | Hans Hagen <pragma@wxs.nl> | 2021-01-17 22:49:53 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2021-01-17 22:49:53 +0100 |
commit | 95686a1754b3cf4f1410d6a52aeb86b65033a96c (patch) | |
tree | e5a5b9c091e2722d8bc7b20d3ad0952055b70dab | |
parent | 980ad5b78d69aa8abfb093c7e6729b0024ce0b49 (diff) | |
download | context-95686a1754b3cf4f1410d6a52aeb86b65033a96c.tar.gz |
2021-01-17 21:42:00
91 files changed, 4756 insertions, 1804 deletions
diff --git a/context/data/scite/context/lexers/data/scite-context-data-metafun.lua b/context/data/scite/context/lexers/data/scite-context-data-metafun.lua index d02ed5332..edbf39a57 100644 --- a/context/data/scite/context/lexers/data/scite-context-data-metafun.lua +++ b/context/data/scite/context/lexers/data/scite-context-data-metafun.lua @@ -1,4 +1,4 @@ return { - ["commands"]={ "loadfile", "loadimage", "loadmodule", "dispose", "nothing", "transparency", "tolist", "topath", "tocycle", "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", "tanh", "zmod", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "unittriangle", "fulltriangle", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "uptriangle", "downtriangle", "lefttriangle", "righttriangle", "triangle", "smoothed", "cornered", "superellipsed", "randomized", "randomizedcontrols", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "perpendicular", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "drawdoublearrows", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "boundingradius", "boundingcircle", "boundingpoint", "crossingunder", "insideof", "outsideof", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withcircularshade", "withlinearshade", "defineshade", "shaded", "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "shownshadedirection", "shownshadecenter", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "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", "rawmadetext", "validtexbox", "onetimetextext", "rawfmttext", "thefmttext", "fmttext", "onetimefmttext", "notcached", "keepcached", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "withopacity", "property", "properties", "withproperties", "asgroup", "infont", "space", "crlf", "dquote", "percent", "SPACE", "CRLF", "DQUOTE", "PERCENT", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "colorlike", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedfunction", "constructedpath", "constructedpairs", "straightfunction", "straightpath", "straightpairs", "curvedfunction", "curvedpath", "curvedpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "resetarrows", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "basiccolors", "complementary", "complemented", "resolvedcolor", "normalfill", "normaldraw", "visualizepaths", "detailpaths", "naturalizepaths", "drawboundary", "drawwholepath", "drawpathonly", "visualizeddraw", "visualizedfill", "detaileddraw", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "pencilled", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "topair", "format", "formatted", "quotation", "quote", "startpassingvariable", "stoppassingvariable", "eofill", "eoclip", "nofill", "dofill", "fillup", "eofillup", "nodraw", "dodraw", "area", "addbackground", "shadedup", "shadeddown", "shadedleft", "shadedright", "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", "utflen", "utfsub", "newhash", "disposehash", "inhash", "tohash", "isarray", "prefix", "isobject", "comment", "report", "lua", "lualist", "mp", "MP", "luacall", "mirrored", "mirroredabout", "scriptindex", "newscriptindex", "newcolor", "newrgbcolor", "newcmykcolor", "newnumeric", "newboolean", "newtransform", "newpath", "newpicture", "newstring", "newpair" }, + ["commands"]={ "loadfile", "loadimage", "loadmodule", "dispose", "nothing", "transparency", "tolist", "topath", "tocycle", "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", "tanh", "zmod", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "unittriangle", "fulltriangle", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "uptriangle", "downtriangle", "lefttriangle", "righttriangle", "triangle", "smoothed", "cornered", "superellipsed", "randomized", "randomizedcontrols", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "perpendicular", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "drawdoublearrows", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "boundingradius", "boundingcircle", "boundingpoint", "crossingunder", "insideof", "outsideof", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withcircularshade", "withlinearshade", "defineshade", "shaded", "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "shownshadedirection", "shownshadecenter", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "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", "rawmadetext", "validtexbox", "onetimetextext", "rawfmttext", "thefmttext", "fmttext", "onetimefmttext", "notcached", "keepcached", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "withopacity", "property", "properties", "withproperties", "asgroup", "infont", "space", "crlf", "dquote", "percent", "SPACE", "CRLF", "DQUOTE", "PERCENT", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "colorlike", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedfunction", "constructedpath", "constructedpairs", "straightfunction", "straightpath", "straightpairs", "curvedfunction", "curvedpath", "curvedpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "resetarrows", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "basiccolors", "complementary", "complemented", "resolvedcolor", "normalfill", "normaldraw", "visualizepaths", "detailpaths", "naturalizepaths", "drawboundary", "drawwholepath", "drawpathonly", "visualizeddraw", "visualizedfill", "detaileddraw", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "pencilled", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "topair", "format", "formatted", "quotation", "quote", "startpassingvariable", "stoppassingvariable", "eofill", "eoclip", "nofill", "dofill", "fillup", "eofillup", "nodraw", "dodraw", "area", "addbackground", "shadedup", "shadeddown", "shadedleft", "shadedright", "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", "utfnum", "utflen", "utfsub", "newhash", "disposehash", "inhash", "tohash", "isarray", "prefix", "isobject", "comment", "report", "lua", "lualist", "mp", "MP", "luacall", "mirrored", "mirroredabout", "scriptindex", "newscriptindex", "newcolor", "newrgbcolor", "newcmykcolor", "newnumeric", "newboolean", "newtransform", "newpath", "newpicture", "newstring", "newpair" }, ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "shadeoffset", "textextoffset", "textextanchor", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent", "ahvariant", "ahdimple", "ahfactor", "ahscale", "metapostversion", "maxdimensions", "drawoptionsfactor", "dq", "sq", "crossingscale", "crossingoption", "contextlmtxmode", "metafunversion", "minifunversion", "getparameters", "presetparameters", "hasparameter", "hasoption", "getparameter", "getparameterdefault", "getparametercount", "getmaxparametercount", "getparameterpath", "getparameterpen", "getparametertext", "applyparameters", "pushparameters", "popparameters", "definecolor" }, }
\ No newline at end of file diff --git a/context/data/scite/context/scite-context-data-metafun.properties b/context/data/scite/context/scite-context-data-metafun.properties index ac2a048df..79f8b5087 100644 --- a/context/data/scite/context/scite-context-data-metafun.properties +++ b/context/data/scite/context/scite-context-data-metafun.properties @@ -72,12 +72,13 @@ positionpath positioncurve positionxy positionpxy positionwhd \ positionpage positionregion positionbox positionanchor positioninregion \ positionatanchor wdpart htpart dppart texvar \ texstr inpath pointof leftof rightof \ -utflen utfsub newhash disposehash inhash \ -tohash isarray prefix isobject comment \ -report lua lualist mp MP \ -luacall mirrored mirroredabout scriptindex newscriptindex \ -newcolor newrgbcolor newcmykcolor newnumeric newboolean \ -newtransform newpath newpicture newstring newpair +utfnum utflen utfsub newhash disposehash \ +inhash tohash isarray prefix isobject \ +comment report lua lualist mp \ +MP luacall mirrored mirroredabout scriptindex \ +newscriptindex newcolor newrgbcolor newcmykcolor newnumeric \ +newboolean newtransform newpath newpicture newstring \ +newpair keywordclass.metafun.internals=\ nocolormodel greycolormodel graycolormodel rgbcolormodel \ diff --git a/context/data/textadept/context/data/scite-context-data-metafun.lua b/context/data/textadept/context/data/scite-context-data-metafun.lua index d02ed5332..edbf39a57 100644 --- a/context/data/textadept/context/data/scite-context-data-metafun.lua +++ b/context/data/textadept/context/data/scite-context-data-metafun.lua @@ -1,4 +1,4 @@ return { - ["commands"]={ "loadfile", "loadimage", "loadmodule", "dispose", "nothing", "transparency", "tolist", "topath", "tocycle", "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", "tanh", "zmod", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "unittriangle", "fulltriangle", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "uptriangle", "downtriangle", "lefttriangle", "righttriangle", "triangle", "smoothed", "cornered", "superellipsed", "randomized", "randomizedcontrols", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "perpendicular", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "drawdoublearrows", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "boundingradius", "boundingcircle", "boundingpoint", "crossingunder", "insideof", "outsideof", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withcircularshade", "withlinearshade", "defineshade", "shaded", "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "shownshadedirection", "shownshadecenter", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "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", "rawmadetext", "validtexbox", "onetimetextext", "rawfmttext", "thefmttext", "fmttext", "onetimefmttext", "notcached", "keepcached", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "withopacity", "property", "properties", "withproperties", "asgroup", "infont", "space", "crlf", "dquote", "percent", "SPACE", "CRLF", "DQUOTE", "PERCENT", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "colorlike", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedfunction", "constructedpath", "constructedpairs", "straightfunction", "straightpath", "straightpairs", "curvedfunction", "curvedpath", "curvedpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "resetarrows", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "basiccolors", "complementary", "complemented", "resolvedcolor", "normalfill", "normaldraw", "visualizepaths", "detailpaths", "naturalizepaths", "drawboundary", "drawwholepath", "drawpathonly", "visualizeddraw", "visualizedfill", "detaileddraw", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "pencilled", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "topair", "format", "formatted", "quotation", "quote", "startpassingvariable", "stoppassingvariable", "eofill", "eoclip", "nofill", "dofill", "fillup", "eofillup", "nodraw", "dodraw", "area", "addbackground", "shadedup", "shadeddown", "shadedleft", "shadedright", "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", "utflen", "utfsub", "newhash", "disposehash", "inhash", "tohash", "isarray", "prefix", "isobject", "comment", "report", "lua", "lualist", "mp", "MP", "luacall", "mirrored", "mirroredabout", "scriptindex", "newscriptindex", "newcolor", "newrgbcolor", "newcmykcolor", "newnumeric", "newboolean", "newtransform", "newpath", "newpicture", "newstring", "newpair" }, + ["commands"]={ "loadfile", "loadimage", "loadmodule", "dispose", "nothing", "transparency", "tolist", "topath", "tocycle", "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", "tanh", "zmod", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "unittriangle", "fulltriangle", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "uptriangle", "downtriangle", "lefttriangle", "righttriangle", "triangle", "smoothed", "cornered", "superellipsed", "randomized", "randomizedcontrols", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "perpendicular", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "drawdoublearrows", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "boundingradius", "boundingcircle", "boundingpoint", "crossingunder", "insideof", "outsideof", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withcircularshade", "withlinearshade", "defineshade", "shaded", "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "shownshadedirection", "shownshadecenter", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "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", "rawmadetext", "validtexbox", "onetimetextext", "rawfmttext", "thefmttext", "fmttext", "onetimefmttext", "notcached", "keepcached", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "withopacity", "property", "properties", "withproperties", "asgroup", "infont", "space", "crlf", "dquote", "percent", "SPACE", "CRLF", "DQUOTE", "PERCENT", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "colorlike", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedfunction", "constructedpath", "constructedpairs", "straightfunction", "straightpath", "straightpairs", "curvedfunction", "curvedpath", "curvedpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "resetarrows", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "basiccolors", "complementary", "complemented", "resolvedcolor", "normalfill", "normaldraw", "visualizepaths", "detailpaths", "naturalizepaths", "drawboundary", "drawwholepath", "drawpathonly", "visualizeddraw", "visualizedfill", "detaileddraw", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "pencilled", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "topair", "format", "formatted", "quotation", "quote", "startpassingvariable", "stoppassingvariable", "eofill", "eoclip", "nofill", "dofill", "fillup", "eofillup", "nodraw", "dodraw", "area", "addbackground", "shadedup", "shadeddown", "shadedleft", "shadedright", "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", "utfnum", "utflen", "utfsub", "newhash", "disposehash", "inhash", "tohash", "isarray", "prefix", "isobject", "comment", "report", "lua", "lualist", "mp", "MP", "luacall", "mirrored", "mirroredabout", "scriptindex", "newscriptindex", "newcolor", "newrgbcolor", "newcmykcolor", "newnumeric", "newboolean", "newtransform", "newpath", "newpicture", "newstring", "newpair" }, ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "shadeoffset", "textextoffset", "textextanchor", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent", "ahvariant", "ahdimple", "ahfactor", "ahscale", "metapostversion", "maxdimensions", "drawoptionsfactor", "dq", "sq", "crossingscale", "crossingoption", "contextlmtxmode", "metafunversion", "minifunversion", "getparameters", "presetparameters", "hasparameter", "hasoption", "getparameter", "getparameterdefault", "getparametercount", "getmaxparametercount", "getparameterpath", "getparameterpen", "getparametertext", "applyparameters", "pushparameters", "popparameters", "definecolor" }, }
\ No newline at end of file diff --git a/context/data/vscode/extensions/context/syntaxes/context-syntax-mps.json b/context/data/vscode/extensions/context/syntaxes/context-syntax-mps.json index 9000bd62f..29bb24058 100644 --- a/context/data/vscode/extensions/context/syntaxes/context-syntax-mps.json +++ b/context/data/vscode/extensions/context/syntaxes/context-syntax-mps.json @@ -60,7 +60,7 @@ "name" : "context.extra" }, "helper" : { - "match" : "(zmod|ystretched|ysized|xysized|xyscaled|xstretched|xsized|withtransparency|withshadevector|withshadetransform|withshadestep|withshaderadius|withshadeorigin|withshademethod|withshadefraction|withshadefactor|withshadedomain|withshadedirection|withshadecolors|withshadecenter|withshade|withproperties|withopacity|withmask|withlinearshade|withgrey|withgray|withcircularshade|whitecolor|wdpart|visualizepaths|visualizedfill|visualizeddraw|verbatim|validtexbox|utfsub|utflen|urtriangle|urmoved|urenlarged|urcircle|uptriangle|unspiked|unitvector|unittriangle|unitdiamond|unitcircle|uniquelist|undrawfill|undecorated|undashed|uncolored|ultriangle|ulmoved|ulenlarged|ulcircle|tripled|triangle|transparent|transparency|tostring|topenlarged|topboundary|topath|topair|tolist|tohash|tocycle|thetextext|thetexbox|theoffset|thelabel|thefmttext|texvar|texvar|textextoffset|textext|texstr|texstr|texmode|texbox|tensecircle|tcircle|tanh|tand|tan|systemmode|superellipsed|strut|stretched|straightpath|straightpairs|straightfunction|stoppassingvariable|startpassingvariable|squeezed|squarepath|sqr|spotcolor|space|sortlist|softened|snapped|smoothed|sized|sinh|sin|simplified|shownshadevector|shownshadeorigin|shownshadedirection|shownshadecenter|shortened|shapedlist|shadedup|shadedright|shadedleft|shadedinto|shadeddown|shaded|settoks|setmacro|setdimen|setcount|scriptindex|rule|roundedsquare|righttriangle|rightof|rightenlarged|rightboundary|rightarrow|resolvedcolor|resetdrawoptions|resetarrows|report|register|redecorated|readfile|rcircle|rawtextext|rawtexbox|rawmadetext|rawfmttext|randomshifted|randomizedcontrols|randomized|radian|quote|quotation|pushcurrentpicture|pushboundingbox|punked|property|properties|prefix|prefix|pow|positionxy|positionwhd|positionregion|positionpxy|positionpath|positionpage|positioninregion|positioncurve|positionbox|positionatanchor|positionanchor|popcurrentpicture|popboundingbox|pointof|pi|perpendicular|percent|penpoint|pencilled|peepholed|pathconnectors|passvariable|passarrayvariable|paralleled|paired|outsideof|outlinetexttopath|outlinetext|outerboundingbox|originpath|onlayer|onetimetextext|onetimefmttext|oddly|nothing|notcached|normalfill|normaldraw|nofill|nodraw|newtransform|newstring|newscriptindex|newrgbcolor|newpicture|newpath|newpair|newnumeric|newhash|newcolor|newcmykcolor|newboolean|naturalizepaths|namedcolor|multitonecolor|mp|mirroredabout|mirrored|lualist|luacall|lua|lrtriangle|lrmoved|lrenlarged|lrcircle|log|loadmodule|loadimage|loadfile|loadfigure|ln|lltriangle|llmoved|llenlarged|llcircle|listtolines|listtocurves|listsize|listlast|linearpath|lefttriangle|leftof|leftenlarged|leftboundary|leftarrow|lcircle|laddered|label|keepcached|istextext|isobject|isarray|isarray|invtan|invsin|inverted|invcos|inv|intersection_point|intersection_found|interpolated|insideof|inpath|innerboundingbox|inhash|infont|infinite|htpart|greyscale|greyed|grayscale|grayed|graphictext|gettoks|getmacro|getdimen|getcount|function|fulltriangle|fullsquare|fulldiamond|formatted|format|fmttext|fillup|filloutlinetext|figure|externalfigure|exp|evenly|epsed|eofillup|eofill|eoclip|enlonged|enlarged|drawwholepath|drawpoints|drawpointoptions|drawpointlabels|drawpoint|drawpathoptions|drawpathonly|drawpath|drawoutlinetext|draworiginoptions|draworigin|drawlineoptions|drawlabeloptions|drawfill|drawdoublearrows|drawcontrolpoints|drawcontroloptions|drawcontrollines|drawboundoptions|drawboundingbox|drawboundary|dquote|dppart|downtriangle|dofill|dodraw|disposehash|dispose|dimension|detailpaths|detaileddraw|defineshade|decorated|ddecimal|dddecimal|ddddecimal|cutends|curvedpath|curvedpairs|curvedfunction|curved|crossingunder|crossed|crlf|cotd|cot|cosh|cos|cornered|copylist|constructedpath|constructedpairs|constructedfunction|condition|complemented|complementary|comment|colortype|colorpart|colorlike|colordecimalslist|colordecimals|cmyk|clearxy|circularpath|checkedbounds|checkbounds|centerarrow|center|break|boundingradius|boundingpoint|boundingcircle|boundingbox|bottomenlarged|bottomboundary|blownup|blackcolor|bitmapimage|bcircle|bbwidth|bbheight|basiccolors|autoalign|atan|asinh|asin|asgroup|arrowpath|area|anchored|along|addbackground|acosh|acos|SPACE|PERCENT|MP|DQUOTE|CRLF)(?=[^a-zA-Z\u005C_@!?-ÿ])", + "match" : "(zmod|ystretched|ysized|xysized|xyscaled|xstretched|xsized|withtransparency|withshadevector|withshadetransform|withshadestep|withshaderadius|withshadeorigin|withshademethod|withshadefraction|withshadefactor|withshadedomain|withshadedirection|withshadecolors|withshadecenter|withshade|withproperties|withopacity|withmask|withlinearshade|withgrey|withgray|withcircularshade|whitecolor|wdpart|visualizepaths|visualizedfill|visualizeddraw|verbatim|validtexbox|utfsub|utfnum|utflen|urtriangle|urmoved|urenlarged|urcircle|uptriangle|unspiked|unitvector|unittriangle|unitdiamond|unitcircle|uniquelist|undrawfill|undecorated|undashed|uncolored|ultriangle|ulmoved|ulenlarged|ulcircle|tripled|triangle|transparent|transparency|tostring|topenlarged|topboundary|topath|topair|tolist|tohash|tocycle|thetextext|thetexbox|theoffset|thelabel|thefmttext|texvar|texvar|textextoffset|textext|texstr|texstr|texmode|texbox|tensecircle|tcircle|tanh|tand|tan|systemmode|superellipsed|strut|stretched|straightpath|straightpairs|straightfunction|stoppassingvariable|startpassingvariable|squeezed|squarepath|sqr|spotcolor|space|sortlist|softened|snapped|smoothed|sized|sinh|sin|simplified|shownshadevector|shownshadeorigin|shownshadedirection|shownshadecenter|shortened|shapedlist|shadedup|shadedright|shadedleft|shadedinto|shadeddown|shaded|settoks|setmacro|setdimen|setcount|scriptindex|rule|roundedsquare|righttriangle|rightof|rightenlarged|rightboundary|rightarrow|resolvedcolor|resetdrawoptions|resetarrows|report|register|redecorated|readfile|rcircle|rawtextext|rawtexbox|rawmadetext|rawfmttext|randomshifted|randomizedcontrols|randomized|radian|quote|quotation|pushcurrentpicture|pushboundingbox|punked|property|properties|prefix|prefix|pow|positionxy|positionwhd|positionregion|positionpxy|positionpath|positionpage|positioninregion|positioncurve|positionbox|positionatanchor|positionanchor|popcurrentpicture|popboundingbox|pointof|pi|perpendicular|percent|penpoint|pencilled|peepholed|pathconnectors|passvariable|passarrayvariable|paralleled|paired|outsideof|outlinetexttopath|outlinetext|outerboundingbox|originpath|onlayer|onetimetextext|onetimefmttext|oddly|nothing|notcached|normalfill|normaldraw|nofill|nodraw|newtransform|newstring|newscriptindex|newrgbcolor|newpicture|newpath|newpair|newnumeric|newhash|newcolor|newcmykcolor|newboolean|naturalizepaths|namedcolor|multitonecolor|mp|mirroredabout|mirrored|lualist|luacall|lua|lrtriangle|lrmoved|lrenlarged|lrcircle|log|loadmodule|loadimage|loadfile|loadfigure|ln|lltriangle|llmoved|llenlarged|llcircle|listtolines|listtocurves|listsize|listlast|linearpath|lefttriangle|leftof|leftenlarged|leftboundary|leftarrow|lcircle|laddered|label|keepcached|istextext|isobject|isarray|isarray|invtan|invsin|inverted|invcos|inv|intersection_point|intersection_found|interpolated|insideof|inpath|innerboundingbox|inhash|infont|infinite|htpart|greyscale|greyed|grayscale|grayed|graphictext|gettoks|getmacro|getdimen|getcount|function|fulltriangle|fullsquare|fulldiamond|formatted|format|fmttext|fillup|filloutlinetext|figure|externalfigure|exp|evenly|epsed|eofillup|eofill|eoclip|enlonged|enlarged|drawwholepath|drawpoints|drawpointoptions|drawpointlabels|drawpoint|drawpathoptions|drawpathonly|drawpath|drawoutlinetext|draworiginoptions|draworigin|drawlineoptions|drawlabeloptions|drawfill|drawdoublearrows|drawcontrolpoints|drawcontroloptions|drawcontrollines|drawboundoptions|drawboundingbox|drawboundary|dquote|dppart|downtriangle|dofill|dodraw|disposehash|dispose|dimension|detailpaths|detaileddraw|defineshade|decorated|ddecimal|dddecimal|ddddecimal|cutends|curvedpath|curvedpairs|curvedfunction|curved|crossingunder|crossed|crlf|cotd|cot|cosh|cos|cornered|copylist|constructedpath|constructedpairs|constructedfunction|condition|complemented|complementary|comment|colortype|colorpart|colorlike|colordecimalslist|colordecimals|cmyk|clearxy|circularpath|checkedbounds|checkbounds|centerarrow|center|break|boundingradius|boundingpoint|boundingcircle|boundingbox|bottomenlarged|bottomboundary|blownup|blackcolor|bitmapimage|bcircle|bbwidth|bbheight|basiccolors|autoalign|atan|asinh|asin|asgroup|arrowpath|area|anchored|along|addbackground|acosh|acos|SPACE|PERCENT|MP|DQUOTE|CRLF)(?=[^a-zA-Z\u005C_@!?-ÿ])", "name" : "context.command.metafun.helper.mps" }, "identifier" : { diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf Binary files differindex 635e56000..f5ece94d6 100644 --- a/doc/context/documents/general/manuals/luametatex.pdf +++ b/doc/context/documents/general/manuals/luametatex.pdf diff --git a/doc/context/sources/general/manuals/followingup/followingup-fonts.tex b/doc/context/sources/general/manuals/followingup/followingup-fonts.tex index 2f7320b12..6bc10e929 100644 --- a/doc/context/sources/general/manuals/followingup/followingup-fonts.tex +++ b/doc/context/sources/general/manuals/followingup/followingup-fonts.tex @@ -23,7 +23,24 @@ Fonts come in sizes, and for instance Latin Modern has quite a few variants wher the shapes are adapted to the size. This means that when you need a 9pt regular shape alongside a 12pt one, two fonts have to be loaded. This is quite visible in math where we have three related sizes: text, script and scriptscript, grouped in -so called families. +so called families. When we scale the digit~2 to the same height you will notice +that the text, script and scriptscript sizes look different (the last three are +unscaled): + +\startlinecorrection +\dontleavehmode\scale[frame=on,height=5ex]{$\textstyle 2$}\quad +\dontleavehmode\scale[frame=on,height=5ex]{$\scriptstyle 2$}\quad +\dontleavehmode\scale[frame=on,height=5ex]{$\scriptscriptstyle 2$}\quad\quad +\dontleavehmode\scale[frame=on,height=2ex]{$\textstyle 2$}\quad +\dontleavehmode\scale[frame=on,height=2ex]{$\scriptstyle 2$}\quad +\dontleavehmode\scale[frame=on,height=2ex]{$\scriptscriptstyle 2$}\quad\quad +\dontleavehmode\scale[frame=on,width=4em]{\colored[r=.6,a=1,t=.5]{$\textstyle 2$}}\hskip-4em +\dontleavehmode\scale[frame=on,width=4em]{\colored[g=.6,a=1,t=.5]{$\scriptstyle 2$}}\hskip-4em +\dontleavehmode\scale[frame=on,width=4em]{\colored[b=.6,a=1,t=.5]{$\scriptscriptstyle 2$}}\quad\quad +\dontleavehmode{$\textstyle 2$}\quad +\dontleavehmode{$\scriptstyle 2$}\quad +\dontleavehmode{$\scriptscriptstyle 2$}\quad +\stoplinecorrection Plenty has been written (in various documents that come with \CONTEXT) about how this all works together and how it impacts the design of the system, so here I @@ -34,62 +51,82 @@ just give a short summary of what a font system has to deal with. In a bodyfont setup different sizes (9pt, 10pt, 12pt) can have their own specific set of fonts. This can result in quite some definitions that relate to the style, like regular, bold, italic, bolditalic, slanted and - boldslanted, etc. When possible loading the fonts is delayed. + boldslanted, etc. When possible loading the fonts is delayed. But in + \CONTEXT\ often the number of actually loaded fonts is not that large. \stopitem \startitem Some font designs have different shapes per bodyfont size. A minor - complication is that when one is missing some heuristic best match choice - might be needed. + complication is that when one is missing some heuristic best|-|match choice + might be needed. Okay, in practice only Latin Modern falls into this + category. Maybe \OPENTYPE\ variable fonts can be seen this way, but, although + we supported that right from the start, I haven't noticed much interest in + the \TEX\ community. \stopitem \startitem Within a bodyfont size we distinguish size variants. We can go smaller (x and xx), for instance when we use sub- and superscripts in text, or we can go - larger, for instance in titling (a, b, c, d, \unknown). Fortunately most of + larger, for instance in titles (a, b, c, d, \unknown). Fortunately most of the loading of these can be delayed too. \stopitem \startitem When instances are not available, scaling can be used, as happens for instance with 11pt in Computer Modern. Actually, this is why in \CONTEXT\ we default to 12pt, because the scaled versions didn't look as nice as the - others. + others (keep in mind that we started in the age of bitmaps). \stopitem \startitem Special features, like smallcaps or oldstyle numerals, can demand their own definitions. More loading and automatic definitions can be triggered by sizes - needed in for instance scripts and titling. + needed in for instance scripts and titles. \stopitem \startitem A document can have a mixed setup, that is: use different font designs in one document, so some kind of namespace subsystem is needed. \stopitem \startitem - In traditional eight bit engine the dependency of hyphenation on the encoding - of a font can result in the necessity to load a font multiple times in - different encodings, something that depends on the language mix used. + In an eight bit font world, we not only have text fonts but also collections + of symbols, and even in math there are additional symbol collections. In + \OPENTYPE\ symbols end up in text fonts, but there we have tons of emoji's + and color fonts. All has to be dealt with in an integrated way. And we're + not even talking of virtual fonts, (runtime) \METAPOST\ generated fonts, and + so on. +\stopitem +\startitem + In traditional eight bit engines the dependency of hyphenation on the + encoding of a font can result in the necessity to load a font multiple times + in different encodings, something that depends on the language mix used. + Interesting is that coming up with an European encoding (covering most Latin + languages) was not that hard, especially when one keeps in mind that many + eight bit encodings waste slots on seldom used symbols, but by that time + \OPENTYPE\ and and \UNICODE\ input started to dominate. \stopitem \startitem In the more modern \OPENTYPE\ fonts combinations of features can demand - additional instances (one can thing of language|/|script combinations, + additional instances (one can think of language|/|script combinations, substitutions in base mode, special effects like boldening, color fonts, etc.). \stopitem \startitem - Math is complicated by the fact that alphabets come from different fonts - (sometimes a font has several alphabets which means that some mapping can be - needed). Operating on the size, shape, encoding and style axes puts some - demands on the font system. Add to this (often) partial (due to lack of - fonts) bold support and it gets even more complicated. + Math is complicated by the fact that in traditional \TEX\ alphabets come from + different fonts which is why we have many so called families; sometimes a + font has several alphabets which means that some mapping can be needed. + Operating on the size, shape, encoding and style axes puts some demands on + the font system. Add to this (often) partial (due to lack of fonts) bold + support and it gets even more complicated. In \OPENTYPE\ all the alphabets + come from one font. \stopitem \startitem There is additional math auto|-|definition and loading code for the sizes - used in text scripts and titling. + used in text scripts and titles. \stopitem \stopitemize All this has resulted in a pretty complex subsystem. Although going \OPENTYPE\ (and emulated \OPENTYPE\ with \TYPEONE\ fonts as we do in \MKIV) removes some complications, like encodings, it does also add complexity because of the many -possible font features, either or not dependent on script and language. +possible font features, either or not dependent on script and language. Text as +well as math got simpler at the \TEX\ end (but that is compensated by quite a bit +\LUA\ code that deals with new features). Also, in order to let a font subsystem not impact performance to much, let alone extensive memory usage, the \CONTEXT\ font subsystem is rather optimized. The @@ -102,26 +139,27 @@ always been rather fast. \startsection[title={Reality}] In \MKIV\ and therefore also in \LMTX\ more font magic happens. The initial node -lists that makes up a box or paragraph can get manipulated in several ways and -often fonts are involved. The mentioned font features can be defines static (as -part of the definition) or dynamic (resolved on the spot at the cost of some -overhead). Characters can be remapped, fonts can be replaced. The math subsystem -in \MKIV\ was different right from the start: we use a limited number of families -(regular, bold, l2r and r2l), and stay abstract till the moment we need to deal -with the specific alphabets. But still, in \MKIV, we have the families with three -fonts. +lists that make up a box or paragraph can get manipulated in several ways and +often fonts are involved. The font features (smallcaps, oldstyle, alternates, +etc.) can be defined static (as part of the definition) or dynamic (resolved on +the spot at the cost of some overhead). Characters can be remapped, fonts can be +replaced. The math subsystem in \MKIV\ was different right from the start: we use +a limited number of families (regular, bold, l2r and r2l), and stay abstract till +the moment we need to deal with the specific alphabets. But still, in \MKIV, we +have the families with three fonts. In the \LUAMETATEX\ manual we show some math magic and we do so for different -fonts. As a side effect, we set up half a dozen bodyfont collections. Even with -delayed and shared font loading, we end up with 158 instances but quite a bit of -them are math fonts, at least six per bodyfont size: regular and bold (boldened) -text, script and scriptscript. Of course most are just copies with different -scaling that reuse already loaded resources. +fonts. As a side effect, we set up half a dozen bodyfont collections: Lucida, +Pagella, Latin Modern, Dejavu, the math standard Cambria, etc. Even with delayed +and shared font loading, we end up with 158 instances but quite a bit of them are +math fonts, at least six per bodyfont size: regular and bold (boldened) text, +script and scriptscript. Of course most are just copies with different scaling +that reuse already loaded resources. In the final\PDF\ we have 21 subset fonts. If we look at the math fonts that we use today, there is however quite some overlap. It starts with a text font. From that script and scriptscript variants are derived, but often these variants use many text size related shapes too. Some -shapes get alternatives (from the \type {ssty} feature), and the whole clone get +shapes get alternatives (from the \type {ssty} feature), and the whole clone gets scaled. But, much of the logic of for instance extensibles is the same. A similar situation happens with for instance large \CJK\ fonts: there are hardly @@ -130,19 +168,25 @@ dimensions, and these fonts can be real huge! Actually, when we talk about features, in many cases in \CONTEXT\ you don't define them as part of the font. For instance small caps can best be triggered by -using a dynamic feature: applied to a specific stretch of text. When the font -handler does its work there are actually four cases: no features get applied, -something that for instance happens with most monospaced fonts, base mode is -used, which means that the \TEX\ machinery takes care of constructing ligatures -and injecting kerns, and node mode, where \LUA\ handles the features. The fourth -case is a special case of node mode where a different features set is applied. -\footnote {We also have so called plug mode where an external rendered can do the -work but that one is only around for some experiments during Idris' font -development.} At the cost of some extra overhead (for each node mode run) dynamic -features are quite powerful and save quite some memory and definitions. The -overhead comes from much more testing regarding the font we deal with because -suddenly the same font can demand different treatments, depending on what dynamic -features is active. +using a dynamic feature: applied to a specific stretch of text. In fact, often +features like superiors of fractions only work well on characters that fit the +bill and produce weird side effects otherwise (a matter of design completeness). +When the font handler does its work there are actually four cases: no features +get applied, something that for instance happens with most mono spaced fonts, +base mode is used, which means that the \TEX\ machinery takes care of +constructing ligatures and injecting kerns, and node mode, where \LUA\ handles +the features. The fourth case is a special case of node mode where a different +feature set is applied. \footnote {We also have so called plug mode where an +external renderer can do the work but that one is only around for some +experiments during Idris Hamid's font development.} At the cost of some extra +overhead (for each node mode run) dynamic features are quite powerful and save +quite some memory and definitions. \footnote {The generic font handler that is +derived from the \CONTEXT\ one doesn't implement this so it runs a little +faster.} The overhead comes from much more testing regarding the font we deal +with because suddenly the same font can demand different treatments, depending on +what dynamic features are active. \footnote {Originally this model was introduced +for a dynamic paragraph optimization subsystem for Arabic but no one really uses +it because there there are no suitable fonts.} Although the font handling is responsible for much of the time spent in \LUA, it is still reasonable given what has to be done. Actually, because we have an extensible @@ -183,8 +227,8 @@ e{\glyphxscale 2500 ffi}cient So, in order to deal with this kind of scaling, we now operate not only on the font (id) and dynamic feature axes, but also on the scales of which we have three -variants: glyph scale, glyph xscale and glyph y scale). There is actually also a -state dimension but we leave that for now. Think of flagging glyphs as initial or +variants: glyph scale, glyph xscale and glyph yscale). There is actually also a +state dimension but we leave that for now; think of flagging glyphs as initial or final. This brings the number of axis to six. It is important to stress that in these examples the same font instance is used! @@ -197,22 +241,22 @@ go together but for now I see no real gain in that. \startsection[title={Math}] -Given what is written in the previous sections, a logical question is if we can -apply scaling to math and the answer is \quotation {yes, we can}. But we actually -go a bit further and that is partly due to some other properties of the engine. +Given what is written in the previous sections, a logical question would be +\quotation {Can we apply scaling to math?} and the answer is \quotation {Yes, we +can!}. But we actually go a bit further and that is partly due to some other +properties of the engine. From \PDFTEX\ the \LUATEX\ engines inherited character protrusion and glyph expansions, aka hz. However, where in \PDFTEX\ copies of the font are made that carry the expanded dimensions, in \LUATEX\ at some point this was replaced by an expansion field in the glyph and kern nodes. So, instead of changing the font id of expanded glyphs, the same id is used but with the applied expansion factor set -in the glyph. A side effect was that in places where dimensions are needed, calls -to functions that calculate the expanded widths on request (as these can change -during linebreak calculations) in combination with accessing font dimensions -directly, we now always use accessor functions. This level of abstraction is even -more present in \LUAMETATEX. This means that we have an uniform interface to -fonts and as a side effect scaling is to be dealt with in only a few places in -the code. +in the glyph. A side effect was that in places where dimensions are needed, we +call functions that calculate the expanded widths on request (as these can +change during linebreak calculations) in combination with accessing font +dimensions directly. This level of abstraction is even more present in +\LUAMETATEX. This means that we have an uniform interface to fonts and as a side +effect scaling is to be dealt with in only a few places in the code. Now, in math we have a few more complications. First of all, we have three sizes to consider and we also have lots of parameters that depend on the size. But, as @@ -236,9 +280,9 @@ the math engine needs a specific character at a given size (text, script, scriptscript) we just follow that chain. In an \OPENTYPE\ math font the script and scriptscript sizes are specified as -percentages of the text size. So, when the dimensions of a glyph are needed, we -just scale on the fly. Again this adds some overhead but I'm pretty sure that no -user will notice this. +percentages of the text size. When the dimensions of a glyph are needed, we just +scale on the fly. Again this adds some overhead but I'm pretty sure that no user +will notice this. So, to summarize: if we need a character at scriptscript size, we access the text size glyph, check for a pointer to a script size, go there, and again check for a @@ -246,8 +290,11 @@ smaller size. We just use what fits the bill. And, when we need dimensions we just scale. In order to scale we need the relative size, so we need to set that up when we load the font. Because in \CONTEXT\ we also can assemble a virtual \OPENTYPE\ font from \TYPEONE\ fonts, it was actually that (old) compatibility -feature that took most time to adapt, not so much because it is complicates but -because in \LMTX\ we have to bypass some advanced loading mechanisms. +feature, the one that implements \TYPEONE\ bases \OPENTYPE\ math, that took most +time to adapt, not so much because it is complicates but because in \LMTX\ we +have to bypass some advanced loading mechanisms. Because we can scale in two +dimensions the many (font related) math parameters also need to be dealt with +accordingly. The end result is that for math we now only need to define two fonts per bodyfont setup: regular and bold at the natural scale (normally 10pt) and we share these @@ -283,12 +330,12 @@ manual we get these stats: \stoptyping So, we win on all fronts when we use this glyph scale mechanism. The magic -primitive that deals with this is \type {\glyphscale} which accepts a number, -where \type {1200} and \type {1.2} both mean scaling to 20\percent\ more than -normal. But one can best not use this primitive directly. +primitive that deals with this is \type {\glyphscale} primitive that accepts a +number, where \type {1200} and \type {1.2} both mean scaling to 20\percent\ more +than normal. But one can best not use this primitive directly. A specific font can be defined using the \type {\definefont} command. In \LMTX\ a -regular scaler can be followed by two scale factors. The nest example +regular scaler can be followed by two scale factors. The next example demonstrates this: \startbuffer @@ -311,11 +358,10 @@ only shows the two scales but also introduces the offset. \getbuffer -Here is another one: +In compact mode this is one font. Here is another example: \startbuffer -\definetweakedfont[squeezed] [xscale=0.9] -\definetweakedfont[squeezed] [xscale=0.9] +\definetweakedfont[squeezed][xscale=0.9] \startlines $a = b^2 + \sqrt{c}$ @@ -330,13 +376,13 @@ $a = b^2 + \sqrt{c}$ Watch this: \startbuffer -\startcombination[4*1] +\startcombination[3*1] {\bTABLE \bTR \bTD foo \eTD \bTD[style=\squeezed] $x = 1$ \eTD \eTR \bTR \bTD oof \eTD \bTD[style=\squeezed] $x = 2$ \eTD \eTR \eTABLE} {local} - {\bTABLE[style=squeezed] + {\bTABLE[style=\squeezed] \bTR \bTD $x = 1$ \eTD \bTD $x = 3$ \eTD \eTR \bTR \bTD $x = 2$ \eTD \bTD $x = 4$ \eTD \eTR \eTABLE} @@ -404,20 +450,28 @@ gives: \stoplinecorrection Glyphs can have offsets and these are used for implementing \OPENTYPE\ features. -However, they are also available at the \TEX\ end. Take this +However, they are also available at the \TEX\ end. Take this example where we use +the new \type {\glyph} primitive (a variant of \type {\char} that takes +keywords): \startbuffer \ruledhbox{ - \ruledhbox{\glyph yoffset 1ex options 0 123} + \ruledhbox{\glyph yoffset 1ex options 0 123} % left curly brace \ruledhbox{\glyph xoffset .5em yoffset 1ex options "C0 123} - \ruledhbox{oeps{\glyphyoffset 1ex \glyphxscale 800 \glyphyscale\glyphxscale oeps}oeps} + \ruledhbox{oeps{\glyphyoffset 1ex \glyphxscale 800 + \glyphyscale\glyphxscale oeps}oeps} } \stopbuffer -This example demonstrates that the \type {\glyph} primitive takes keywords: \type -{xoffset}, \type {yoffset}, \type {xscale}, \type {yscale}, \type {options}, -\type {font} and \type {id} where the last two take a font identifier or font id -(an positive number). +\typebuffer \getbuffer + +This example demonstrates that the \type {\glyph} primitive takes quite some +keywords: \type {xoffset}, \type {yoffset}, \type {xscale}, \type {yscale}, \type +{left}, \type {right}, \type {raise}, \type {options}, \type {font} and \type {id} +where the last two take a font identifier or font id (an positive number). For +this article it's enough to know that the option indicates that glyph dimension +should include the offset. In a moment we will see an alternative that doesn't +need that. \startbuffer \samplefile{jojomayer} @@ -441,7 +495,7 @@ To quote Jojo Mayer: \stopnarrower Keep in mind that this can interfere badly with font feature processing which also -used offsets. It might work out okay, or not. +used offsets. It might often work out okay vertically, but less well horizontally. The scales, as mentioned, works with pseudo scales but that is sometimes a bit cumbersome. This is why a special \type {\numericscale} primitive has been @@ -477,8 +531,8 @@ the slanted version could use some more left shifting of the E. \typebuffer[definition,example] -This gives is the \TEX\ logos (but of course we normally use the real ones -instead). +This gives the \TEX\ logos but of course we normally use the more official +definitions instead. \startnarrower \darkred \getbuffer[definition,example] @@ -490,7 +544,7 @@ suboptimal. Here is a better alternative: \startbuffer[definition] \def\UnKernedTeX - {T\glyph left .2ex raise -.4ex `E\glyph left .4ex `X\relax} + {T\glyph left .2ex raise -.4ex `E\glyph left .2ex `X\relax} \stopbuffer \typebuffer[definition] @@ -501,7 +555,7 @@ The result is the same: \darkgreen \getbuffer[definition,example] \stopnarrower -But anyway: don't over|-|do it. We could deal with such cases for decades without +But anyway: don't over|-|do it. We have dealt with such cases for decades without these fancy new features. The next example show margins in action: \startlinecorrection @@ -565,23 +619,25 @@ dimensions of a glyph. Discussing the implementation in the engine makes no sense here, also because details might change. However, it is good to know that quite some properties -travel with the glyph nodes, for instance the scales and offsets. The dimensions -(width, height and depth) are not stored in the glyph node but calculated from -the font, scales and optionally the offsets and expansion factor. One problem is -that the more clever (and nice) solutions we cook up, the more it might impact -performance. So, I will delay some experiments till I have a more powerful -machine. +travel with the glyph nodes, for instance the scales, margins, offsets, language, +script and state properties, control over kerning, ligaturing, expansion and +protrusion, etc. The dimensions (width, height and depth) are not stored in the +glyph node but calculated from the font, scales and optionally the offsets and +expansion factor. One problem is that the more clever (and nice) solutions we +cook up, the more it might impact performance. So, I will delay some experiments +till I have a more powerful machine. One reason for {\em not} storing the dimensions in a glyph node is that we often copy those nodes or change character fields in the font handler and we definitely don't want the wrong dimensions there. At that moment, offsets and margin fields -don't reflect features yet, so copying them is no big deal. However, dimensions -are rather character bound so every time a character is set, we also would have -to set the dimensions. Even worse, when we can set them, the question arises if -they actually were already set explicitly. So, this is a can of worms we're not -going to open: the basic width, height and depth of the glyph as specified in the -font is used and combines with actual dimensions (likely already scaled according -the glyph scales) in offset and margin fields. +don't reflect features yet, so copying them is no big deal because at that moment +these are still zero. However, dimensions are rather character bound so every +time a character is set, we also would have to set the dimensions. Even worse, +when we can set them, the question arises if they actually were already set +explicitly. So, this is a can of worms we're not going to open: the basic width, +height and depth of the glyph as specified in the font is used and combined with +actual dimensions (likely already scaled according the glyph scales) in offset +and margin fields. Now, I have to admit that especially playing with using margins to glyphs instead of font kerns is more of an experiment to see what the consequences are than a diff --git a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex index 747945f55..bf4233165 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex @@ -615,6 +615,8 @@ primitives (for as far their functionality is still around) you now can do this: \protected\def\pdfmapline {\pdfextension mapline } \protected\def\pdftrailer {\pdfextension trailer } \protected\def\pdfglyphtounicode {\pdfextension glyphtounicode } +\protected\def\pdfrunninglinkoff {\pdfextension linkstate 1 } +\protected\def\pdfrunninglinkon {\pdfextension linkstate 0 } \stoptyping The introspective primitives can be defined as: diff --git a/metapost/context/base/mpxl/mp-lmtx.mpxl b/metapost/context/base/mpxl/mp-lmtx.mpxl index 28fdb1417..88a0450d6 100644 --- a/metapost/context/base/mpxl/mp-lmtx.mpxl +++ b/metapost/context/base/mpxl/mp-lmtx.mpxl @@ -2219,10 +2219,7 @@ def lmt_registerglyphs = applyparameters "mpsglyphs" "lmt_do_registerglyphs" end def lmt_registerglyph = applyparameters "mpsglyph" "lmt_do_registerglyph" enddef ; newscriptindex mfid_registerglyphs ; mfid_registerglyphs := scriptindex "registerglyphs" ; def lmt_do_registerglyphs = runscript mfid_registerglyphs enddef ; -newscriptindex mfid_registerglyph ; mfid_registerglyph := scriptindex "registerglyph " ; def lmt_do_registerglyph = runscript mfid_registerglyph enddef ; - -% vardef lmt_do_registerglyphs = lua.mp.lmt_register_glyphs() ; enddef ; -% vardef lmt_do_registerglyph = lua.mp.lmt_register_glyph () ; enddef ; +newscriptindex mfid_registerglyph ; mfid_registerglyph := scriptindex "registerglyph" ; def lmt_do_registerglyph = runscript mfid_registerglyph enddef ; % Again an experiment (todo: the faster method): diff --git a/metapost/context/base/mpxl/mp-luas.mpxl b/metapost/context/base/mpxl/mp-luas.mpxl index c13db4d59..9ea130d35 100644 --- a/metapost/context/base/mpxl/mp-luas.mpxl +++ b/metapost/context/base/mpxl/mp-luas.mpxl @@ -215,16 +215,19 @@ permanent inpath, pointof, leftof, rightof ; extra_endfig := extra_endfig & " runscript mfid_path_reset ; " ; +newscriptindex mfid_utfnum ; mfid_utfnum := scriptindex "utfnum" ; newscriptindex mfid_utflen ; mfid_utflen := scriptindex "utflen" ; newscriptindex mfid_utfsub ; mfid_utfsub := scriptindex "utfsub" ; +% def utfnum = runscript mfid_utfnum enddef ; % def utflen = runscript mfid_utflen enddef ; % def utfsub = runscript mfid_utfsub enddef ; +vardef utfnum(expr s) = runscript mfid_utfnum s enddef ; % str vardef utflen(expr s) = runscript mfid_utflen s enddef ; % str vardef utfsub(text t) = runscript mfid_utfsub t enddef ; % str, first, (optional) last -permanent utflen, utfsub ; +permanent utfnum, utflen, utfsub ; newscriptindex mfid_getparameters ; mfid_getparameters := scriptindex "getparameters" ; newscriptindex mfid_presetparameters ; mfid_presetparameters := scriptindex "presetparameters" ; diff --git a/metapost/context/base/mpxl/mp-math.mpxl b/metapost/context/base/mpxl/mp-math.mpxl index c2723b0f6..cfe9e55e6 100644 --- a/metapost/context/base/mpxl/mp-math.mpxl +++ b/metapost/context/base/mpxl/mp-math.mpxl @@ -79,27 +79,27 @@ newscriptindex mfid_m_yz ; mfid_m_yz := scriptindex "m_y0" newscriptindex mfid_m_y ; mfid_m_y := scriptindex "m_y1" ; def m_y = runscript mfid_m_y enddef ; % y1 newscriptindex mfid_m_yn ; mfid_m_yn := scriptindex "m_yn" ; def m_yn = runscript mfid_m_yn enddef ; -newscriptindex mfid_c_sin ; mfid_c_asin := scriptindex "c_sin" ; def c_sin = runscript mfid_c_sin enddef ; -newscriptindex mfid_c_cos ; mfid_c_acos := scriptindex "c_cos" ; def c_cos = runscript mfid_c_cos enddef ; -newscriptindex mfid_c_tan ; mfid_c_acos := scriptindex "c_tan" ; def c_tan = runscript mfid_c_tan enddef ; -newscriptindex mfid_c_sinh ; mfid_c_acos := scriptindex "c_sinh" ; def c_sinh = runscript mfid_c_sinh enddef ; -newscriptindex mfid_c_cosh ; mfid_c_acos := scriptindex "c_cosh" ; def c_cosh = runscript mfid_c_cosh enddef ; -newscriptindex mfid_c_tanh ; mfid_c_acos := scriptindex "c_tanh" ; def c_tanh = runscript mfid_c_tanh enddef ; - -newscriptindex mfid_c_asin ; mfid_c_acos := scriptindex "c_asin" ; def c_asin = runscript mfid_c_asin enddef ; +newscriptindex mfid_c_sin ; mfid_c_sin := scriptindex "c_sin" ; def c_sin = runscript mfid_c_sin enddef ; +newscriptindex mfid_c_cos ; mfid_c_cos := scriptindex "c_cos" ; def c_cos = runscript mfid_c_cos enddef ; +newscriptindex mfid_c_tan ; mfid_c_tan := scriptindex "c_tan" ; def c_tan = runscript mfid_c_tan enddef ; +newscriptindex mfid_c_sinh ; mfid_c_sinh := scriptindex "c_sinh" ; def c_sinh = runscript mfid_c_sinh enddef ; +newscriptindex mfid_c_cosh ; mfid_c_cosh := scriptindex "c_cosh" ; def c_cosh = runscript mfid_c_cosh enddef ; +newscriptindex mfid_c_tanh ; mfid_c_tanh := scriptindex "c_tanh" ; def c_tanh = runscript mfid_c_tanh enddef ; + +newscriptindex mfid_c_asin ; mfid_c_asin := scriptindex "c_asin" ; def c_asin = runscript mfid_c_asin enddef ; newscriptindex mfid_c_acos ; mfid_c_acos := scriptindex "c_acos" ; def c_acos = runscript mfid_c_acos enddef ; -newscriptindex mfid_c_atan ; mfid_c_acos := scriptindex "c_atan" ; def c_atan = runscript mfid_c_atan enddef ; -newscriptindex mfid_c_asinh ; mfid_c_acos := scriptindex "c_asinh" ; def c_asinh = runscript mfid_c_asinh enddef ; -newscriptindex mfid_c_acosh ; mfid_c_acos := scriptindex "c_acosh" ; def c_acosh = runscript mfid_c_acosh enddef ; -newscriptindex mfid_c_atanh ; mfid_c_acos := scriptindex "c_atanh" ; def c_atanh = runscript mfid_c_atanh enddef ; - -newscriptindex mfid_c_sqrt ; mfid_c_acos := scriptindex "c_sqrt" ; def c_sqrt = runscript mfid_c_sqrt enddef ; -newscriptindex mfid_c_abs ; mfid_c_acos := scriptindex "c_abs" ; def c_abs = runscript mfid_c_abs enddef ; -newscriptindex mfid_c_arg ; mfid_c_acos := scriptindex "c_arg" ; def c_arg = runscript mfid_c_arg enddef ; -newscriptindex mfid_c_conj ; mfid_c_acos := scriptindex "c_conj" ; def c_conj = runscript mfid_c_conj enddef ; -newscriptindex mfid_c_exp ; mfid_c_acos := scriptindex "c_exp" ; def c_exp = runscript mfid_c_exp enddef ; -newscriptindex mfid_c_log ; mfid_c_acos := scriptindex "c_log" ; def c_log = runscript mfid_c_log enddef ; -newscriptindex mfid_c_proj ; mfid_c_acos := scriptindex "c_proj" ; def c_proj = runscript mfid_c_proj enddef ; +newscriptindex mfid_c_atan ; mfid_c_atan := scriptindex "c_atan" ; def c_atan = runscript mfid_c_atan enddef ; +newscriptindex mfid_c_asinh ; mfid_c_asinh := scriptindex "c_asinh" ; def c_asinh = runscript mfid_c_asinh enddef ; +newscriptindex mfid_c_acosh ; mfid_c_acosh := scriptindex "c_acosh" ; def c_acosh = runscript mfid_c_acosh enddef ; +newscriptindex mfid_c_atanh ; mfid_c_atanh := scriptindex "c_atanh" ; def c_atanh = runscript mfid_c_atanh enddef ; + +newscriptindex mfid_c_sqrt ; mfid_c_sqrt := scriptindex "c_sqrt" ; def c_sqrt = runscript mfid_c_sqrt enddef ; +newscriptindex mfid_c_abs ; mfid_c_abs := scriptindex "c_abs" ; def c_abs = runscript mfid_c_abs enddef ; +newscriptindex mfid_c_arg ; mfid_c_arg := scriptindex "c_arg" ; def c_arg = runscript mfid_c_arg enddef ; +newscriptindex mfid_c_conj ; mfid_c_conj := scriptindex "c_conj" ; def c_conj = runscript mfid_c_conj enddef ; +newscriptindex mfid_c_exp ; mfid_c_exp := scriptindex "c_exp" ; def c_exp = runscript mfid_c_exp enddef ; +newscriptindex mfid_c_log ; mfid_c_log := scriptindex "c_log" ; def c_log = runscript mfid_c_log enddef ; +newscriptindex mfid_c_proj ; mfid_c_proj := scriptindex "c_proj" ; def c_proj = runscript mfid_c_proj enddef ; newscriptindex mfid_c_erf ; mfid_c_erf := scriptindex "c_erf" ; def c_erf = runscript mfid_c_erf enddef ; newscriptindex mfid_c_erfc ; mfid_c_erfc := scriptindex "c_erfc" ; def c_erfc = runscript mfid_c_erfc enddef ; diff --git a/metapost/context/fonts/mpiv/punkfont-characters.mp b/metapost/context/fonts/mpiv/punkfont-characters.mp index da0015b02..5ba7a8a21 100644 --- a/metapost/context/fonts/mpiv/punkfont-characters.mp +++ b/metapost/context/fonts/mpiv/punkfont-characters.mp @@ -592,9 +592,19 @@ pd z1; pd z2; pd z3; pd z4; draw z1--z2; draw flex(z3,z6,z4); % stems pd z5; draw z5--z6; % crossbar endchar; -beginpunkchar("i",5,1,2); -z1=pp(.5w,0); z2=(.5w,1/3h); z3=(.5w,2/3h); z4=(.5w,h); -pd z1; pd z4; draw flex(z1,z2,z3,z4); % stem +% beginpunkchar("i",5,1,2); +% z1=pp(.5w,0); z2=(.5w,1/3h); z3=(.5w,2/3h); z4=(.5w,h); +% pd z1; pd z4; draw flex(z1,z2,z3,z4); % stem +% endchar; + +% beginpunkchar("i",9,1,2); +% z1=pp(.5w,0); z2=(.5w,.1h); z3=(.5w,2/3h); z4=(.5w,h); +% pd z1; pd z4; draw flex(z1,z2,z3,z4) withcolor red; % stem +% endchar; + +beginpunkchar("i",9,1,2); +z1=pp(.5w,0); z4=(.5w,h); +pd z1; pd z4; draw z1--z4; % stem endchar; beginpunkchar("j",9,1,2); @@ -642,7 +652,8 @@ z5=pp(.4w,.2h); z6=pp(w-u,-.1h); z7=pp(.5[x5,x6],-.2h); pd z5; pd z6; draw z5--z7--z6; % tail endchar; -beginpunkchar("r",16,1,2); +% beginpunkchar("r",16,1,2); +beginpunkchar("r",13,1,2); z1=pp(2u,0); z2=pp(2u,h); z3=pp(w-u,.6[y2,y4]); z4=pp(2u,.5h); z5=pp(w-1.5u,0); pd z1; pd z2; pd z5; draw z1--flex(z2,z3,z4)--z5; % stem, bowl, and diagonal endchar; diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index d06fbe463..6c1dca8a2 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.01.11 16:28} +\newcontextversion{2021.01.17 21:39} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index c36274955..dbe4e4249 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.01.11 16:28} +\edef\contextversion{2021.01.17 21:39} %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 49c850c9b..d8dfa0fa2 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.01.11 16:28} +\newcontextversion{2021.01.17 21:39} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 93744dfda..8e697e850 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.01.11 16:28} +\edef\contextversion{2021.01.17 21:39} %D Kind of special: diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua index ed82fcc48..d2294e93c 100644 --- a/tex/context/base/mkiv/font-imp-math.lua +++ b/tex/context/base/mkiv/font-imp-math.lua @@ -80,6 +80,34 @@ registerotffeature { } } +function fonts.helpers.mathscriptslots(tfmdata,textcode) + local rawdata = tfmdata.shared.rawdata + local rawresources = rawdata and rawdata.resources + local rawfeatures = rawresources and rawresources.features + local basesubstitutions = rawfeatures and rawfeatures.gsub + local sequences = basesubstitutions and tfmdata.resources.sequences + if sequences then + local characters = tfmdata.characters + if characters[textcode] then + for s=1,#sequences do + local sequence = sequences[s] + local sfeatures = sequence.features + if sfeatures and sfeatures.ssty then + local steps = sequence.steps + for i=1,#steps do + local coverage = steps[i].coverage + if coverage then + local okay = coverage[textcode] + if okay then + return okay + end + end + end + end + end + end + end +end local function initialize(tfmdata,key,value) if value then local rawdata = tfmdata.shared.rawdata diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua index 1acf14558..255b4cdf0 100644 --- a/tex/context/base/mkiv/font-imp-tracing.lua +++ b/tex/context/base/mkiv/font-imp-tracing.lua @@ -139,107 +139,3 @@ local specification = { 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/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv index c32690375..445dedd25 100644 --- a/tex/context/base/mkiv/font-pre.mkiv +++ b/tex/context/base/mkiv/font-pre.mkiv @@ -405,6 +405,7 @@ mathalternates=yes, mathitalics=yes, % we pass them mathdimensions=all, + % mathkerns=yes, % mathgaps=yes, language=dflt, script=math] diff --git a/tex/context/base/mkiv/good-mth.lua b/tex/context/base/mkiv/good-mth.lua index b85e680cc..3473cc205 100644 --- a/tex/context/base/mkiv/good-mth.lua +++ b/tex/context/base/mkiv/good-mth.lua @@ -6,8 +6,9 @@ if not modules then modules = { } end modules ['good-mth'] = { license = "see context related readme files" } -local type, next = type, next +local type, next, tonumber, unpack = type, next, tonumber, unpack local ceil = math.ceil +local match = string.match local fonts = fonts @@ -20,6 +21,10 @@ local fontgoodies = fonts.goodies or { } local fontcharacters = fonts.hashes.characters +local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) + +local report_math = logs.reporter("mathematics","initializing") + local nuts = nodes.nuts local setlink = nuts.setlink @@ -33,11 +38,149 @@ local new_vlist = nodepool.vlist local insert_node_after = nuts.insert_after +local helpers = fonts.helpers +local upcommand = helpers.commands.up +local rightcommand = helpers.commands.right +local charcommand = helpers.commands.char +local prependcommands = helpers.prependcommands + -- experiment, we have to load the definitions immediately as they precede -- the definition so they need to be initialized in the typescript +local function withscriptcode(tfmdata,unicode,data,action) + if type(unicode) == "string" then + local p, u = match(unicode,"^(.-):(.-)$") + if u then + u = tonumber(u) + if u then + local slots = fonts.helpers.mathscriptslots(tfmdata,u) + if slots then + if p == "*" then + action(u,data) + for i=1,#slots do + action(slots[i],data) + end + else + p = tonumber(p) + if p then + action(slots[p],data) + end + end + end + end + end + else + action(unicode,data) + end +end + local function finalize(tfmdata,feature,value) - mathematics.overloaddimensions(tfmdata,tfmdata,value) +-- if tfmdata.mathparameters then -- funny, cambria text has this + local goodies = tfmdata.goodies + if goodies then + local virtualized = mathematics.virtualized + for i=1,#goodies do + local goodie = goodies[i] + local mathematics = goodie.mathematics + local dimensions = mathematics and mathematics.dimensions + if dimensions then + if trace_defining then + report_math("overloading dimensions in %a @ %p",tfmdata.properties.fullname,tfmdata.parameters.size) + end + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local parameters = tfmdata.parameters + local factor = parameters.factor + local hfactor = parameters.hfactor + local vfactor = parameters.vfactor + local function overloadone(unicode,data) + local character = characters[unicode] + if not character then + local c = virtualized[unicode] + if c then + character = characters[c] + end + end + if character then + local width = data.width + 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 %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 + if depth then character.depth = depth * vfactor end + -- + local xoffset = data.xoffset + local yoffset = data.yoffset + if xoffset == "llx" then + local d = descriptions[unicode] + if d then + xoffset = - d.boundingbox[1] * hfactor + character.width = character.width + xoffset + xoffset = rightcommand[xoffset] + else + xoffset = nil + end + elseif xoffset and xoffset ~= 0 then + xoffset = rightcommand[xoffset * hfactor] + else + xoffset = nil + end + if yoffset and yoffset ~= 0 then + yoffset = upcommand[yoffset * vfactor] + else + yoffset = nil + end + if xoffset or yoffset then + local commands = characters.commands + if commands then + prependcommands(commands,yoffset,xoffset) + else + local slot = charcommand[unicode] + if xoffset and yoffset then + character.commands = { xoffset, yoffset, slot } + elseif xoffset then + character.commands = { xoffset, slot } + else + character.commands = { yoffset, slot } + end + end + end + elseif trace_defining then + report_math("no overloading dimensions of %C, not in font",unicode) + end + end + local function overload(dimensions) + for unicode, data in next, dimensions do + withscriptcode(tfmdata,unicode,data,overloadone) + end + end + if value == nil then + value = { "default" } + end + if value == "all" or value == true then + for name, value in next, dimensions do + overload(value) + end + else + if type(value) == "string" then + value = utilities.parsers.settings_to_array(value) + end + if type(value) == "table" then + for i=1,#value do + local d = dimensions[value[i]] + if d then + overload(d) + end + end + end + end + end + end + end end registerotffeature { @@ -77,10 +220,11 @@ end fontgoodies.register("mathematics", initialize) -local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end) +-- local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end) local function initialize(tfmdata) - if enabled and tfmdata.mathparameters then -- funny, cambria text has this +-- if enabled and tfmdata.mathparameters then -- funny, cambria text has this + if tfmdata.mathparameters then -- funny, cambria text has this local goodies = tfmdata.goodies if goodies then local characters = tfmdata.characters @@ -91,12 +235,15 @@ local function initialize(tfmdata) if mathgoodies then local kerns = mathgoodies.kerns if kerns then - for unicode, specification in next, kerns do + local function kernone(unicode,data) local chardata = characters[unicode] - if chardata and (not chardata.mathkerns or specification.force) then - chardata.mathkerns = specification + if chardata and (not chardata.mathkerns or data.force) then + chardata.mathkerns = data end end + for unicode, data in next, kerns do + withscriptcode(tfmdata,unicode,data,kernone) + end return end end @@ -109,9 +256,9 @@ local function initialize(tfmdata) end registerotffeature { - name = "mathkerns", - description = "math kerns", - default = true, + name = "mathkerns", + description = "math kerns", + -- default = true, initializers = { base = initialize, node = initialize, diff --git a/tex/context/base/mkiv/math-act.lua b/tex/context/base/mkiv/math-act.lua index 4f38b4195..a5cfa82de 100644 --- a/tex/context/base/mkiv/math-act.lua +++ b/tex/context/base/mkiv/math-act.lua @@ -230,115 +230,6 @@ sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaft local virtualized = mathematics.virtualized -function mathematics.overloaddimensions(target,original,set) - local goodies = target.goodies - if goodies then - for i=1,#goodies do - local goodie = goodies[i] - local mathematics = goodie.mathematics - local dimensions = mathematics and mathematics.dimensions - if dimensions then - if trace_defining then - report_math("overloading dimensions in %a @ %p",target.properties.fullname,target.parameters.size) - end - local characters = target.characters - local descriptions = target.descriptions - local parameters = target.parameters - local factor = parameters.factor - local hfactor = parameters.hfactor - local vfactor = parameters.vfactor -if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then - target.type = "virtual" - target.properties.virtualized = true -end - local function overload(dimensions) - for unicode, data in next, dimensions do - local character = characters[unicode] - if not character then - local c = virtualized[unicode] - if c then - character = characters[c] - end - end - if character then - -- - local width = data.width - 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 %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 - if depth then character.depth = depth * vfactor end - -- - local xoffset = data.xoffset - local yoffset = data.yoffset - if xoffset == "llx" then - local d = descriptions[unicode] - if d then - xoffset = - d.boundingbox[1] * hfactor - character.width = character.width + xoffset - xoffset = rightcommand[xoffset] - else - xoffset = nil - end - elseif xoffset and xoffset ~= 0 then - xoffset = rightcommand[xoffset * hfactor] - else - xoffset = nil - end - if yoffset and yoffset ~= 0 then - yoffset = upcommand[yoffset * vfactor] - else - yoffset = nil - end - if xoffset or yoffset then - local commands = characters.commands - if commands then - prependcommands(commands,yoffset,xoffset) - else - local slot = charcommand[unicode] - if xoffset and yoffset then - character.commands = { xoffset, yoffset, slot } - elseif xoffset then - character.commands = { xoffset, slot } - else - character.commands = { yoffset, slot } - end - end - end - elseif trace_defining then - report_math("no overloading dimensions of %C, not in font",unicode) - end - end - end - if set == nil then - set = { "default" } - end - if set == "all" or set == true then - for name, set in next, dimensions do - overload(set) - end - else - if type(set) == "string" then - set = utilities.parsers.settings_to_array(set) - end - if type(set) == "table" then - for i=1,#set do - local d = dimensions[set[i]] - if d then - overload(d) - end - end - end - end - end - end - end -end - -- no, it's a feature now (see good-mth): -- -- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions") @@ -711,10 +602,10 @@ function mathematics.finishfallbacks(target,specification,fallbacks) fonts = { } target.fonts = fonts end -if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then + -- target.type = "virtual" target.properties.virtualized = true -end + -- if #fonts == 0 then fonts[1] = { id = 0, size = size } -- self, will be resolved later end diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua index 4d99e8320..4e4a901c0 100644 --- a/tex/context/base/mkiv/mult-fun.lua +++ b/tex/context/base/mkiv/mult-fun.lua @@ -187,7 +187,7 @@ return { -- "inpath", "pointof", "leftof", "rightof", -- - "utflen", "utfsub", + "utfnum", "utflen", "utfsub", -- "newhash", "disposehash", "inhash", "tohash", -- diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex d55bfa411..605d8e1f1 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 78ade839c..3c5c26cb3 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua index b5fd2667b..f7953c416 100644 --- a/tex/context/base/mkiv/strc-mar.lua +++ b/tex/context/base/mkiv/strc-mar.lua @@ -122,7 +122,7 @@ end local function sweep(head,first,last) 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 + if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr local a = getattr(n,a_marks) if not a then -- next diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua index c06e32df3..3e78fb2f9 100644 --- a/tex/context/base/mkiv/task-ini.lua +++ b/tex/context/base/mkiv/task-ini.lua @@ -95,6 +95,7 @@ appendaction("shipouts", "finishers", "attributes.transparencies.handler", 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.alternates.handler", nil, "nut", "disabled" ) appendaction("shipouts", "finishers", "attributes.viewerlayers.handler", nil, "nut", "disabled" ) appendaction("shipouts", "wrapup", "nodes.handlers.export", nil, "nut", "disabled" ) -- always last diff --git a/tex/context/base/mkxl/anch-pos.lmt b/tex/context/base/mkxl/anch-pos.lmt index e804dbdf6..67d1657f2 100644 --- a/tex/context/base/mkxl/anch-pos.lmt +++ b/tex/context/base/mkxl/anch-pos.lmt @@ -1628,6 +1628,9 @@ end) local newsavepos = nodes.pool.savepos +jobpositions.lastx = 0 +jobpositions.lasty = 0 + implement { name = "savepos", actions = function() context(newsavepos()) end } -implement { name = "lastxpos", actions = function() context(gethpos()) end } -implement { name = "lastypos", actions = function() context(getvpos()) end } +implement { name = "lastxpos", actions = function() context(jobpositions.lastx) end } +implement { name = "lastypos", actions = function() context(jobpositions.lasty) end } diff --git a/tex/context/base/mkxl/attr-alt.lmt b/tex/context/base/mkxl/attr-alt.lmt new file mode 100644 index 000000000..9d8592074 --- /dev/null +++ b/tex/context/base/mkxl/attr-alt.lmt @@ -0,0 +1,111 @@ +if not modules then modules = { } end modules ['attr-eff'] = { + version = 1.001, + comment = "companion to attr-eff.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities +local tex = tex + +local states = attributes.states +local enableaction = nodes.tasks.enableaction +local nodeinjections = backends.nodeinjections +local texsetattribute = tex.setattribute +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + +local interfaces = interfaces +local implement = interfaces.implement + +attributes.alternates = attributes.alternates or { } +local alternates = attributes.alternates + +local a_alternate = attributes.private('alternate') + +alternates.data = allocate() +alternates.values = alternates.values or { } +alternates.registered = alternates.registered or { } +alternates.attribute = a_alternate + +local data = alternates.data +local registered = alternates.registered +local values = alternates.values + +storage.register("attributes/alternates/registered", registered, "attributes.alternates.registered") +storage.register("attributes/alternates/values", values, "attributes.alternates.values") + +local function extender(alternates,key) + if key == "none" then + local d = nodeinjections.stopalternate() + alternates.none = d + return d + end +end + +local function reviver(data,n) + local d = values[n] and nodeinjections.startalternate(values[n]) or nodeinjections.stopalternate() + data[n] = d + return d +end + +setmetatableindex(alternates, extender) +setmetatableindex(alternates.data, reviver) + +alternates.handler = nodes.installattributehandler { + name = "alternate", + namespace = alternates, + initializer = states.initialize, + finalizer = states.finalize, + processor = states.simple, +} + +local function register(specification) + local text = specification.text or "unknown" + local n = registered[text] + if not n then + n = #values + 1 + values[n] = text + registered[text] = n + end + return n +end + +local enabled = false + +local function enable() + if not enabled then + enableaction("shipouts","attributes.alternates.handler") + enabled = true + end +end + +alternates.register = register +alternates.enable = enable + +-- interface + +implement { + name = "setalternate", + actions = function(specification) + if not enabled then + enable() + end + texsetattribute(a_alternate,register(specification)) + end, + arguments = { + { + { "text", "string" }, + } + } +} + +implement { + name = "resetalternate", + actions = function() + if enabled then + texsetattribute(a_alternate) + end + end +} diff --git a/tex/context/base/mkxl/attr-alt.mkxl b/tex/context/base/mkxl/attr-alt.mkxl new file mode 100644 index 000000000..3881d929e --- /dev/null +++ b/tex/context/base/mkxl/attr-alt.mkxl @@ -0,0 +1,55 @@ +%D \module +%D [ file=attr-alt, +%D version=2007.06.06, +%D title=\CONTEXT\ Attribute Macros, +%D subtitle=Alternates, +%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 Attribute Macros / Alternates} + +\registerctxluafile{attr-alt}{autosuffix} + +%D The main reason for providing this is that we need to make sure we have no +%D dangling end markers when we cross a page. Public viewers don't seem to support +%D actual text at all and acrobat has some funny selection issues. +%D +%D \starttyping +%D test +%D \startalternate[text={A}] +%D \dorecurse{10}{A } +%D \startalternate[text={B}] +%D \dorecurse{10}{B } +%D \stopalternate +%D \dorecurse{10}{A } +%D \stopalternate +%D test \par +%D \stoptyping +%D +%D \starttyping +%D test \startalternate[text={e=mc^2}]!$e=mc^2$\stopalternate\par +%D test \alternate{e=mc^2}{copy:}\nbsp$e=mc^2$\par +%D \stoptyping + +\unprotect + +\permanent\protected\def\startalternate[#1]% maybe better/also: [text={...}] + {\begingroup + \getdummyparameters[\c!text=,#1]% + \clf_setalternate text {\dummyparameter\c!text}\relax} + +\permanent\protected\def\stopalternate + {\endgroup} + +\permanent\protected\def\alternate#1% + {\groupedcommand{\clf_setalternate text {#1}\relax}{}} + +\permanent\protected\def\setalternate #1{\clf_setalternate text {#1}\relax} +\permanent\protected\def\resetalternate {\clf_resetalternate} + +\protect \endinput diff --git a/tex/context/base/mkxl/attr-eff.mkxl b/tex/context/base/mkxl/attr-eff.mkxl index 04a0c55ce..42aadf9a2 100644 --- a/tex/context/base/mkxl/attr-eff.mkxl +++ b/tex/context/base/mkxl/attr-eff.mkxl @@ -30,8 +30,8 @@ \appendtoks \edef\p_method{\effectparameter\c!method}% \ifx\p_method\v!command - \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}% - \setuxvalue{\e!stop \currenteffect}{\stopeffect}% + \frozen\protected\xdefcsname\e!start\currenteffect\endcsname{\starteffect[#1]}% + \frozen\protected\xdefcsname\e!stop \currenteffect\endcsname{\stopeffect}% \fi \to \everydefineeffect diff --git a/tex/context/base/mkxl/attr-ini.mkxl b/tex/context/base/mkxl/attr-ini.mkxl index de22cd6e2..8cef1ec56 100644 --- a/tex/context/base/mkxl/attr-ini.mkxl +++ b/tex/context/base/mkxl/attr-ini.mkxl @@ -130,6 +130,7 @@ \definesystemattribute [ruled] [public] \definesystemattribute [shifted] [public] \definesystemattribute [checkedbreak] [public] +\definesystemattribute [alternate] [public] \definesystemattribute [vboxtohboxseparator] [public] \permanent\protected\let\showattributes\clf_showattributes % maybe at lua end diff --git a/tex/context/base/mkxl/back-trf.mkxl b/tex/context/base/mkxl/back-ext.mkxl index fcf69ade4..bba33335d 100644 --- a/tex/context/base/mkxl/back-trf.mkxl +++ b/tex/context/base/mkxl/back-ext.mkxl @@ -1,8 +1,8 @@ %D \module -%D [ file=back-trf, -%D version=2019.02.08, % 2009.04.15, +%D [ file=back-ext, +%D version=2019.02.08, % and later, merged file %D title=\CONTEXT\ Backend Macros, -%D subtitle=Transformations, +%D subtitle=Output, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -11,9 +11,15 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% \registerctxluafile{back-ext}{autosuffix} + \unprotect -\registerctxluafile{back-trf}{autosuffix} +% \let\normalopenout \openout +% \let\normalwrite \write +% \let\normalcloseout\closeout +% \let\normallatelua \latelua +% \let\normalspecial \special % rotation diff --git a/tex/context/base/mkxl/back-ini.lmt b/tex/context/base/mkxl/back-ini.lmt index ee40c384d..922705742 100644 --- a/tex/context/base/mkxl/back-ini.lmt +++ b/tex/context/base/mkxl/back-ini.lmt @@ -95,17 +95,6 @@ statistics.register("used backend", function() end end) -local comment = { "comment", "" } - -tables.vfspecials = allocate { - red = comment, - green = comment, - blue = comment, - black = comment, - startslant = comment, - stopslant = comment, -} - -- can best be here interfaces.implement { @@ -131,25 +120,6 @@ end) backends.included = included --- 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 - return paper_width, paper_height -end - -function codeinjections.getpagedimensions() - return paper_width, paper_height -end - -- could also be codeinjections function backends.getcallbackstate() diff --git a/tex/context/base/mkxl/back-out.lmt b/tex/context/base/mkxl/back-out.lmt deleted file mode 100644 index fbcb220dc..000000000 --- a/tex/context/base/mkxl/back-out.lmt +++ /dev/null @@ -1,255 +0,0 @@ -if not modules then modules = { } end modules ['back-out'] = { - version = 1.001, - comment = "companion to back-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 loadstring = loadstring - -local context = context - --- tokens.scanners..... - -local get = token.get_index -local scanners = tokens.scanners -local scaninteger = scanners.integer -local scanstring = scanners.string -local scankeyword = scanners.keyword -local scantokenlist = scanners.tokenlist - -local serialize = token.serialize - -local logwriter = logs.writer -local openfile = io.open -local flushio = io.flush - -local nuts = nodes.nuts -local tonode = nuts.tonode -local copynode = nuts.copy -local nodepool = nuts.pool - -local getdata = nuts.getdata - -local whatsit_code = nodes.nodecodes.whatsit - -local whatsitcodes = nodes.whatsitcodes - -local literalvalues = nodes.literalvalues -local originliteral_code = literalvalues.origin -local pageliteral_code = literalvalues.page -local directliteral_code = literalvalues.direct -local rawliteral_code = literalvalues.raw - -local immediate_code = tex.flagcodes.immediate - -local nodeproperties = nodes.properties.data - -local channels = { } - -local register = nodepool.register -local newnut = nuts.new - -local opennode = register(newnut(whatsit_code,whatsitcodes.open)) -local writenode = register(newnut(whatsit_code,whatsitcodes.write)) -local closenode = register(newnut(whatsit_code,whatsitcodes.close)) -local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua)) -local literalnode = register(newnut(whatsit_code,whatsitcodes.literal)) -local savenode = register(newnut(whatsit_code,whatsitcodes.save)) -local restorenode = register(newnut(whatsit_code,whatsitcodes.restore)) -local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix)) - -local open_command, write_command, close_command - -backends = backends or { } - -local function immediately(prefix) - return prefix and (prefix & immediate_code) ~= 0 -end - -local function openout(prefix) - local channel = scaninteger() - scankeyword("=") -- hack - local filename = scanstring() - if not immediately(prefix) then - local n = copynode(opennode) - nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" - return context(tonode(n)) - elseif not channels[channel] then - local handle = openfile(filename,"wb") or false - if handle then - channels[channel] = handle - else - -- error - end - end -end - -function backends.openout(n) - local p = nodeproperties[n] - if p then - local handle = openfile(p.filename,"wb") or false - if handle then - channels[p.channel] = handle - else - -- error - end - end -end - -local function write(prefix) - local channel = scaninteger() - if not immediately(prefix) then - local t = scantokenlist() - local n = copynode(writenode) - nodeproperties[n] = { channel = channel, data = t } -- action = "write" - return context(tonode(n)) - else - local content = scanstring() - local handle = channels[channel] - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end -end - -function backends.writeout(n) - local p = nodeproperties[n] - if p then - local handle = channels[p.channel] - local content = serialize(p.data) - if handle then - handle:write(content,"\n") - else - logwriter(content,"\n") - end - end -end - -local function closeout(prefix) - local channel = scaninteger() - if not immediately(prefix) then - local n = copynode(closenode) - nodeproperties[n] = { channel = channel } -- action = "close" - return context(tonode(n)) - else - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end -end - -function backends.closeout(n) - local p = nodeproperties[n] - if p then - local channel = p.channel - local handle = channels[channel] - if handle then - handle:close() - channels[channel] = false - flushio() - else - -- error - end - end -end - -local noflatelua = 0 - -local function latelua() - local node = copynode(lateluanode) - local name = "latelua" - if scankeyword("name") then - name = scanstring() - end - local data = scantokenlist() - nodeproperties[node] = { name = name, data = data } - return context(tonode(node)) -end - -function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) - local p = nodeproperties[current] - if p then - data = p.data - else - data = getdata(current) - end - noflatelua = noflatelua + 1 - local kind = type(data) - if kind == "table" then - data.action(data.specification or data) - elseif kind == "function" then - data() - else - if kind ~= "string" then - data = serialize(data) - end - if #data ~= "" then - local code = loadstring(data) - if code then - code() - end - end - end -end - -function backends.getcallbackstate() - return { count = noflatelua } -end - -function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end -function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end -function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end -function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end - -local pdfliterals = { - [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, - [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, - [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, - [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, -} - -function nodepool.literal(mode,str) - local t = copynode(literalnode) - if str then - nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } - else - nodeproperties[t] = { data = mode, mode = pageliteral_code } - end - return t -end - ---- these 3 will move to node-res as they are generic - -function nodepool.save() - return copynode(savenode) -end - -function nodepool.restore() - return copynode(restorenode) -end - -function nodepool.setmatrix(rx,sx,sy,ry,tx,ty) - local t = copynode(setmatrixnode) - nodeproperties[t] = { matrix = { rx, sx, sy, ry, tx, ty } } - return t -end - -interfaces.implement { name = "openout", actions = openout, public = true, usage = "value" } -interfaces.implement { name = "write", actions = write, public = true, usage = "value" } -interfaces.implement { name = "closeout", actions = closeout, public = true, usage = "value" } -interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true } -interfaces.implement { name = "special", actions = scanstring, public = true, protected = true } - -open_command = get(token.create("openout")) -write_command = get(token.create("write")) -close_command = get(token.create("closeout")) diff --git a/tex/context/base/mkxl/back-out.mkxl b/tex/context/base/mkxl/back-out.mkxl deleted file mode 100644 index 5cf79b2ea..000000000 --- a/tex/context/base/mkxl/back-out.mkxl +++ /dev/null @@ -1,22 +0,0 @@ -%D \module -%D [ file=back-out, -%D version=2019.02.08, -%D title=\CONTEXT\ Backend Macros, -%D subtitle=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. - -\registerctxluafile{back-out}{autosuffix} - -% \let\normalopenout \openout -% \let\normalwrite \write -% \let\normalcloseout\closeout -% \let\normallatelua \latelua -% \let\normalspecial \special - -\endinput diff --git a/tex/context/base/mkxl/back-pdf.mkxl b/tex/context/base/mkxl/back-pdf.mkxl index 66db06ef1..d59c29bc0 100644 --- a/tex/context/base/mkxl/back-pdf.mkxl +++ b/tex/context/base/mkxl/back-pdf.mkxl @@ -20,7 +20,6 @@ \registerctxluafile{lpdf-ini}{autosuffix,optimize} \registerctxluafile{lpdf-lmt}{autosuffix,optimize} \registerctxluafile{lpdf-col}{autosuffix} -\registerctxluafile{lpdf-vfc}{autosuffix} \registerctxluafile{lpdf-xmp}{autosuffix} \registerctxluafile{lpdf-ano}{autosuffix} \registerctxluafile{lpdf-res}{autosuffix} diff --git a/tex/context/base/mkxl/back-trf.lmt b/tex/context/base/mkxl/back-trf.lmt deleted file mode 100644 index e3ec0bda3..000000000 --- a/tex/context/base/mkxl/back-trf.lmt +++ /dev/null @@ -1,164 +0,0 @@ -if not modules then modules = { } end modules ['back-trf'] = { - version = 1.001, - comment = "companion to back-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local sind, cosd, abs = math.sind, math.cosd, math.abs -local insert, remove = table.insert, table.remove -local unpack = unpack - -local context = context - -local formatters = string.formatters - -local scanners = tokens.scanners -local scankeyword = scanners.keyword -local scaninteger = scanners.integer -local scannumber = scanners.number -local scanstring = scanners.string - -local implement = interfaces.implement - -local nodepool = nodes.pool -local savenode = nodepool.save -local restorenode = nodepool.restore -local setmatrixnode = nodepool.setmatrix -local literalnode = nodepool.literal -- has to become some nodeinjection - -local stack = { } -local restore = true -- false - -updaters.register("backend.update",function() - savenode = nodepool.save -- not needed - restorenode = nodepool.restore -- not needed - setmatrixnode = nodepool.setmatrix -- not needed - literalnode = nodepool.literal -- has to become some nodeinjection -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 - --- this could also run on top of pack-rul ... todo - --- local function startclipping() --- -- context(savenode()) --- context(literalnode("origin",formatters["q 0 w %s W n"](scanstring()))) --- end --- --- local function stopclipping() --- -- context(restorenode()) --- context(literalnode("Q")) --- end - -local function startclipping() - context(savenode()) - context(literalnode("origin",formatters["0 w %s W n"](scanstring()))) -end - -local function stopclipping() - context(restorenode()) -end - -implement { name = "startclipping", actions = startclipping } -implement { name = "stopclipping", actions = stopclipping } diff --git a/tex/context/base/mkxl/colo-nod.lmt b/tex/context/base/mkxl/colo-nod.lmt index d65f5978c..67487fee5 100644 --- a/tex/context/base/mkxl/colo-nod.lmt +++ b/tex/context/base/mkxl/colo-nod.lmt @@ -12,9 +12,9 @@ local setattrs = nuts.setattrs local privateattributes = attributes.private +local a_colormodel = privateattributes('colormodel') local a_color = privateattributes('color') local a_transparency = privateattributes('transparency') -local a_colormodel = privateattributes('colormodel') local colors = { } nuts.colors = colors @@ -26,9 +26,9 @@ function colors.set(n,ma,ca,ta) -- we could also do layers here ma = 1 end if ta then - setattrs(n,a_colorspace,ma,a_color,ca,a_transparency,ta) + setattrs(n,a_colormodel,ma,a_color,ca,a_transparency,ta) else - setattrs(n,a_colorspace,ma,a_color,ca) + setattrs(n,a_colormodel,ma,a_color,ca) end end elseif ta then diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 31dbd327a..8f1882ce5 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.01.11 16:28} +\newcontextversion{2021.01.17 21:39} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 751712225..54b1bb730 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.01.11 16:28} +\immutable\edef\contextversion{2021.01.17 21:39} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -159,7 +159,7 @@ \loadmkxlfile{node-ini} -\loadmkxlfile{cldf-bas} % basics / depends on nodes +% \loadmkxlfile{cldf-bas} % basics / depends on nodes \loadmkxlfile{node-fin} \loadmkxlfile{node-mig} @@ -169,13 +169,15 @@ \loadmkxlfile{back-ini} \loadmkxlfile{back-res} -\loadmkxlfile{back-trf} -\loadmkxlfile{back-out} +\loadmkxlfile{back-ext} + +\loadmkxlfile{cldf-bas} % basics / depends on nodes \loadmkxlfile{attr-col} \loadmkxlfile{attr-lay} \loadmkxlfile{attr-neg} \loadmkxlfile{attr-eff} +\loadmkxlfile{attr-alt} \loadmkxlfile{attr-mkr} \loadmkxlfile{trac-tex} diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt index 9747ba82d..cfa61e30e 100644 --- a/tex/context/base/mkxl/driv-shp.lmt +++ b/tex/context/base/mkxl/driv-shp.lmt @@ -99,21 +99,7 @@ local gleaders_code = gluecodes.gleaders local spaceskip_code = gluecodes.spaceskip -local saveposwhatsit_code = whatsitcodes.savepos -local userdefinedwhatsit_code = whatsitcodes.userdefined -local openwhatsit_code = whatsitcodes.open -local writewhatsit_code = whatsitcodes.write -local closewhatsit_code = whatsitcodes.close -local lateluawhatsit_code = whatsitcodes.latelua -local literalwhatsit_code = whatsitcodes.literal -local setmatrixwhatsit_code = whatsitcodes.setmatrix -local savewhatsit_code = whatsitcodes.save -local restorewhatsit_code = whatsitcodes.restore - -local getpagedimensions getpagedimensions = function() - getpagedimensions = backends.codeinjections.getpagedimensions - return getpagedimensions() -end +local getpagedimensions = layouts.getpagedimensions local drivers = drivers local instances = drivers.instances @@ -154,11 +140,6 @@ local flushcharacter local flushfontchar local flushrule local flushliteral -local flushsetmatrix -local flushsave -local flushrestore -local flushspecial ------ flushimage -- make local @@ -169,307 +150,323 @@ function drivers.getvpos() return round(pos_v) end -- characters -local flush_character - -local stack = setmetatableindex("table") -local level = 0 -local nesting = 0 -local main = 0 - --- experiment (smaller page stream but might be fragile) +local flush_character do -local tospace = false directives.register("backends.spaces", function(v) tospace = v end) + local stack = setmetatableindex("table") + local level = 0 + local nesting = 0 + local main = 0 --- todo: cache streams + -- experiment (smaller page stream but might be fragile) -local default = 16384 * number.dimenfactors.bp -- 65536 // 4 + local tospace = false directives.register("backends.spaces", function(v) tospace = v end) -local startcolor = function() end -local stopcolor = function() end + -- todo: cache streams -updaters.register("backend.update",function() - startcolor = fonts.vfcommands.startcolor - stopcolor = fonts.vfcommands.stopcolor -end) + local default = 16384 * number.dimenfactors.bp -- 65536 // 4 -local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) + local vfinjectors = fonts.helpers.vfinjectors - if nesting > 100 then - return - elseif nesting == 0 then - main = font - end + local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) - nesting = nesting + 1 + if nesting > 100 then + return + elseif nesting == 0 then + main = font + end - local saved_h = pos_h - local saved_v = pos_v - local saved_r = pos_r - pos_r = lefttoright_code + nesting = nesting + 1 - local data = fontdata[font] - local fnt = font - local fonts = data.fonts - local siz = (data.parameters.factor or 1)/65536 + local saved_h = pos_h + local saved_v = pos_v + local saved_r = pos_r + pos_r = lefttoright_code --- siz = siz * data.parameters.size / 1000 + local data = fontdata[font] + local fnt = font + local fonts = data.fonts + local siz = (data.parameters.factor or 1)/65536 - local function flushchar(font,char,fnt,chr,f,e) - if fnt then - local nest = char ~= chr or font ~= fnt - if fnt == 0 then - fnt = main + local function flushchar(font,char,fnt,chr,f,e) + if fnt then + local nest = char ~= chr or font ~= fnt + if fnt == 0 then + fnt = main + end + return flush_character(current,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) + else + return 0 end --- return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) - return flush_character(current,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) - else - return 0 end - end - -- we assume resolved fonts: id mandate but maybe also size - - for i=1,#vfcommands do - local packet = vfcommands[i] - local command = packet[1] - if command == "char" then - local chr = packet[2] - local f = packet[3] - local e = packet[4] - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - elseif command == "slot" then - local index = packet[2] - local chr = packet[3] - local f = packet[4] - local e = packet[5] - if index == 0 then - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - else - local okay = fonts and fonts[index] - if okay then - local fnt = okay.id - if fnt then - pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) - end - else - -- safeguard, we assume the font itself (often index 1) - pos_h = pos_h + flushchar(font,char,font,chr,f,e) - end - end - elseif command == "use" then - local index = packet[2] - if index then - local fnt + -- we assume resolved fonts: id mandate but maybe also size + + -- we could map left, right, up, down -> offset + -- we could map char, font, slot to -> slot + + for i=1,#vfcommands do + local packet = vfcommands[i] + local command = packet[1] + if command == "char" then + local chr = packet[2] + local f = packet[3] + local e = packet[4] + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + elseif command == "slot" then + local index = packet[2] + local chr = packet[3] + local f = packet[4] + local e = packet[5] if index == 0 then - fnt = font + pos_h = pos_h + flushchar(font,char,font,chr,f,e) else local okay = fonts and fonts[index] if okay then - fnt = okay.id + local fnt = okay.id + if fnt then + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + end + else + -- safeguard, we assume the font itself (often index 1) + pos_h = pos_h + flushchar(font,char,font,chr,f,e) end end - if fnt then - -- not efficient but ok for now as experiment - local d = characters[fnt] - if d then - for i=3,#packet do - local chr = packet[i] - local dat = d[chr] - if dat then - flushfontchar(fnt,chr,dat) + elseif command == "use" then + local index = packet[2] + if index then + local fnt + if index == 0 then + fnt = font + else + local okay = fonts and fonts[index] + if okay then + fnt = okay.id + end + end + if fnt then + -- not efficient but ok for now as experiment + local d = characters[fnt] + if d then + for i=3,#packet do + local chr = packet[i] + local dat = d[chr] + if dat then + flushfontchar(fnt,chr,dat) + end end end end end - end - elseif command == "right" then - local h = packet[2] -- already scaled - if factor ~= 0 and h ~= 0 then - h = h + h * factor / 1000 -- expansion - end - h = h * sx - pos_h = pos_h + h - elseif command == "down" then - local v = packet[2] -- already scaled - v = v * sy - pos_v = pos_v - v - elseif command == "push" then - level = level + 1 - local s = stack[level] - s[1] = pos_h - s[2] = pos_v - elseif command == "pop" then - if level > 0 then - local s = stack[level] - pos_h = s[1] - pos_v = s[2] - level = level - 1 - end - elseif command == "rule" then - local size_v = packet[2] - local size_h = packet[3] - if size_h > 0 and size_v > 0 then - if factor ~= 0 then - size_h = size_h + size_h * factor / 1000 + elseif command == "right" then + local h = packet[2] -- already scaled + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h * sx end - if size_h > 0 then - size_h = size_h * sx - size_v = size_v * sy - flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) - pos_h = pos_h + size_h + elseif command == "left" then + local h = packet[2] -- already scaled + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h - h * sx end - end - elseif command == "frame" then - -- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color - local width = packet[2] - if width > 0 then - local height = packet[3] or 0 - local depth = packet[4] or 0 - local total = height + depth - if total > 0 then + elseif command == "down" then + local v = packet[2] -- already scaled + if v and v ~= 0 then + pos_v = pos_v - v * sy + end + elseif command == "up" then + local v = packet[2] -- already scaled + if v and v ~= 0 then + pos_v = pos_v + v * sy + end + elseif command == "offset" then + local h = packet[2] or 0 + local v = packet[3] or 0 + if h ~= 0 then if factor ~= 0 then - width = width + width * factor / 1000 + h = h + h * factor / 1000 -- expansion end - if width > 0 then - local line = packet[5] or default - local outline = not packet[6] - local advance = not packet[7] - local baseline = outline and packet[8] - local color = packet[9] - if color then - startcolor(color) - end - width = width * sx - height = height * sy - depth = depth * sy - flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline) - if color then - stopcolor() + pos_h = pos_h + h * sx + end + if v and v ~= 0 then + pos_v = pos_v + v * sy + end + elseif command == "push" then + level = level + 1 + local s = stack[level] + s[1] = pos_h + s[2] = pos_v + elseif command == "pop" then + if level > 0 then + local s = stack[level] + pos_h = s[1] + pos_v = s[2] + level = level - 1 + end + elseif command == "rule" then + local size_v = packet[2] + local size_h = packet[3] + if size_h > 0 and size_v > 0 then + if factor ~= 0 then + size_h = size_h + size_h * factor / 1000 + end + if size_h > 0 then + size_h = size_h * sx + size_v = size_v * sy + flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) + pos_h = pos_h + size_h + end + end + elseif command == "frame" then + -- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color + local width = packet[2] + if width > 0 then + local height = packet[3] or 0 + local depth = packet[4] or 0 + local total = height + depth + if total > 0 then + if factor ~= 0 then + width = width + width * factor / 1000 end - if advance then - pos_h = pos_h + width + if width > 0 then + local line = packet[5] or default + local outline = not packet[6] + local advance = not packet[7] + local baseline = outline and packet[8] + local color = packet[9] -- no longer needed probably + if color then + vfinjectors.startcolor(pos_h,pos_v,color) -- takes packet or string + end + width = width * sx + height = height * sy + depth = depth * sy + flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline) + if color then + vfinjectors.stopcolor() + end + if advance then + pos_h = pos_h + width + end end end end + elseif command == "font" then + local index = packet[2] + local okay = fonts and fonts[index] + if okay then + fnt = okay.id or fnt -- or maybe just return + end + elseif command == "lua" then + local code = packet[2] + local kind = type(code) + if kind ~= "function" then + code = loadstring(code) + kind = type(code) + end + if kind == "function" then + code(font,char,pos_h,pos_v,sx,sy) + end + elseif command == "node" then -- obsolete + local h = packet[2] + hlist_out(h,getlist(h)) + else + local injector = vfinjectors[command] + if injector then + injector(pos_h,pos_v,packet) + end end - elseif command == "font" then - local index = packet[2] - local okay = fonts and fonts[index] - if okay then - fnt = okay.id or fnt -- or maybe just return - end - elseif command == "lua" then - local code = packet[2] - local kind = type(code) - if kind ~= "function" then - code = loadstring(code) - kind = type(code) - end - if kind == "function" then - code(font,char,pos_h,pos_v,sx,sy) - end - elseif command == "node" then - -- us this really useful? - local h = packet[2] - hlist_out(h,getlist(h)) - elseif command == "pdf" then - -- this will disappear and become a plug - flushliteral(false,pos_h,pos_v,packet[2],packet[3]) - -- elseif command == "image" then - -- -- doesn't work because intercepted by engine so we use a different - -- -- mechanism (for now) - -- local image = packet[2] - -- -- to do - -- elseif command == "pdfmode" then - -- -- doesn't happen - -- elseif command == "special" then - -- -- not supported - -- elseif command == "nop" then - -- -- nothing to do| - -- elseif command == "scale" then - -- -- not supported + -- image : not needed, maybe some day + -- pdfmode : not used + -- special : makes no sense + -- nop : the official ignore + -- scale : not supported end - end - pos_h = saved_h - pos_v = saved_v - pos_r = saved_r + pos_h = saved_h + pos_v = saved_v + pos_r = saved_r - nesting = nesting - 1 -end + nesting = nesting - 1 + end -local onetimemessage -- could be defined later (todo: make plug for this) + local onetimemessage -- could be defined later (todo: make plug for this) -local getxyscales = nuts.getxyscales + local getxyscales = nuts.getxyscales -flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) + flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) - if font ~= lastfont then - lastfont = font - fontcharacters = characters[font] - updatefontstate(font) - end + if font ~= lastfont then + lastfont = font + fontcharacters = characters[font] + updatefontstate(font) + end - local data = fontcharacters[char] - if not data then - if char > 0 then - if not onetimemessage then - onetimemessage = fonts.loggers.onetimemessage + local data = fontcharacters[char] + if not data then + if char > 0 then + if not onetimemessage then + onetimemessage = fonts.loggers.onetimemessage + end + onetimemessage(font,char,"missing") end - onetimemessage(font,char,"missing") - end - return 0, 0, 0 - end - if vfcommands then - vfcommands = data.commands - end - local width, height, depth, naturalwidth, sx, sy - if current then - naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width - sx, sy = getxyscales(current) -- maybe: getwhdfs - if factor == 0 then - width = naturalwidth - else - -- width = (1.0 + factor/1000000.0) * naturalwidth - width = naturalwidth + naturalwidth * factor/1000000.0 - -- width = naturalwidth + naturalwidth * 0.000001 * factor + return 0, 0, 0 end - else - width = data.width or 0 - height = data.height or 0 - depth = data.depth or 0 - naturalwidth = width - if not factor then - factor = 0 + if vfcommands then + vfcommands = data.commands end - sx = 1 - sy = 1 - end - if pos_r == righttoleft_code then - pos_h = pos_h - width -- here ? - end - if vfcommands then - flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ? - else - -- kind of messy that we do orientation here and offsets elsewhere - local orientation = data.orientation - if orientation and (orientation == 1 or orientation == 3) then - local x = data.xoffset - local y = data.yoffset - if x then - pos_h = pos_h + x + local width, height, depth, naturalwidth, sx, sy + if current then + naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width + sx, sy = getxyscales(current) -- maybe: getwhdfs + if factor == 0 then + width = naturalwidth + else + -- width = (1.0 + factor/1000000.0) * naturalwidth + width = naturalwidth + naturalwidth * factor/1000000.0 + -- width = naturalwidth + naturalwidth * 0.000001 * factor end - if y then - pos_v = pos_v + y + else + width = data.width or 0 + height = data.height or 0 + depth = data.depth or 0 + naturalwidth = width + if not factor then + factor = 0 end - pushorientation(orientation,pos_h,pos_v) - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) - poporientation(orientation,pos_h,pos_v) + sx = 1 + sy = 1 + end + if pos_r == righttoleft_code then + pos_h = pos_h - width -- here ? + end + if vfcommands then + flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ? else - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + -- kind of messy that we do orientation here and offsets elsewhere .. this might change + local orientation = data.orientation + if orientation and (orientation == 1 or orientation == 3) then + local x = data.xoffset + local y = data.yoffset + if x then + pos_h = pos_h + x + end + if y then + pos_v = pos_v + y + end + pushorientation(orientation,pos_h,pos_v) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + poporientation(orientation,pos_h,pos_v) + else + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + end end + return width, height, depth end - return width, height, depth + end -- end of characters @@ -536,6 +533,13 @@ local function flushcloseout(current) end end +local function flushsavepos(current,pos_h,pos_v) + jobpositions.lastx = pos_h + jobpositions.lasty = pos_v +end + +local flushwhatsit + local hlist_out, vlist_out do local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) @@ -905,26 +909,7 @@ local hlist_out, vlist_out do goto synced end elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end + flushwhatsit[subtype](current,pos_h,pos_v) elseif id == disc_code then local replace, tail = getreplace(current) -- actually, we no longer have these select discs in the packaged list ... it's about @@ -1164,26 +1149,7 @@ local hlist_out, vlist_out do end cur_v = cur_v + total elseif id == whatsit_code then - if subtype == literalwhatsit_code then - flushliteral(current,pos_h,pos_v) - elseif subtype == lateluawhatsit_code then - flushlatelua(current,pos_h,pos_v) - elseif subtype == setmatrixwhatsit_code then - flushsetmatrix(current,pos_h,pos_v) - elseif subtype == savewhatsit_code then - flushsave(current,pos_h,pos_v) - elseif subtype == restorewhatsit_code then - flushrestore(current,pos_h,pos_v) - elseif subtype == saveposwhatsit_code then - last_position_x = pos_h - last_position_y = pos_v - elseif subtype == writewhatsit_code then - flushwriteout(current) - elseif subtype == closewhatsit_code then - flushcloseout(current) - elseif subtype == openwhatsit_code then - flushopenout(current) - end + flushwhatsit[subtype](current,pos_h,pos_v) else -- penalty goto synced @@ -1223,22 +1189,47 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification) initialize = actions.initialize finalize = actions.finalize - updatefontstate = flushers.updatefontstate - - pushorientation = flushers.pushorientation - poporientation = flushers.poporientation + -- we need to do this once ... + + if not updatefontstate then + + updatefontstate = flushers.updatefontstate + + pushorientation = flushers.pushorientation + poporientation = flushers.poporientation + + flushcharacter = flushers.character + flushfontchar = flushers.fontchar + flushrule = flushers.rule + flushsimplerule = flushers.simplerule + flushspecialrule = flushers.specialrule + flushliteral = flushers.literal + + flushwhatsit = setmetatableindex ( { + [whatsitcodes.literal] = flushliteral, + [whatsitcodes.latelua] = flushlatelua, + [whatsitcodes.userdefined] = function() end, -- special purpose, handled in callbacks + [whatsitcodes.savepos] = flushsavepos, -- only used by generic packages + [whatsitcodes.save] = flushers.save, + [whatsitcodes.restore] = flushers.restore, + [whatsitcodes.setmatrix] = flushers.setmatrix, + [whatsitcodes.open] = flushopenout, -- generic + [whatsitcodes.close] = flushcloseout, -- generic + [whatsitcodes.write] = flushwriteout, -- generic + [whatsitcodes.startmatrix] = flushers.startmatrix, + [whatsitcodes.stopmatrix] = flushers.stopmatrix, + [whatsitcodes.startscaling] = flushers.startscaling, + [whatsitcodes.stopscaling] = flushers.stopscaling, + [whatsitcodes.startrotation] = flushers.startrotation, + [whatsitcodes.stoprotation] = flushers.stoprotation, + [whatsitcodes.startmirroring] = flushers.startmirroring, + [whatsitcodes.stopmirroring] = flushers.stopmirroring, + [whatsitcodes.startclipping] = flushers.startclipping, + [whatsitcodes.stopclipping] = flushers.stopclipping, + [whatsitcodes.setstate] = flushers.setstate, + }, function(t, k) report("weird whatsit %a",k) return function() end end) - flushcharacter = flushers.character - flushfontchar = flushers.fontchar - flushrule = flushers.rule - flushsimplerule = flushers.simplerule - flushspecialrule = flushers.specialrule - flushspecial = flushers.special - flushliteral = flushers.literal - flushsetmatrix = flushers.setmatrix - flushsave = flushers.save - flushrestore = flushers.restore - -- flushimage = flushers.image + end reset_dir_stack() reset_state() @@ -1279,12 +1270,6 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification) local pagewidth, pageheight = getpagedimensions() - -- local h_offset_par = texget("hoffset") - -- local v_offset_par = texget("voffset") - - -- page_h_origin = trueinch - -- page_v_origin = trueinch - pos_r = lefttoright_code if pagewidth > 0 then @@ -1307,17 +1292,14 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification) page_size_v = total end - local refpoint_h = 0 -- + page_h_origin + h_offset_par - local refpoint_v = page_size_v -- - page_v_origin - v_offset_par + local refpoint_h = 0 + local refpoint_v = page_size_v pos_h = refpoint_h pos_v = refpoint_v - height - -- synced else - -- page_h_origin = 0 - -- page_v_origin = 0 page_size_h = width page_size_v = total pos_r = getdirection(box) diff --git a/tex/context/base/mkxl/font-chk.lmt b/tex/context/base/mkxl/font-chk.lmt index 7141be2c7..8e73d1b3c 100644 --- a/tex/context/base/mkxl/font-chk.lmt +++ b/tex/context/base/mkxl/font-chk.lmt @@ -64,7 +64,6 @@ local implement = interfaces.implement local glyph_code = nodes.nodecodes.glyph -local new_special = nodes.pool.special -- todo: literal local hpack_node = node.hpack local nuts = nodes.nuts diff --git a/tex/context/base/mkxl/font-con.lmt b/tex/context/base/mkxl/font-con.lmt index 88e17290a..60e3f0233 100644 --- a/tex/context/base/mkxl/font-con.lmt +++ b/tex/context/base/mkxl/font-con.lmt @@ -51,6 +51,8 @@ constructors.designsizes = designsizes local loadedfonts = allocate() constructors.loadedfonts = loadedfonts +----- scalecommands = fonts.helpers.scalecommands + --[[ldx-- <p>We need to normalize the scale factor (in scaled points). This has to do with the fact that <l n='tex'/> uses a negative multiple of 1000 as @@ -260,6 +262,8 @@ function constructors.scale(tfmdata,specification) end target.specification = specification -- + local scalecommands = fonts.helpers.scalecommands -- defined later + -- local scaledpoints = specification.size local relativeid = specification.relativeid -- @@ -774,37 +778,7 @@ function constructors.scale(tfmdata,specification) end local vc = character.commands if vc then - -- we assume non scaled commands here - -- tricky .. we need to scale pseudo math glyphs too - -- which is why we deal with rules too - local ok = false - for i=1,#vc do - local key = vc[i][1] - if key == "right" or key == "down" or key == "rule" then - ok = true - break - end - end - if ok then - local tt = { } - for i=1,#vc do - local ivc = vc[i] - local key = ivc[1] - if key == "right" then - tt[i] = { key, ivc[2]*hdelta } - elseif key == "down" then - tt[i] = { key, ivc[2]*vdelta } - elseif key == "rule" then - tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta } - else -- not comment - tt[i] = ivc -- shared since in cache and untouched - end - end - chr.commands = tt - else - chr.commands = vc - end - -- chr.index = nil + chr.commands = scalecommands(vc,hdelta,vdelta) end targetcharacters[unicode] = chr end diff --git a/tex/context/base/mkxl/font-fbk.lmt b/tex/context/base/mkxl/font-fbk.lmt index 651bca331..47d284c84 100644 --- a/tex/context/base/mkxl/font-fbk.lmt +++ b/tex/context/base/mkxl/font-fbk.lmt @@ -63,13 +63,12 @@ local function composecharacters(tfmdata) local deltaxheight = scale * (Xdesc.boundingbox[4] - xdesc.boundingbox[4]) local extraxheight = fraction * deltaxheight -- maybe use compose value local italicfactor = parameters.italicfactor or 0 - local vfspecials = backends.tables.vfspecials --brr local red, green, blue, black if trace_visualize then - red = vfspecials.startcolor("red") - green = vfspecials.startcolor("green") - blue = vfspecials.startcolor("blue") - black = vfspecials.stopcolor + red = { "startcolor", "red" } + green = { "startcolor", "green" } + blue = { "startcolor", "blue" } + black = { "stopcolor" } end local compose = fonts.goodies.getcompositions(tfmdata) if compose and trace_visualize then diff --git a/tex/context/base/mkxl/font-imp-math.lmt b/tex/context/base/mkxl/font-imp-math.lmt index 079c867e2..277190f24 100644 --- a/tex/context/base/mkxl/font-imp-math.lmt +++ b/tex/context/base/mkxl/font-imp-math.lmt @@ -70,6 +70,35 @@ registerotffeature { -- A quick and dirty and low level implementation but okay for testing: +function fonts.helpers.mathscriptslots(tfmdata,textcode) + local rawdata = tfmdata.shared.rawdata + local rawresources = rawdata and rawdata.resources + local rawfeatures = rawresources and rawresources.features + local basesubstitutions = rawfeatures and rawfeatures.gsub + local sequences = basesubstitutions and tfmdata.resources.sequences + if sequences then + local characters = tfmdata.characters + if characters[textcode] then + for s=1,#sequences do + local sequence = sequences[s] + local sfeatures = sequence.features + if sfeatures and sfeatures.ssty then + local steps = sequence.steps + for i=1,#steps do + local coverage = steps[i].coverage + if coverage then + local okay = coverage[textcode] + if okay then + return okay + end + end + end + end + end + end + end +end + local function manipulate(tfmdata,key,value) if texconditionals["c_font_compact"] then local rawdata = tfmdata.shared.rawdata @@ -81,7 +110,7 @@ local function manipulate(tfmdata,key,value) if sequences then local characters = tfmdata.characters for s=1,#sequences do - local sequence = sequences[s] + local sequence = sequences[s] local sfeatures = sequence.features if sfeatures and sfeatures.ssty then local steps = sequence.steps diff --git a/tex/context/base/mkxl/font-imp-tracing.lmt b/tex/context/base/mkxl/font-imp-tracing.lmt new file mode 100644 index 000000000..59603c9dd --- /dev/null +++ b/tex/context/base/mkxl/font-imp-tracing.lmt @@ -0,0 +1,286 @@ +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" +} + +local abs = math.abs + +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 + +local function initialize(tfmdata,key,value) + if value then + local vfspecials = fonts.helpers.vfspecials + local vfcommands = fonts.helpers.commands + local backgrounds = vfspecials.backgrounds + local outlines = vfspecials.outlines + local characters = tfmdata.characters + local rulecache = backgrounds + 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 = outlines + elseif v == v_background then + rulecache = backgrounds + 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 function initialize(tfmdata,key,value) + if value then + local rawdata = tfmdata.shared.rawdata + local rawresources = rawdata and rawdata.resources + local mathconstants = rawresources.mathconstants + if mathconstants then + local vfspecials = fonts.helpers.vfspecials + local vfcommands = fonts.helpers.commands + local backgrounds = vfspecials.backgrounds + local outlines = vfspecials.outlines + local characters = tfmdata.characters + local rulecache = backgrounds + local push = vfcommands.push + local pop = vfcommands.pop + local black = { "stopcolor" } + local itcolor = { "startcolor", "trace:0" } -- s / dd (transparent) + local brcolor = { "startcolor", "trace:1" } -- r / dr + local trcolor = { "startcolor", "trace:2" } -- g / dg + local blcolor = { "startcolor", "trace:3" } -- b / db + local tlcolor = { "startcolor", "trace:4" } -- y / dy + for unicode, character in next, characters do + local mathkern = character.mathkern + local italic = character.vert_italic or character.italic + if mathkern or (italic and italic ~= 0) then + local width = character.width or 0 + local height = character.height or 0 + local depth = character.depth or 0 + local list = { } + local count = 0 + if italic and italic ~= 0 then + count = count + 1 list[count] = itcolor + count = count + 1 list[count] = push + count = count + 1 list[count] = { "offset", width + (italic < 0 and -italic or 0), 0 } + count = count + 1 list[count] = rulecache[height][depth][abs(-italic)] + count = count + 1 list[count] = pop + count = count + 1 list[count] = black + end + if mathkern then + local br = mathkern.bottom_right + local tr = mathkern.top_right + local bl = mathkern.bottom_left + local tl = mathkern.top_left + if br then + local done = false + for i=1,#br do + local l = br[i] + local h = l.height or 0 + local k = l.kern or 0 + if k ~= 0 then + if h == 0 then + h = height + depth -- todo max + end + if not done then + count = count + 1 list[count] = brcolor + done = true + end + count = count + 1 list[count] = push + count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), - depth } + count = count + 1 list[count] = rulecache[h][0][abs(k)] + count = count + 1 list[count] = pop + end + end + if done then + count = count + 1 list[count] = black + end + end + if tr then + local done = false + for i=1,#tr do + local l = tr[i] + local h = l.height or 0 + local k = l.kern or 0 + if k ~= 0 then + if h == 0 then + h = height + depth -- todo max + end + if not done then + count = count + 1 list[count] = trcolor + done = true + end + count = count + 1 list[count] = push + count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), height - h } + count = count + 1 list[count] = rulecache[h][0][abs(k)] + count = count + 1 list[count] = pop + end + end + if done then + count = count + 1 list[count] = black + end + end + if bl then + local done = false + for i=1,#bl do + local l = bl[i] + local h = l.height or 0 + local k = l.kern or 0 + if k ~= 0 then + if h == 0 then + h = height + depth -- todo max + end + if not done then + count = count + 1 list[count] = blcolor + done = true + end + count = count + 1 list[count] = push + count = count + 1 list[count] = { "offset", (k < 0 and k or 0), -depth } + count = count + 1 list[count] = rulecache[h][0][abs(k)] + count = count + 1 list[count] = pop + end + end + if done then + count = count + 1 list[count] = black + end + end + if tl then + local done = false + for i=1,#tl do + local l = tl[i] + local h = l.height or 0 + local k = l.kern or 0 + if k ~= 0 then + if h == 0 then + h = height + depth -- todo max + end + if not done then + count = count + 1 list[count] = tlcolor + done = true + end + count = count + 1 list[count] = push + count = count + 1 list[count] = { "offset", (k < 0 and k or 0), height - h } + count = count + 1 list[count] = rulecache[h][0][abs(k)] + count = count + 1 list[count] = pop + end + end + if done then + count = count + 1 list[count] = black + end + end + end + if count > 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 +end + +local specification = { + name = "staircase", + description = "show staircase kerns", +-- position = 1, + manipulators = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) +registerafmfeature(specification) diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx index 00bddc2c3..e90973d75 100644 --- a/tex/context/base/mkxl/font-lib.mklx +++ b/tex/context/base/mkxl/font-lib.mklx @@ -17,7 +17,7 @@ \registerctxluafile{font-ini}{autosuffix} \registerctxluafile{font-log}{} -\registerctxluafile{font-con}{autosuffix} +\registerctxluafile{font-con}{autosuffix} % kind of early %registerctxluafile{font-cft}{} \registerctxluafile{font-enc}{} \registerctxluafile{font-fmp}{autosuffix} @@ -88,7 +88,7 @@ \registerctxluafile{good-ini}{} \registerctxluafile{good-gen}{} \registerctxluafile{good-ctx}{} -\registerctxluafile{good-mth}{} +\registerctxluafile{good-mth}{autosuffix} \registerctxluafile{font-def}{autosuffix} \registerctxluafile{font-ctx}{autosuffix} % after def as it overloads @@ -116,7 +116,7 @@ % not yet, lmtx feature } -\registerctxluafile{font-imp-tracing}{} % comes last! +\registerctxluafile{font-imp-tracing}{autosuffix} % comes last! \registerctxluafile{font-fbk}{autosuffix} diff --git a/tex/context/base/mkxl/font-ogr.lmt b/tex/context/base/mkxl/font-ogr.lmt index df6449ded..a3f8acb3c 100644 --- a/tex/context/base/mkxl/font-ogr.lmt +++ b/tex/context/base/mkxl/font-ogr.lmt @@ -242,6 +242,8 @@ do -- this will move to its own module return false end + -- list of tonumber keywords + local function initializemps(tfmdata,kind,value) if value then local specification = settings_to_hash_strict(value) @@ -256,9 +258,20 @@ do -- this will move to its own module local categories = settings_to_array(category) local usedshapes = nil local index = 0 - local spread = tonumber(specification.spread or 0) + local spread = tonumber(specification.spread or 0) -- hm local hascolor = hascolorspec(specification) - specification.spread = spread -- now a number + + specification.spread = spread -- now a number, maybe also for slant, weight etc + + local preroll = specification.preroll + if preroll then + metapost.simple(instance,"begingroup;",true,true) + metapost.setparameterset("mpsfont",specification) + metapost.simple("simplefun",preroll) + metapost.setparameterset("mpsfont") + metapost.simple(instance,"endgroup;",true,true) + end + for i=1,#categories do local category = categories[i] local mpsshapes = shapes[category] @@ -291,25 +304,39 @@ do -- this will move to its own module } -- todo: deal with extensibles and more properties for unicode, shape in sortedhash(mpsshapes.glyphs) do - -- local oldc = characters[unicode] - -- if oldc then - index = index + 1 -- todo: somehow we end up with 2 as first entry after 0 - local wd = shape.width or defaultwidth - local ht = shape.height or defaultheight - local dp = shape.depth or defaultdepth - local newc = { - index = index, -- into usedshapes - width = scale * (wd + spread), - height = scale * ht, - depth = scale * dp, - unicode = unicode, - } - -- - characters [unicode] = newc - descriptions[unicode] = newc - -- - usedshapes[unicode] = shape.code or defaultcode - -- end + index = index + 1 -- todo: somehow we end up with 2 as first entry after 0 + local wd = shape.width or defaultwidth + local ht = shape.height or defaultheight + local dp = shape.depth or defaultdepth + local uc = shape.tounicode + if uc then + uc = round(uc) -- brrr can be 123.0 + end + local newc = { + index = index, -- into usedshapes + width = scale * (wd + spread), + height = scale * ht, + depth = scale * dp, + unicode = uc or unicode, + } + -- + characters [unicode] = newc + descriptions[unicode] = newc + usedshapes [unicode] = shape.code or defaultcode + -- + -- This is a way to get/use randomized shapes (see punk example). + -- + if uc and uc ~= unicode then + local c = characters[uc] + if c then + local v = c.variants + if v then + v[#v + 1] = unicode + else + c.variants = { unicode } + end + end + end end end end diff --git a/tex/context/base/mkxl/font-pre.mkxl b/tex/context/base/mkxl/font-pre.mkxl index fafe20a60..884a6c913 100644 --- a/tex/context/base/mkxl/font-pre.mkxl +++ b/tex/context/base/mkxl/font-pre.mkxl @@ -405,7 +405,9 @@ mathalternates=yes, mathitalics=yes, % we pass them mathdimensions=all, -compactmath=yes, + % mathkerns=yes, + % staircase=yes, + compactmath=yes, % mathgaps=yes, language=dflt, script=math] diff --git a/tex/context/base/mkxl/font-vfc.lmt b/tex/context/base/mkxl/font-vfc.lmt index e39eca683..9330bdea0 100644 --- a/tex/context/base/mkxl/font-vfc.lmt +++ b/tex/context/base/mkxl/font-vfc.lmt @@ -71,13 +71,111 @@ function helpers.appendcommandtable(commands,t) end helpers.commands = utilities.storage.allocate { - char = setmetatableindex(function(t,k) local v = { "slot", 0, k } t[k] = v return v end), - right = setmetatableindex(function(t,k) local v = { "right", k } t[k] = v return v end), - left = setmetatableindex(function(t,k) local v = { "right", -k } t[k] = v return v end), -- todo: left - down = setmetatableindex(function(t,k) local v = { "down", k } t[k] = v return v end), - up = setmetatableindex(function(t,k) local v = { "down", -k } t[k] = v return v end), -- todo: up + char = setmetatableindex(function(t,k) local v = { "slot", 0, k } t[k] = v return v end), + right = setmetatableindex(function(t,k) local v = { "right", k } t[k] = v return v end), + left = setmetatableindex(function(t,k) local v = { "left", k } t[k] = v return v end), + down = setmetatableindex(function(t,k) local v = { "down", k } t[k] = v return v end), + up = setmetatableindex(function(t,k) local v = { "up", k } t[k] = v return v end), push = push, pop = pop, dummy = dummy, } +helpers.vfinjectors = { + -- backend specific: startcolor, stopcolor etc +} + +-- maybe round() + +local defaultline = 16384 + +helpers.vfspecials = { + + backgrounds = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, true, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v + end), + + outlines = setmetatableindex(function(t,h) + local v = setmetatableindex(function(t,d) + local v = setmetatableindex(function(t,w) + local v = { "frame", w, h, d, defaultline, false, true } + t[w] = v + return v + end) + t[d] = v + return v + end) + t[h] = v + return v + end), + +} + +-- In the past we only copied when we had something that got scaled but the problem +-- is that we then run into issues when we extend a commands in the parent. This +-- needs checking. When we go to glyph scaling, this can go away. +-- +-- The alternative is to work with unscaled values and always do scaling at the +-- TeX end. So, then we need accessors instead of tables and we also need to check +-- all the context code: where do we access values? +-- +-- On the other hand, in glyph scale mode we hardly do any scaling so we seldom +-- call the next one. +-- +-- What if we use named fields: then we can scale by field name. + +local scaled = { + right = true, + down = true, + left = true, + right = true, + offset = true, + rule = true, + char = false, + font = false, + slot = false, + use = false, + push = false, + pop = false, + lua = false, + -- obsolete + node = false, + -- additional ones are never scaled (color etc) +} + +function helpers.scalecommands(list,hdelta,vdelta) + local n = #list + for i=1,n do + local key = list[i][1] + if scaled[list[i][1]] then + local result = { } + for i=1,n do + local cmd = list[i] + local key = ivc[1] + if key == "right" or key == "left" then + result[i] = { key, cmd[2]*hdelta } + elseif key == "down" or key == "up" then + result[i] = { key, cmd[2]*vdelta } + elseif key == "offset" or key == "rule" then + result[i] = { key, cmd[2]*hdelta, cmd[3]*vdelta } + -- elseif key == "frame" then + -- result[i] = cmd -- already scaled, for now + else + result[i] = cmd -- shared since in cache and untouched + end + end + return result + end + end + return list +end diff --git a/tex/context/base/mkxl/good-mth.lmt b/tex/context/base/mkxl/good-mth.lmt new file mode 100644 index 000000000..87b6787df --- /dev/null +++ b/tex/context/base/mkxl/good-mth.lmt @@ -0,0 +1,464 @@ +if not modules then modules = { } end modules ['good-mth'] = { + version = 1.000, + comment = "companion to font-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, next, tonumber, unpack = type, next, tonumber, unpack +local ceil = math.ceil +local match = string.match + +local fonts = fonts + +local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) +local report_goodies = logs.reporter("fonts","goodies") + +local registerotffeature = fonts.handlers.otf.features.register + +local fontgoodies = fonts.goodies or { } + +local fontcharacters = fonts.hashes.characters + +local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) + +local report_math = logs.reporter("mathematics","initializing") + +local nuts = nodes.nuts + +local setlink = nuts.setlink + +local nodepool = nuts.pool + +local new_kern = nodepool.kern +local new_glyph = nodepool.glyph +local new_hlist = nodepool.hlist +local new_vlist = nodepool.vlist + +local insert_node_after = nuts.insert_after + +local helpers = fonts.helpers +local upcommand = helpers.commands.up +local rightcommand = helpers.commands.right +local charcommand = helpers.commands.char +local prependcommands = helpers.prependcommands + +-- experiment, we have to load the definitions immediately as they precede +-- the definition so they need to be initialized in the typescript + +local function withscriptcode(tfmdata,unicode,data,action) + if type(unicode) == "string" then + local p, u = match(unicode,"^(.-):(.-)$") + if u then + u = tonumber(u) + if u then + local slots = fonts.helpers.mathscriptslots(tfmdata,u) + if slots then + if p == "*" then + action(u,data) + for i=1,#slots do + action(slots[i],data) + end + else + p = tonumber(p) + if p then + action(slots[p],data) + end + end + end + end + end + else + action(unicode,data) + end +end + +local function finalize(tfmdata,feature,value) +-- if tfmdata.mathparameters then -- funny, cambria text has this + local goodies = tfmdata.goodies + if goodies then + local virtualized = mathematics.virtualized + for i=1,#goodies do + local goodie = goodies[i] + local mathematics = goodie.mathematics + local dimensions = mathematics and mathematics.dimensions + if dimensions then + if trace_defining then + report_math("overloading dimensions in %a @ %p",tfmdata.properties.fullname,tfmdata.parameters.size) + end + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local parameters = tfmdata.parameters + local factor = parameters.factor + local hfactor = parameters.hfactor + local vfactor = parameters.vfactor + -- + tfmdata.type = "virtual" + tfmdata.properties.virtualized = true + -- + local function overloadone(unicode,data) + local character = characters[unicode] + if not character then + local c = virtualized[unicode] + if c then + character = characters[c] + end + end + if character then + local width = data.width + 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 %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 + if depth then character.depth = depth * vfactor end + -- + local xoffset = data.xoffset + local yoffset = data.yoffset + if xoffset == "llx" then + local d = descriptions[unicode] + if d then + xoffset = - d.boundingbox[1] * hfactor + character.width = character.width + xoffset + xoffset = rightcommand[xoffset] + else + xoffset = nil + end + elseif xoffset and xoffset ~= 0 then + xoffset = rightcommand[xoffset * hfactor] + else + xoffset = nil + end + if yoffset and yoffset ~= 0 then + yoffset = upcommand[yoffset * vfactor] + else + yoffset = nil + end + if xoffset or yoffset then + local commands = characters.commands + if commands then + prependcommands(commands,yoffset,xoffset) + else + local slot = charcommand[unicode] + if xoffset and yoffset then + character.commands = { xoffset, yoffset, slot } + elseif xoffset then + character.commands = { xoffset, slot } + else + character.commands = { yoffset, slot } + end + end + end + elseif trace_defining then + report_math("no overloading dimensions of %C, not in font",unicode) + end + end + local function overload(dimensions) + for unicode, data in next, dimensions do + withscriptcode(tfmdata,unicode,data,overloadone) + end + end + if value == nil then + value = { "default" } + end + if value == "all" or value == true then + for name, value in next, dimensions do + overload(value) + end + else + if type(value) == "string" then + value = utilities.parsers.settings_to_array(value) + end + if type(value) == "table" then + for i=1,#value do + local d = dimensions[value[i]] + if d then + overload(d) + end + end + end + end + end + end + end +end + +registerotffeature { + name = "mathdimensions", + description = "manipulate math dimensions", + -- default = true, + manipulators = { + base = finalize, + node = finalize, + } +} + +local function initialize(goodies) + local mathgoodies = goodies.mathematics + if mathgoodies then + local virtuals = mathgoodies.virtuals + local mapfiles = mathgoodies.mapfiles + local maplines = mathgoodies.maplines + if virtuals then + for name, specification in next, virtuals do + -- beware, they are all constructed ... we should be more selective + mathematics.makefont(name,specification,goodies) + end + end + if mapfiles then + for i=1,#mapfiles do + fonts.mappings.loadfile(mapfiles[i]) -- todo: backend function + end + end + if maplines then + for i=1,#maplines do + fonts.mappings.loadline(maplines[i]) -- todo: backend function + end + end + end +end + +fontgoodies.register("mathematics", initialize) + +-- local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end) + +local function initialize(tfmdata) +-- if enabled and tfmdata.mathparameters then -- funny, cambria text has this + if tfmdata.mathparameters then -- funny, cambria text has this + local goodies = tfmdata.goodies + if goodies then + local characters = tfmdata.characters + if characters[0x1D44E] then -- 119886 + -- we have at least an italic a + for i=1,#goodies do + local mathgoodies = goodies[i].mathematics + if mathgoodies then + local kerns = mathgoodies.kerns + if kerns then + local function kernone(unicode,data) + local chardata = characters[unicode] + if chardata and (not chardata.mathkerns or data.force) then + chardata.mathkerns = data + end + end + for unicode, data in next, kerns do + withscriptcode(tfmdata,unicode,data,kernone) + end + return + end + end + end + else + return -- no proper math font anyway + end + end + end +end + +registerotffeature { + name = "mathkerns", + description = "math kerns", + -- default = true, + initializers = { + base = initialize, + node = initialize, + } +} + +-- math italics (not really needed) +-- +-- it would be nice to have a \noitalics\font option + +local function initialize(tfmdata) + local goodies = tfmdata.goodies + if goodies then + local shared = tfmdata.shared + for i=1,#goodies do + local mathgoodies = goodies[i].mathematics + if mathgoodies then + local mathitalics = mathgoodies.italics + if mathitalics then + local properties = tfmdata.properties + if properties.setitalics then + mathitalics = mathitalics[file.nameonly(properties.name)] or mathitalics + if mathitalics then + if trace_goodies then + report_goodies("loading mathitalics for font %a",properties.name) + end + local corrections = mathitalics.corrections + local defaultfactor = mathitalics.defaultfactor + -- properties.mathitalic_defaultfactor = defaultfactor -- we inherit outer one anyway (name will change) + if corrections then + fontgoodies.registerpostprocessor(tfmdata, function(tfmdata) -- this is another tfmdata (a copy) + -- better make a helper so that we have less code being defined + local properties = tfmdata.properties + local parameters = tfmdata.parameters + local characters = tfmdata.characters + properties.mathitalic_defaultfactor = defaultfactor + properties.mathitalic_defaultvalue = defaultfactor * parameters.quad + if trace_goodies then + report_goodies("assigning mathitalics for font %a",properties.name) + end + local quad = parameters.quad + local hfactor = parameters.hfactor + for k, v in next, corrections do + local c = characters[k] + if c then + if v > -1 and v < 1 then + c.italic = v * quad + else + c.italic = v * hfactor + end + else + report_goodies("invalid mathitalics entry %U for font %a",k,properties.name) + end + end + end) + end + return -- maybe not as these can accumulate + end + end + end + end + end + end +end + +registerotffeature { + name = "mathitalics", + description = "additional math italic corrections", + -- default = true, + initializers = { + base = initialize, + node = initialize, + } +} + +-- fontgoodies.register("mathitalics", initialize) + +local function mathradicalaction(n,h,v,font,mchar,echar) + local characters = fontcharacters[font] + local mchardata = characters[mchar] + local echardata = characters[echar] + local ewidth = echardata.width + local mwidth = mchardata.width + local delta = h - ewidth + local glyph = new_glyph(font,echar) + local head = glyph + if delta > 0 then + local count = ceil(delta/mwidth) + local kern = (delta - count * mwidth) / count + for i=1,count do + local k = new_kern(kern) + local g = new_glyph(font,mchar) + setlink(k,head) + setlink(g,k) + head = g + end + end + local height = mchardata.height + local list = new_hlist(head) + local kern = new_kern(height-v) + list = setlink(kern,list) + local list = new_vlist(kern) + insert_node_after(n,n,list) +end + +local function mathhruleaction(n,h,v,font,bchar,mchar,echar) + local characters = fontcharacters[font] + local bchardata = characters[bchar] + local mchardata = characters[mchar] + local echardata = characters[echar] + local bwidth = bchardata.width + local mwidth = mchardata.width + local ewidth = echardata.width + local delta = h - ewidth - bwidth + local glyph = new_glyph(font,echar) + local head = glyph + if delta > 0 then + local count = ceil(delta/mwidth) + local kern = (delta - count * mwidth) / (count+1) + for i=1,count do + local k = new_kern(kern) + local g = new_glyph(font,mchar) + setlink(k,head) + setlink(g,k) + head = g + end + local k = new_kern(kern) + setlink(k,head) + head = k + end + local g = new_glyph(font,bchar) + setlink(g,head) + head = g + local height = mchardata.height + local list = new_hlist(head) + local kern = new_kern(height-v) + list = setlink(kern,list) + local list = new_vlist(kern) + insert_node_after(n,n,list) +end + +local function initialize(tfmdata) + local goodies = tfmdata.goodies + if goodies then + local resources = tfmdata.resources + local ruledata = { } + for i=1,#goodies do + local mathematics = goodies[i].mathematics + if mathematics then + local rules = mathematics.rules + if rules then + for tag, name in next, rules do + ruledata[tag] = name + end + end + end + end + if next(ruledata) then + local characters = tfmdata.characters + local unicodes = resources.unicodes + if characters and unicodes then + local mathruleactions = resources.mathruleactions + if not mathruleactions then + mathruleactions = { } + resources.mathruleactions = mathruleactions + end + -- + local mchar = unicodes[ruledata["radical.extender"] or false] + local echar = unicodes[ruledata["radical.end"] or false] + if mchar and echar then + mathruleactions.radicalaction = function(n,h,v,font) + mathradicalaction(n,h,v,font,mchar,echar) + end + end + -- + local bchar = unicodes[ruledata["hrule.begin"] or false] + local mchar = unicodes[ruledata["hrule.extender"] or false] + local echar = unicodes[ruledata["hrule.end"] or false] + if bchar and mchar and echar then + mathruleactions.hruleaction = function(n,h,v,font) + mathhruleaction(n,h,v,font,bchar,mchar,echar) + end + end + -- not that nice but we need to register it at the tex end + -- context.enablemathrules("\\fontclass") + end + end + end +end + +registerotffeature { + name = "mathrules", + description = "check math rules", + default = true, + initializers = { + base = initialize, + node = initialize, + } +} diff --git a/tex/context/base/mkxl/layo-ini.lmt b/tex/context/base/mkxl/layo-ini.lmt new file mode 100644 index 000000000..1570075d9 --- /dev/null +++ b/tex/context/base/mkxl/layo-ini.lmt @@ -0,0 +1,115 @@ +if not modules then modules = { } end modules ['layo-ini'] = { + version = 1.001, + comment = "companion to layo-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- We need to share information between the TeX and Lua end about the typographical +-- model. This happens here. This code might move. + +local texgetcount = tex.getcount +local conditionals = tex.conditionals + +layouts = { + status = { }, +} + +local status = layouts.status + +function status.leftorrightpageaction(left,right) + if left == nil then + left, right = false, true + end + if not conditionals.layoutisdoublesided then + return left, right + elseif conditionals.layoutissinglesided then + return left, right + elseif texgetcount("pagenoshift") % 2 == 0 then + if texgetcount("realpageno") % 2 == 0 then + return right, left + else + return left, right + end + else + if texgetcount("realpageno") % 2 == 0 then + return left, right + else + return right, left + end + end +end + +function status.isleftpage(r) + if not conditionals.layoutisdoublesided then + return false + elseif conditionals.layoutissinglesided then + return false + elseif texgetcount("pagenoshift") % 2 == 0 then + return (r or texgetcount("realpageno")) % 2 == 0 + else + return not (r or texgetcount("realpageno")) % 2 == 0 + end +end + +-- Instead of making these these driver specific we make them generic. We can even consider +-- to make these registers at the tex end. + +local canvas = { + pagespec = "default", -- v_default + paperwidth = 0, + paperheight = 0, + topoffset = 0, + leftoffset = 0, + height = 0, + width = 0, + cropoffset = 0, + bleedoffset = 0, + trimoffset = 0, + artoffset = 0, + doublesided = false, + marked = false, + copies = false, +} + +function layouts.setupcanvas(specification) + local paperheight = specification.paperheight or canvas.paperheight + local paperwidth = specification.paperwidth or canvas.paperwidth + local cropoffset = specification.cropoffset or 0 + local trimoffset = cropoffset - (specification.trimoffset or 0) + local bleedoffset = trimoffset - (specification.bleedoffset or 0) + local artoffset = bleedoffset - (specification.artoffset or 0) + -- + canvas.paperheight = paperheight + canvas.paperwidth = paperwidth + canvas.cropoffset = cropoffset + canvas.trimoffset = trimoffset + canvas.bleedoffset = bleedoffset + canvas.artoffset = artoffset + -- + canvas.pagespec = specification.mode or pagespec + canvas.topoffset = specification.topoffset or 0 + canvas.leftoffset = specification.leftoffset or 0 + canvas.height = specification.height or paperheight + canvas.width = specification.width or paperwidth + canvas.marked = specification.print + -- + local copies = specification.copies + if type(copies) == "number" and copies < 2 then + canvas.copies = false + end + -- + local doublesided = specification.doublesided + if doublesided ~= nil then + canvas.doublesided = doublesided + end +end + +function layouts.getpagedimensions() + return canvas.paperwidth, canvas.paperheight +end + +function layouts.getcanvas() + return canvas +end diff --git a/tex/context/base/mkxl/layo-ini.mkxl b/tex/context/base/mkxl/layo-ini.mkxl index 4979989cd..73b7e978e 100644 --- a/tex/context/base/mkxl/layo-ini.mkxl +++ b/tex/context/base/mkxl/layo-ini.mkxl @@ -25,6 +25,6 @@ \ifdefined\pagenoshift \else \newcount \pagenoshift \fi \ifdefined\realpageno \else \newcount \realpageno \fi -\registerctxluafile{layo-ini}{} +\registerctxluafile{layo-ini}{autosuffix} \protect \endinput diff --git a/tex/context/base/mkxl/lpdf-col.lmt b/tex/context/base/mkxl/lpdf-col.lmt index 778d250c6..a999cb2c7 100644 --- a/tex/context/base/mkxl/lpdf-col.lmt +++ b/tex/context/base/mkxl/lpdf-col.lmt @@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['lpdf-col'] = { license = "see context related readme files" } --- slants also page ? - local type, next, tostring, tonumber = type, next, tostring, tonumber local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch local settings_to_array, settings_to_numbers = utilities.parsers.settings_to_array, utilities.parsers.settings_to_numbers @@ -25,7 +23,7 @@ local registrations = backends.pdf.registrations local nodepool = nodes.nuts.pool local register = nodepool.register -local pageliteral = nodepool.pageliteral +local setstate = nodepool.setstate local pdfconstant = lpdf.constant local pdfdictionary = lpdf.dictionary @@ -131,26 +129,26 @@ lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup") -- color injection function nodeinjections.rgbcolor(r,g,b) - return register(pageliteral(f_rgb(r,g,b,r,g,b))) + return register(setstate(f_rgb(r,g,b,r,g,b))) end function nodeinjections.cmykcolor(c,m,y,k) - return register(pageliteral(f_cmyk(c,m,y,k,c,m,y,k))) + return register(setstate(f_cmyk(c,m,y,k,c,m,y,k))) end function nodeinjections.graycolor(s) -- caching 0/1 does not pay off - return register(pageliteral(f_gray(s,s))) + return register(setstate(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(pageliteral(f_spot(n,n,p,p))) + return register(setstate(f_spot(n,n,p,p))) end function nodeinjections.transparency(n) - return register(pageliteral(f_tr_gs(n))) + return register(setstate(f_tr_gs(n))) end -- a bit weird but let's keep it here for a while @@ -169,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(pageliteral(f_effect(stretch,rulethickness,effect))) -- watch order + return register(setstate(f_effect(stretch,rulethickness,effect))) -- watch order end -- spot- and indexcolors @@ -727,29 +725,20 @@ function lpdf.finishtransparencycode() end end --- this will move to lpdf-spe.lua an dwe then can also add a metatable with --- normal context colors - do - local pdfcolor = lpdf.color - local pdftransparency = lpdf.transparency - - local f_slant = formatters["q 1 0 %N 1 0 0 cm"] + local pdfprint, pdfcolor, pdftransparency - local slants = setmetatableindex(function(t,k) - local v = { "pdf", "origin", f_slant(a) } - t[k] = v - return k + updaters.register("backend.update.lpdf",function() + pdfprint = lpdf.print + pdfcolor = lpdf.color + pdftransparency = lpdf.transparency end) - local function startslant(a) - return slants[a] - end - local c_cache = setmetatableindex(function(t,m) + -- We inherit the outer transparency. local v = setmetatableindex(function(t,c) - local p = { "pdf", "page", "q " .. pdfcolor(m,c) } + local p = "q " .. pdfcolor(m,c) t[c] = p return p end) @@ -757,13 +746,11 @@ do return v end) - -- we inherit the outer transparency - local t_cache = setmetatableindex(function(t,transparency) local p = pdftransparency(transparency) local v = setmetatableindex(function(t,colormodel) local v = setmetatableindex(function(t,color) - local v = { "pdf", "page", "q " .. pdfcolor(colormodel,color) .. " " .. p } + local v = "q " .. pdfcolor(colormodel,color) .. " " .. p t[color] = v return v end) @@ -774,120 +761,33 @@ do return v end) - local function startcolor(k) - local m, c = colortoattributes(k) - local t = transparencytoattribute(k) - if t and t ~= unsetvalue then - return t_cache[t][m][c] - else - return c_cache[m][c] - end - end - - -- A problem is that we need to transfer back and this is kind of - -- messy so we force text mode .. i'll do a better job on that but - -- will experiment first (both engines). Virtual fonts will change - -- anyway. - - local vfspecials = backends.pdf.tables.vfspecials or allocate { } - backends.pdf.tables.vfspecials = vfspecials - - vfspecials.startcolor = startcolor - -- vfspecials.stopcolor = { "pdf", "text", "Q" } -- fails - vfspecials.stopcolor = { "pdf", "page", "Q" } - - vfspecials.startslant = startslant - vfspecials.stopslant = { "pdf", "page", "Q" } -- fails - -end - --- new method: - -do - updaters.register("backend.update.lpdf",function() - pdfprint = lpdf.print - end) - - -- Is this still used? It's a font property now. - - local f_slant = formatters["q 1 0 %N 1 0 0 cm"] - - local slants = setmetatableindex(function(t,k) - local v = f_slant(a) - t[k] = v - return k - end) - local function startslant(a) - return pdfprint("origin", slants[a]) - end + local vfinjectors = fonts.helpers.vfinjectors - local function stopslant() - pdfprint("text", "Q") - end + vfinjectors.pdf = function(pos_h,pos_v,packet) + pdfprint(packet[2],packet[3]) + end - -- We inherit the outer transparency. - - local pdfcolor = lpdf.color - local pdftransparency = lpdf.transparency - - -- local c_cache = setmetatableindex(function(t,m) - -- local v = setmetatableindex(function(t,c) - -- local p = "q " .. pdfcolor(m,c) - -- t[c] = p - -- return p - -- end) - -- t[m] = v - -- return v - -- end) - -- - -- local t_cache = setmetatableindex(function(t,transparency) - -- local p = pdftransparency(transparency) - -- local v = setmetatableindex(function(t,colormodel) - -- local v = setmetatableindex(function(t,color) - -- local v = "q " .. pdfcolor(colormodel,color) .. " " .. p - -- t[color] = v - -- return v - -- end) - -- t[colormodel] = v - -- return v - -- end) - -- t[transparency] = v - -- return v - -- end) - - -- local function startcolor(color) - -- local m, c = colortoattributes(color) - -- local t = transparencytoattribute(color) - -- if t then - -- pdfprint("page", t_cache[t][m][c]) - -- else - -- pdfprint("page", c_cache[m][c]) - -- end - -- end - - local function startcolor(color) - local m, c = colortoattributes(color) - local t = transparencytoattribute(color) - if t and t ~= unsetvalue then - pdfprint("page", "q " .. pdfcolor(m,c) .. " " .. pdftransparency(t)) - else - pdfprint("page", "q " .. pdfcolor(m,c)) + vfinjectors.startcolor = function(pos_h,pos_v,packet) + local color = type(packet) == "table" and packet[2] or packet + if color then + local m, c = colortoattributes(color) + local t = transparencytoattribute(color) + if t and t ~= unsetvalue then + pdfprint("page", t_cache[t][m][c]) -- "q " .. pdfcolor(m,c) .. " " .. pdftransparency(t) + else + pdfprint("page", c_cache[m][c]) -- "q " .. pdfcolor(m,c)) + end + else + pdfprint("page", "q") + end end - end - local function stopcolor() - pdfprint("text", "Q") - end + vfinjectors.stopcolor = function() + pdfprint("text", "Q") + end - updaters.register("backend.update.lpdf",function() - fonts.vfcommands = { - startslant = startslant, - stopslant = stopslant, - startcolor = startcolor, - stopcolor = stopcolor, - } end) end diff --git a/tex/context/base/mkxl/lpdf-ini.lmt b/tex/context/base/mkxl/lpdf-ini.lmt index 59e728dfb..ea9466d39 100644 --- a/tex/context/base/mkxl/lpdf-ini.lmt +++ b/tex/context/base/mkxl/lpdf-ini.lmt @@ -82,12 +82,11 @@ do lpdf.getpos = drivers.getpos end) - local pdfgetmatrix, pdfhasmatrix, pdfprint, pdfgetpos + local pdfgetmatrix, pdfhasmatrix, pdfgetpos updaters.register("backend.update.lpdf",function() pdfgetmatrix = lpdf.getmatrix pdfhasmatrix = lpdf.hasmatrix - pdfprint = lpdf.print pdfgetpos = lpdf.getpos end) @@ -541,21 +540,6 @@ end local function add_x(t,k,v) rawset(t,k,tostring(v)) end --- 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 } @@ -1259,6 +1243,17 @@ do end } + local setstate = nodes.nuts.pool.setstate + + function nodeinjections.startalternate(str) + return setstate(f_actual_text(tosixteen(str))) + end + + function nodeinjections.stopalternate() + return setstate("EMC") + end + + end -- interface diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt index 44352994a..b57557aee 100644 --- a/tex/context/base/mkxl/lpdf-lmt.lmt +++ b/tex/context/base/mkxl/lpdf-lmt.lmt @@ -100,6 +100,10 @@ local report_objects = logs.reporter("backend","objects") local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end) local trace_details = false trackers.register("backend.details", function(v) trace_details = v end) +-- we collect them: + +local flushers = { } + -- used variables local pdf_h, pdf_v @@ -185,7 +189,7 @@ local tjfactor = 100 / 65536 lpdf.usedcharacters = usedcharacters -local function updatefontstate(font) +function flushers.updatefontstate(font) fontcharacters = characters[font] fontdescriptions = descriptions[font] fontparameters = parameters[font] @@ -400,8 +404,7 @@ local function pdf_goto_fontmode() end -- characters - -local flushcharacter do +do local round = math.round @@ -413,52 +416,23 @@ local flushcharacter do local hshift = false local vshift = false - -- local naturalwidths = setmetatableindex(function(t,font) - -- local d = descriptions[font] - -- local c = characters[font] - -- local f = parameters[font].hfactor - -- local v = setmetatableindex(function(t,char) - -- local w - -- local e = d and d[char] - -- if e then - -- w = e.width - -- if w then - -- w = w * f - -- end - -- end - -- if not w then - -- e = c[char] - -- if e then - -- w = e.width or 0 - -- end - -- end - -- if not w then - -- w = 0 - -- end - -- t[char] = w - -- return w - -- end) - -- t[font] = v - -- return v - -- end) - local naturalwidths = setmetatableindex(function(t,font) local d = descriptions[font] local c = characters[font] - local f = parameters[font].hfactor + local f = parameters[font].hfactor or parameters[font].factor local v = setmetatableindex(function(t,char) local w - local e = c[char] + local e = d and d[char] if e then - w = e.width or 0 + w = e.width + if w then + w = w * f + end end if not w then - e = d and d[char] + e = c[char] if e then - w = e.width - if w then - w = w * f - end + w = e.width or 0 end end if not w then @@ -592,7 +566,7 @@ local flushcharacter do -- luatex (a precursor to lmtx and also for comparison) but only in lmtx now so ... -- time to move on I guess. - flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + flushers.character = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) if sx ~= f_x_scale or sy ~= f_y_scale or need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then pdf_goto_textmode() setup_fontparameters(font,factor,f,e,sx,sy) @@ -665,7 +639,7 @@ local flushcharacter do end - flushfontchar = function(font,char,data) + flushers.fontchar = function(font,char,data) local dummy = usedfonts[font] local index = data.index or char if not pdfcharacters[index] then @@ -690,14 +664,12 @@ local flushliteral do local textliteral_code = literalvalues.text local fontliteral_code = literalvalues.font - local getdata = nuts.getdata - - flushliteral = function(current,pos_h,pos_v,mode,str) - if mode then - if not str then - mode, str = originliteral_code, mode - elseif mode == "mode" then - mode = literalvalues[str] + flushliteral = function(current,pos_h,pos_v) + local p = nodeproperties[current] + if p then + local str = p.data + if str and str ~= "" then + local mode = p.mode if mode == originliteral_code then pdf_goto_pagemode() pdf_set_pos(pos_h,pos_v) @@ -707,49 +679,22 @@ local flushliteral do pdf_goto_textmode() elseif mode == fontliteral_code then pdf_goto_fontmode() - elseif mode == alwaysliteral_code then + elseif mode == alwaysliteral_code then -- aka direct pdf_end_string_nl() need_tm = true elseif mode == rawliteral_code then pdf_end_string_nl() + else + report("invalid literal mode %a when flushing %a",mode,str) + return end - return - else - mode = literalvalues[mode] - end - else - local p = nodeproperties[current] - if p then - str = p.data - mode = p.mode - else - str, mode = getdata(current) - end - end - if str and str ~= "" then - if mode == originliteral_code then - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) - elseif mode == pageliteral_code then - pdf_goto_pagemode() - elseif mode == textliteral_code then - pdf_goto_textmode() - elseif mode == fontliteral_code then - pdf_goto_fontmode() - elseif mode == alwaysliteral_code then - pdf_end_string_nl() - need_tm = true - elseif mode == rawliteral_code then - pdf_end_string_nl() - else - report("check literal") - pdf_goto_pagemode() - pdf_set_pos(pos_h,pos_v) + b = b + 1 ; buffer[b] = str end - b = b + 1 ; buffer[b] = str end end + flushers.literal = flushliteral + function lpdf.print(mode,str) -- This only works inside objects, don't change this to flush -- in between. It's different from luatex but okay. @@ -774,8 +719,8 @@ local flushliteral do elseif mode == rawliteral_code then pdf_end_string_nl() else - pdf_goto_pagemode() - -- pdf_set_pos(pdf_h,pdf_v) + report("invalid literal mode %a when flushing %a",mode,str) + return end b = b + 1 ; buffer[b] = str end @@ -785,14 +730,14 @@ end -- grouping & orientation -local flushsave, flushrestore, flushsetmatrix do +do local matrices = { } local positions = { } local nofpositions = 0 local nofmatrices = 0 - flushsave = function(current,pos_h,pos_v) + local flushsave = function(current,pos_h,pos_v) nofpositions = nofpositions + 1 positions[nofpositions] = { pos_h, pos_v, nofmatrices } pdf_goto_pagemode() @@ -800,7 +745,7 @@ local flushsave, flushrestore, flushsetmatrix do b = b + 1 ; buffer[b] = "q" end - flushrestore = function(current,pos_h,pos_v) + local flushrestore = function(current,pos_h,pos_v) if nofpositions < 1 then return end @@ -822,7 +767,7 @@ local flushsave, flushrestore, flushsetmatrix do local f_matrix_2 = formatters["%.6N 0 0 %.6N 0 0 cm"] local f_matrix_4 = formatters["%.6N %.6N %.6N %.6N 0 0 cm"] - flushsetmatrix = function(current,pos_h,pos_v) + local flushsetmatrix = function(current,pos_h,pos_v) local p = nodeproperties[current] if p then local m = p.matrix @@ -879,6 +824,10 @@ local flushsave, flushrestore, flushsetmatrix do end end + flushers.setmatrix = flushsetmatrix + flushers.save = flushsave + flushers.restore = flushrestore + function lpdf.hasmatrix() return nofmatrices > 0 end @@ -891,7 +840,7 @@ local flushsave, flushrestore, flushsetmatrix do end end - pushorientation = function(orientation,pos_h,pos_v,pos_r) + flushers.pushorientation = function(orientation,pos_h,pos_v,pos_r) pdf_goto_pagemode() pdf_set_pos(pos_h,pos_v) b = b + 1 ; buffer[b] = "q" @@ -904,12 +853,76 @@ local flushsave, flushrestore, flushsetmatrix do end end - poporientation = function(orientation,pos_h,pos_v,pos_r) + flushers.poporientation = function(orientation,pos_h,pos_v,pos_r) pdf_goto_pagemode() pdf_set_pos(pos_h,pos_v) b = b + 1 ; buffer[b] = "Q" end + -- + + flushers.startmatrix = function(current,pos_h,pos_v) + flushsave(current,pos_h,pos_v) + flushsetmatrix(current,pos_h,pos_v) + end + + flushers.stopmatrix = function(current,pos_h,pos_v) + flushrestore(current,pos_h,pos_v) + end + + flushers.startscaling = function(current,pos_h,pos_v) + flushsave(current,pos_h,pos_v) + flushsetmatrix(current,pos_h,pos_v) + end + + flushers.stopscaling = function(current,pos_h,pos_v) + flushrestore(current,pos_h,pos_v) + end + + flushers.startrotation = function(current,pos_h,pos_v) + flushsave(current,pos_h,pos_v) + flushsetmatrix(current,pos_h,pos_v) + end + + flushers.stoprotation = function(current,pos_h,pos_v) + flushrestore(current,pos_h,pos_v) + end + + flushers.startmirroring = function(current,pos_h,pos_v) + flushsave(current,pos_h,pos_v) + flushsetmatrix(current,pos_h,pos_v) + end + + flushers.stopmirroring = function(current,pos_h,pos_v) + flushrestore(current,pos_h,pos_v) + end + + flushers.startclipping = function(current,pos_h,pos_v) + flushsave(current,pos_h,pos_v) + flushliteral("origin",formatters["0 w %s W n"](properties[current].path)) + end + + flushers.stopclipping = function(current,pos_h,pos_v) + flushrestore(current,pos_h,pos_v) + end + +end + +do + + local nodeproperties = nodes.properties.data + + flushers.setstate = function(current,pos_h,pos_v) + local p = nodeproperties[current] + if p then + local d = p.data + if d and d ~= "" then + pdf_goto_pagemode() + b = b + 1 ; buffer[b] = d + end + end + end + end -- rules @@ -917,7 +930,7 @@ end local flushedxforms = { } -- actually box resources but can also be direct local localconverter = nil -- will be set -local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do +local flushimage do local rulecodes = nodes.rulecodes local newrule = nodes.pool.rule @@ -1041,7 +1054,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do end end --- updaters.register("backend.update.tex",function() + -- updaters.register("backend.update.tex",function() updaters.register("backend.update.lpdf",function() tex.saveboxresource = saveboxresource tex.useboxresource = useboxresource @@ -1115,7 +1128,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do local groups = 0 local group = nil - flushgroup = function(content,bbox) + local flushgroup = function(content,bbox) if not group then group = pdfdictionary { Type = pdfconstant("Group"), @@ -1136,6 +1149,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do return f_gr(groups) end + flushers.group = flushgroup lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps -- end of experiment @@ -1287,6 +1301,8 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do b = b + 1 ; buffer[b] = s_e end + flushers.image = flushimage + -- For the moment we need this hack because the engine checks the 'image' -- command in virtual fonts (so we use lua instead). -- @@ -1294,7 +1310,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do -- never because the next are like the other engines and compensate for -- small sizes which is needed for inaccurate viewers. - flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) + flushers.rule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype) if subtype == emptyrule_code then return @@ -1350,7 +1366,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do end - flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v) + flushers.simplerule = function(pos_h,pos_v,pos_r,size_h,size_v) pdf_goto_pagemode() b = b + 1 ; buffer[b] = s_b @@ -1374,7 +1390,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do b = b + 1 ; buffer[b] = s_e end - flushspecialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline) + flushers.specialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline) pdf_goto_pagemode() b = b + 1 ; buffer[b] = s_b @@ -2953,24 +2969,7 @@ do drivers.install { name = "pdf", - flushers = { - character = flushcharacter, - fontchar = flushfontchar, - rule = flushrule, - simplerule = flushsimplerule, - specialrule = flushspecialrule, - pushorientation = pushorientation, - poporientation = poporientation, - -- - literal = flushliteral, - setmatrix = flushsetmatrix, - save = flushsave, - restore = flushrestore, - image = flushimage, - group = flushgroup, - -- - updatefontstate = updatefontstate, - }, + flushers = flushers, actions = { prepare = prepare, wrapup = wrapup, diff --git a/tex/context/base/mkxl/lpdf-mis.lmt b/tex/context/base/mkxl/lpdf-mis.lmt index 46accf9a4..afb149d8a 100644 --- a/tex/context/base/mkxl/lpdf-mis.lmt +++ b/tex/context/base/mkxl/lpdf-mis.lmt @@ -26,11 +26,14 @@ local nodeinjections = backends.pdf.nodeinjections local codeinjections = backends.pdf.codeinjections local registrations = backends.pdf.registrations +local getpagedimensions = layouts.getpagedimensions +local getcanvas = layouts.getcanvas + local nuts = nodes.nuts local copy_node = nuts.copy local nodepool = nuts.pool -local pageliteral = nodepool.pageliteral +local setstate = nodepool.setstate local register = nodepool.register local pdfdictionary = lpdf.dictionary @@ -86,10 +89,10 @@ local v_righttoleft = variables.righttoleft local v_title = variables.title local v_nomenubar = variables.nomenubar -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 positive = register(setstate("/GSpositive gs")) +local negative = register(setstate("/GSnegative gs")) +local overprint = register(setstate("/GSoverprint gs")) +local knockout = register(setstate("/GSknockout gs")) local omitextraboxes = false @@ -410,46 +413,12 @@ local pagespecs = { }, } -local pagespec, topoffset, leftoffset, height, width, doublesided = "default", 0, 0, 0, 0, false -local cropoffset, bleedoffset, trimoffset, artoffset = 0, 0, 0, 0 -local marked = false -local copies = false +local function documentspecification() + local canvas = getcanvas() -local getpagedimensions getpagedimensions = function() - getpagedimensions = backends.codeinjections.getpagedimensions - return getpagedimensions() -end + -- move this to layo-ini ? -function codeinjections.setupcanvas(specification) - local paperheight = specification.paperheight - local paperwidth = specification.paperwidth - local paperdouble = specification.doublesided - -- - 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 paperheight - width = specification.width or paperwidth - marked = specification.print - -- - copies = specification.copies - if copies and copies < 2 then - copies = false - end - -- - cropoffset = specification.cropoffset or 0 - trimoffset = cropoffset - (specification.trimoffset or 0) - bleedoffset = trimoffset - (specification.bleedoffset or 0) - artoffset = bleedoffset - (specification.artoffset or 0) - -- - if paperdouble ~= nil then - doublesided = paperdouble - end -end - -local function documentspecification() + local pagespec = canvas.pagespec if not pagespec or pagespec == "" then pagespec = v_default end @@ -460,7 +429,7 @@ local function documentspecification() local spec = defaults or pagespecs[v_default] -- successive keys can modify this if spec.layout == "auto" then - if doublesided then + if canvas.doublesided then local s = pagespecs[v_doublesided] -- to be checked voor interfaces for k, v in next, s do spec[k] = v @@ -478,6 +447,7 @@ local function documentspecification() end end end + -- maybe interfaces.variables local layout = spec.layout local mode = spec.mode @@ -495,6 +465,8 @@ local function documentspecification() addtocatalog("PageMode",pdfconstant(mode)) end local prints = nil + local marked = canvas.marked + local copies = canvas.copies if marked then local pages = structures.pages local marked = pages.allmarked(marked) @@ -534,10 +506,15 @@ local function boxvalue(n) -- we could share them end local function pagespecification() - local paperwidth, paperheight = codeinjections.getpagedimensions() + local canvas = getcanvas() + local paperwidth = canvas.paperwidth + local paperheight = canvas.paperheight + local leftoffset = canvas.leftoffset + local topoffset = canvas.topoffset + -- local llx = leftoffset - local lly = paperheight + topoffset - height - local urx = width - leftoffset + local urx = canvas.width - leftoffset + local lly = paperheight + topoffset - canvas.height local ury = paperheight - topoffset -- boxes can be cached local function extrabox(WhatBox,offset,always) @@ -553,10 +530,10 @@ local function pagespecification() 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 + extrabox("CropBox",canvas.cropoffset,true) -- mandate for rendering + extrabox("TrimBox",canvas.trimoffset,true) -- mandate for pdf/x + extrabox("BleedBox",canvas.bleedoffset) -- optional + -- extrabox("ArtBox",canvas.artoffset) -- optional .. unclear what this is meant to do end end diff --git a/tex/context/base/mkxl/lpdf-ren.lmt b/tex/context/base/mkxl/lpdf-ren.lmt index 8aa61e1dc..3794250d9 100644 --- a/tex/context/base/mkxl/lpdf-ren.lmt +++ b/tex/context/base/mkxl/lpdf-ren.lmt @@ -60,7 +60,7 @@ local copy_node = nuts.copy local nodepool = nuts.pool local register = nodepool.register -local pageliteral = nodepool.pageliteral +local setstate = nodepool.setstate local pdf_ocg = pdfconstant("OCG") local pdf_ocmd = pdfconstant("OCMD") @@ -267,7 +267,7 @@ function nodeinjections.startlayer(name) local c = cache[name] if not c then useviewerlayer(name) - c = register(pageliteral(f_bdc(escapednames[name]))) + c = register(setstate(f_bdc(escapednames[name]))) cache[name] = c end return copy_node(c) @@ -275,7 +275,7 @@ end function nodeinjections.stoplayer() if not stop then - stop = register(pageliteral(s_emc)) + stop = register(setstate(s_emc)) end return copy_node(stop) end @@ -292,7 +292,7 @@ function nodeinjections.startstackedlayer(s,t,first,last) r[#r+1] = startlayer(values[t[i]]) end r = concat(r," ") - return pageliteral(r) + return setstate(r) end function nodeinjections.stopstackedlayer(s,t,first,last) @@ -301,7 +301,7 @@ function nodeinjections.stopstackedlayer(s,t,first,last) r[#r+1] = stoplayer() end r = concat(r," ") - return pageliteral(r) + return setstate(r) end function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2) @@ -313,7 +313,7 @@ function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2) r[#r+1] = startlayer(values[t2[i]]) end r = concat(r," ") - return pageliteral(r) + return setstate(r) end -- transitions diff --git a/tex/context/base/mkxl/lpdf-rul.lmt b/tex/context/base/mkxl/lpdf-rul.lmt index ae2142a8e..efcc62073 100644 --- a/tex/context/base/mkxl/lpdf-rul.lmt +++ b/tex/context/base/mkxl/lpdf-rul.lmt @@ -33,13 +33,9 @@ local formatters = string.formatters -- This is very pdf specific. Maybe move some to lpdf-rul.lua some day. -local pdfprint +local pdfprint ; pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end -pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end - --- updaters.register("backend.update",function() --- pdfprint = lpdf.print --- end) +-- updaters.register("backend.update",function() pdfprint = lpdf.print end) do diff --git a/tex/context/base/mkxl/lpdf-tag.lmt b/tex/context/base/mkxl/lpdf-tag.lmt index 4ea92d951..44a84ea59 100644 --- a/tex/context/base/mkxl/lpdf-tag.lmt +++ b/tex/context/base/mkxl/lpdf-tag.lmt @@ -63,7 +63,7 @@ local a_image = attributes.private('image') local nuts = nodes.nuts local nodepool = nuts.pool -local pageliteral = nodepool.pageliteral +local setstate = nodepool.setstate local register = nodepool.register local getid = nuts.getid @@ -369,7 +369,7 @@ local visualize = nil function nodeinjections.addtags(head) if not EMCliteral then - EMCliteral = register(pageliteral("EMC")) + EMCliteral = register(setstate("EMC")) end local last = nil @@ -516,9 +516,9 @@ end end end if prev then - literal = pageliteral(makecontent(prev,id,specification)) + literal = setstate(makecontent(prev,id,specification)) elseif ignore then - literal = pageliteral(makeignore(specification)) + literal = setstate(makeignore(specification)) else -- maybe also ignore or maybe better: comment or so end @@ -543,7 +543,7 @@ end else - local literal = pageliteral(makeignore(specification)) + local literal = setstate(makeignore(specification)) inject(start,stop,list,literal) @@ -667,9 +667,9 @@ end -- end -- -- if r > 0 then --- local literal = pageliteral(concat(result,"\n")) +-- local literal = setstate(concat(result,"\n")) -- -- use insert instead: --- local literal = pageliteral(result) +-- local literal = setstate(result) -- local prev = getprev(start) -- if prev then -- setlink(prev,literal) @@ -691,7 +691,7 @@ end -- for i=1,noftop do -- result[i] = "EMC" -- end --- local literal = pageliteral(concat(result,"\n")) +-- local literal = setstate(concat(result,"\n")) -- -- use insert instead: -- local next = getnext(last) -- if next then diff --git a/tex/context/base/mkxl/lpdf-vfc.lmt b/tex/context/base/mkxl/lpdf-vfc.lmt deleted file mode 100644 index 6030bb028..000000000 --- a/tex/context/base/mkxl/lpdf-vfc.lmt +++ /dev/null @@ -1,42 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-vfc'] = { - 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 setmetatableindex = table.setmetatableindex - -local defaultline = 16384 - -local vfspecials = backends.pdf.tables.vfspecials or utilities.storage.allocate { } -backends.pdf.tables.vfspecials = vfspecials - -vfspecials.backgrounds = setmetatableindex(function(t,h) - local v = setmetatableindex(function(t,d) - local v = setmetatableindex(function(t,w) - local v = { "frame", w, h, d, defaultline, true, true } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) - -vfspecials.outlines = setmetatableindex(function(t,h) - local v = setmetatableindex(function(t,d) - local v = setmetatableindex(function(t,w) - local v = { "frame", w, h, d, defaultline, false, true } - t[w] = v - return v - end) - t[d] = v - return v - end) - t[h] = v - return v -end) diff --git a/tex/context/base/mkxl/math-act.lmt b/tex/context/base/mkxl/math-act.lmt new file mode 100644 index 000000000..3076f2ac9 --- /dev/null +++ b/tex/context/base/mkxl/math-act.lmt @@ -0,0 +1,480 @@ +if not modules then modules = { } end modules ['math-act'] = { + version = 1.001, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Here we tweak some font properties (if needed). The commented sections +-- have been removed (no longer viable) but can be found in the .lua variant. + +local type, next = type, next +local fastcopy, insert, remove = table.fastcopy, table.insert, table.remove +local formatters = string.formatters + +local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) +local trace_collecting = false trackers.register("math.collecting", function(v) trace_collecting = v end) + +local report_math = logs.reporter("mathematics","initializing") + +local context = context +local commands = commands +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 + +local fontchars = fonts.hashes.characters +local fontproperties = fonts.hashes.properties + +local mathfontparameteractions = sequencers.new { + name = "mathparameters", + arguments = "target,original", +} + +appendgroup("mathparameters","before") -- user +appendgroup("mathparameters","system") -- private +appendgroup("mathparameters","after" ) -- user + +function fonts.constructors.assignmathparameters(original,target) + local runner = mathfontparameteractions.runner + if runner then + runner(original,target) + end +end + +function mathematics.initializeparameters(target,original) + local mathparameters = original.mathparameters + if mathparameters and next(mathparameters) then + mathparameters = mathematics.dimensions(mathparameters) + if not mathparameters.SpaceBeforeScript then + mathparameters.SpaceBeforeScript = mathparameters.SpaceAfterScript + end + target.mathparameters = mathparameters + end +end + +sequencers.appendaction("mathparameters","system","mathematics.initializeparameters") + +local how = { + -- RadicalKernBeforeDegree = "horizontal", + -- RadicalKernAfterDegree = "horizontal", + ScriptPercentScaleDown = "unscaled", + ScriptScriptPercentScaleDown = "unscaled", + RadicalDegreeBottomRaisePercent = "unscaled", + NoLimitSupFactor = "unscaled", + NoLimitSubFactor = "unscaled", +} + +function mathematics.scaleparameters(target,original) + if not target.properties.math_is_scaled then + local mathparameters = target.mathparameters + if mathparameters and next(mathparameters) then + local parameters = target.parameters + local factor = parameters.factor + local hfactor = parameters.hfactor + local vfactor = parameters.vfactor + for name, value in next, mathparameters do + local h = how[name] + if h == "unscaled" then + -- kept + elseif h == "horizontal" then + value = value * hfactor + elseif h == "vertical"then + value = value * vfactor + else + value = value * factor + end + mathparameters[name] = value + end + end + target.properties.math_is_scaled = true + end +end + +-- AccentBaseHeight vs FlattenedAccentBaseHeight + +function mathematics.checkaccentbaseheight(target,original) + local mathparameters = target.mathparameters + if mathparameters and mathparameters.AccentBaseHeight == 0 then + mathparameters.AccentBaseHeight = target.parameters.x_height -- needs checking + end +end + +function mathematics.checkprivateparameters(target,original) + local mathparameters = target.mathparameters + if mathparameters then + local parameters = target.parameters + local properties = target.properties + if parameters then + local size = parameters.size + if size then + if not mathparameters.FractionDelimiterSize then + mathparameters.FractionDelimiterSize = 1.01 * size + end + if not mathparameters.FractionDelimiterDisplayStyleSize then + mathparameters.FractionDelimiterDisplayStyleSize = 2.40 * size + end + elseif properties then + report_math("invalid parameters in font %a",properties.fullname or "?") + else + report_math("invalid parameters in font") + end + elseif properties then + report_math("no parameters in font %a",properties.fullname or "?") + else + report_math("no parameters and properties in font") + end + end +end + +function mathematics.overloadparameters(target,original) + local mathparameters = target.mathparameters + if mathparameters and next(mathparameters) then + local goodies = target.goodies + if goodies then + for i=1,#goodies do + local goodie = goodies[i] + local mathematics = goodie.mathematics + local parameters = mathematics and mathematics.parameters + if parameters then + if trace_defining then + report_math("overloading math parameters in %a @ %p",target.properties.fullname,target.parameters.size) + end + for name, value in next, parameters do + local tvalue = type(value) + if tvalue == "string" then + report_math("comment for math parameter %a: %s",name,value) + else + local oldvalue = mathparameters[name] + local newvalue = oldvalue + if oldvalue then + if tvalue == "number" then + newvalue = value + elseif tvalue == "function" then + newvalue = value(oldvalue,target,original) + elseif not tvalue then + newvalue = nil + end + if trace_defining and oldvalue ~= newvalue then + report_math("overloading math parameter %a: %S => %S",name,oldvalue,newvalue) + end + else + report_math("invalid math parameter %a",name) + end + mathparameters[name] = newvalue + end + end + end + end + end + end +end + +local function applytweaks(when,target,original) + local goodies = original.goodies + if goodies then + for i=1,#goodies do + local goodie = goodies[i] + local mathematics = goodie.mathematics + local tweaks = mathematics and mathematics.tweaks + if type(tweaks) == "table" then + tweaks = tweaks[when] + if type(tweaks) == "table" then + if trace_defining then + report_math("tweaking math of %a @ %p (%s)",target.properties.fullname,target.parameters.size,when) + end + for i=1,#tweaks do + local tweak= tweaks[i] + local tvalue = type(tweak) + if tvalue == "function" then + tweak(target,original) + end + end + end + end + end + end +end + +function mathematics.tweakbeforecopyingfont(target,original) + local mathparameters = target.mathparameters -- why not hasmath + if mathparameters then + applytweaks("beforecopying",target,original) + end +end + +function mathematics.tweakaftercopyingfont(target,original) + local mathparameters = target.mathparameters -- why not hasmath + if mathparameters then + applytweaks("aftercopying",target,original) + end +end + +sequencers.appendaction("mathparameters","system","mathematics.scaleparameters") +sequencers.appendaction("mathparameters","system","mathematics.checkaccentbaseheight") -- should go in lfg instead +sequencers.appendaction("mathparameters","system","mathematics.checkprivateparameters") -- after scaling ! +sequencers.appendaction("mathparameters","system","mathematics.overloadparameters") + +sequencers.appendaction("beforecopyingcharacters","system","mathematics.tweakbeforecopyingfont") +sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaftercopyingfont") + +local virtualized = mathematics.virtualized + +-- no, it's a feature now (see good-mth): +-- +-- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions") + +-- a couple of predefined tweaks: + +local tweaks = { } +mathematics.tweaks = tweaks + +-- helpers + +local setmetatableindex = table.setmetatableindex + +local getfontoffamily = tex.getfontoffamily + +local fontcharacters = fonts.hashes.characters +local extensibles = utilities.storage.allocate() +fonts.hashes.extensibles = extensibles + +local chardata = characters.data +local extensibles = mathematics.extensibles + +-- we use numbers at the tex end (otherwise we could stick to chars) + +local e_left = extensibles.left +local e_right = extensibles.right +local e_horizontal = extensibles.horizontal +local e_mixed = extensibles.mixed +local e_unknown = extensibles.unknown + +local unknown = { e_unknown, false, false } + +local function extensiblecode(font,unicode) + local characters = fontcharacters[font] + local character = characters[unicode] + if not character then + return unknown + end + local first = character.next + local code = unicode + local next = first + while next do + code = next + character = characters[next] + next = character.next + end + local char = chardata[unicode] + if not char then + return unknown + end + if character.horiz_variants then + if character.vert_variants then + return { e_mixed, code, character } + else + local m = char.mathextensible + local e = m and extensibles[m] + return e and { e, code, character } or unknown + end + elseif character.vert_variants then + local m = char.mathextensible + local e = m and extensibles[m] + return e and { e, code, character } or unknown + elseif first then + -- assume accent (they seldom stretch .. sizes) + local m = char.mathextensible or char.mathstretch + local e = m and extensibles[m] + return e and { e, code, character } or unknown + else + return unknown + end +end + +setmetatableindex(extensibles,function(extensibles,font) + local codes = { } + setmetatableindex(codes, function(codes,unicode) + local status = extensiblecode(font,unicode) + codes[unicode] = status + return status + end) + extensibles[font] = codes + return codes +end) + +local function extensiblecode(family,unicode) + return extensibles[getfontoffamily(family or 0)][unicode][1] +end + +-- left : [head] ... +-- right : ... [head] +-- horizontal : [head] ... [head] +-- +-- abs(right["start"] - right["end"]) | right.advance | characters[right.glyph].width + +local function horizontalcode(family,unicode) + local font = getfontoffamily(family or 0) + local data = extensibles[font][unicode] + local kind = data[1] + local loffset = 0 + local roffset = 0 + if kind == e_left then + local charlist = data[3].horiz_variants + if charlist then + local left = charlist[1] + loffset = abs((left["start"] or 0) - (left["end"] or 0)) + end + elseif kind == e_right then + local charlist = data[3].horiz_variants + if charlist then + local right = charlist[#charlist] + roffset = abs((right["start"] or 0) - (right["end"] or 0)) + end + elseif kind == e_horizontal then + local charlist = data[3].horiz_variants + if charlist then + local left = charlist[1] + local right = charlist[#charlist] + loffset = abs((left ["start"] or 0) - (left ["end"] or 0)) + roffset = abs((right["start"] or 0) - (right["end"] or 0)) + end + end + return kind, loffset, roffset +end + +mathematics.extensiblecode = extensiblecode +mathematics.horizontalcode = horizontalcode + +interfaces.implement { + name = "extensiblecode", + arguments = { "integer", "integer" }, + actions = { extensiblecode, context } +} + +interfaces.implement { + name = "horizontalcode", + arguments = { "integer", "integer" }, + actions = function(family,unicode) + local kind, loffset, roffset = horizontalcode(family,unicode) + texsetdimen("scratchleftoffset", loffset) + texsetdimen("scratchrightoffset",roffset) + context(kind) + end +} + + +local stack = { } + +function mathematics.registerfallbackid(n,id,name) + if trace_collecting then + report_math("resolved fallback font %i, name %a, id %a, used %a", + n,name,id,fontproperties[id].fontname) + end + stack[#stack][n] = id +end + +interfaces.implement { -- will be shared with text + name = "registerfontfallbackid", + arguments = { "integer", "integer", "string" }, + actions = mathematics.registerfallbackid, +} + +function mathematics.resolvefallbacks(target,specification,fallbacks) + local definitions = fonts.collections.definitions[fallbacks] + if definitions then + local size = specification.size -- target.size + local list = { } + insert(stack,list) + context.pushcatcodes("prt") -- context.unprotect() + for i=1,#definitions do + local definition = definitions[i] + local name = definition.font + local features = definition.features or "" + local size = size * (definition.rscale or 1) + context.font_fallbacks_register_math(i,name,features,size) + if trace_collecting then + report_math("registering fallback font %i, name %a, size %a, features %a",i,name,size,features) + end + end + context.popcatcodes() + end +end + +function mathematics.finishfallbacks(target,specification,fallbacks) + local list = remove(stack) + if list and #list > 0 then + local definitions = fonts.collections.definitions[fallbacks] + if definitions and #definitions > 0 then + if trace_collecting then + report_math("adding fallback characters to font %a",specification.hash) + end + local definedfont = fonts.definers.internal + local copiedglyph = fonts.handlers.vf.math.copy_glyph + local fonts = target.fonts + local size = specification.size -- target.size + local characters = target.characters + if not fonts then + fonts = { } + target.fonts = fonts + end + if #fonts == 0 then + fonts[1] = { id = 0, size = size } -- self, will be resolved later + end + local done = { } + for i=1,#definitions do + local definition = definitions[i] + local name = definition.font + local start = definition.start + local stop = definition.stop + local gaps = definition.gaps + local check = definition.check + local force = definition.force + local rscale = definition.rscale or 1 + local offset = definition.offset or start + local id = list[i] + if id then + local index = #fonts + 1 + fonts[index] = { id = id, size = size } + local chars = fontchars[id] + local function remap(unic,unicode,gap) + if check and not chars[unicode] then + return + end + if force or (not done[unic] and not characters[unic]) then + if trace_collecting then + report_math("replacing math character %C by %C using vector %a and font id %a for %a%s%s", + unic,unicode,fallbacks,id,fontproperties[id].fontname,check and ", checked",gap and ", gap plugged") + end + characters[unic] = copiedglyph(target,characters,chars,unicode,index) + done[unic] = true + end + end + local step = offset - start + for unicode = start, stop do + remap(unicode + step,unicode,false) + end + if gaps then + for unic, unicode in next, gaps do + remap(unic,unicode,true) + remap(unicode,unicode,true) + end + end + end + end + elseif trace_collecting then + report_math("no fallback characters added to font %a",specification.hash) + end + end +end diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl index d90f3ab0f..72f857720 100644 --- a/tex/context/base/mkxl/math-ali.mkxl +++ b/tex/context/base/mkxl/math-ali.mkxl @@ -285,7 +285,7 @@ \math_number_right_of_eqalign \global\settrue\c_math_eqalign_first \crcr - \dostoptagged} % finish row + \noalign{\dostoptagged}} % finish row \permanent\protected\def\math_alignment_NC {\relax diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index 95501be65..01ecd63a2 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -66,7 +66,7 @@ \registerctxluafile{math-ini}{} \registerctxluafile{math-dim}{} -\registerctxluafile{math-act}{} +\registerctxluafile{math-act}{autosuffix} \registerctxluafile{math-ext}{} \registerctxluafile{math-vfu}{autosuffix} \registerctxluafile{math-ttv}{} diff --git a/tex/context/base/mkxl/math-noa.lmt b/tex/context/base/mkxl/math-noa.lmt index c884e6927..92edbc441 100644 --- a/tex/context/base/mkxl/math-noa.lmt +++ b/tex/context/base/mkxl/math-noa.lmt @@ -693,7 +693,8 @@ do end -- We can optimize this if we really think that math is a bottleneck which it never - -- really is. + -- really is. Beware: the font is the text font in the family, so we only check the + -- text font here. relocate[mathchar_code] = function(pointer) local g = getattr(pointer,a_mathgreek) or 0 @@ -757,7 +758,13 @@ do end end if not characters[char] then + local fam = getfam(pointer) + local fnt = getfontoffamily(fam,1) setchar(pointer,errorchar(font,char)) + if font ~= fnt then + errorchar(fnt,char) + errorchar(getfontoffamily(fam,2),char) + end end if trace_analyzing then setnodecolor(pointer,"font:medi") diff --git a/tex/context/base/mkxl/meta-imp-punk.mkxl b/tex/context/base/mkxl/meta-imp-punk.mkxl new file mode 100644 index 000000000..050023642 --- /dev/null +++ b/tex/context/base/mkxl/meta-imp-punk.mkxl @@ -0,0 +1,272 @@ +%D \module +%D [ file=meta-imp-punk, +%D version=2020.01.16, +%D title=\METAPOST\ Graphics, +%D subtitle=Punk, +%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. + +% This file is a merge of the original punk files by Donald Knuth, who +% added this comment: +% +% Font inspired by Gerard and Marjan Unger's lectures, Feb 1985 +% +% The regular punk files are part of TeXLive and in metafont format. All +% errors introduced are ours. We also changed the encoding to unicode. In +% due time we might add a few more more characters. We still need to +% improve some of the metrics which involves a bit of trial and error. The +% font just covers basic latin shapes but in ConTeXt MkIV we add virtual +% composed shapes. There is a module m-punk.tex that implements this. This +% derivate is also used in mk.tex (mk.pdf) which is one of our tests for +% LuaTeX. We published an article on it in the MAPS (NTG magazine). +% +% 2008, mkiv variant: Taco Hoekwater & Hans Hagen +% 2020, lmtx variant: Hans Hagen (playground) + +\startMPcalculation{simplefun} + + picture PunkShapes[][]; + + numeric PunkId ; PunkId := 0 ; + numeric PunkBase ; PunkBase := 0 ; + string PunkName ; PunkName := "punk" ; + numeric PunkUsed ; PunkUsed := 0 ; + numeric PunkSlant ; PunkSlant := 0 ; + numeric PunkWeight ; PunkWeight := 1 ; + numeric PunkSqueeze ; PunkSqueeze := 1 ; + numeric PunkExtend ; PunkExtend := 1 ; + numeric PunkVariants ; PunkVariants := 0 ; + + numeric PunkRatio ; PunkRatio := 2/3 ; + numeric PunkScale ; PunkScale := 20 ; % when zero we use the knuth values + numeric PunkN ; PunkN := 0 ; + + def beginpunkchar(expr c, n, hor, ver) = + begingroup ; + save uc, w, h, d, hdev, vdev ; + hdev := hor * dev ; % modify horizontal amounts of deviation + vdev := ver * dev ; % modify vertical amounts of deviation + uc := if string c : utfnum(c) else : c fi ; + h := if PunkScale > 0 : PunkN else : n fi / PunkSqueeze ; + w := n * PunkExtend ; + d := 0 ; + clearxy ; + clearit ; + enddef ; + + def endpunkchar = + if PunkSlant <> 0 : + currentpicture := currentpicture slanted PunkSlant ; + fi ; + save llx, lly, uly ; + llx := xpart llcorner currentpicture ; + lly := ypart llcorner currentpicture ; + uly := ypart ulcorner currentpicture ; + + currentpicture := currentpicture shifted (- llx + 1, 0); + w := bbwidth(currentpicture) + 2 ; + h := uly ; + d := if lly < 0 : - lly else : 0 fi ; + + PunkUsed := if PunkBase > 0 : PunkBase else : uc fi; + PunkShapes[PunkId][PunkUsed] := currentpicture ; + lmt_registerglyph [ + category = PunkName, + unicode = PunkUsed, + tounicode = uc, + width = w, + height = h, + depth = d, + code = "draw PunkShapes[" & decimal PunkId & "][" & decimal PunkUsed & "]", + ] ; + if PunkBase > 0 : + PunkBase := PunkBase + 1 ; + fi ; + endgroup ; + enddef ; + + def initialize_punk_upper = + PunkN := PunkScale ; + dev := 1 ; + enddef ; + + def initialize_punk_lower = + PunkN := PunkScale * PunkRatio ; + dev := .5 ; + enddef ; + + def revert_punk_lower = + PunkN := PunkScale ; + dev := 1 ; + enddef ; + + def beginpunkfont = + + begingroup ; + + save dev; + + save u ; u := 1 ; + + PunkBase := 0 ; + + pen linepen ; linepen := pencircle scaled (PunkWeight * u) ; + pen dotpen ; dotpen := linepen scaled 2 slanted -PunkSlant ; + + pickup linepen ; + + save pp ; vardef pp expr z = + z + (hdev * normaldeviate, vdev * normaldeviate) + enddef ; + + save pd ; def pd expr z = + drawdot z withpen dotpen ; + enddef ; + + PunkId := PunkId + 1 ; + + lmt_registerglyphs [ + name = PunkName, % todo: when we do name = name we get ['"name"'] = name + units = 25, + width = 25, + height = 25, + depth = 0, + usecolor = true, + ] ; + + def endchar = endpunkchar enddef ; + + enddef ; + + def endpunkfont = + endgroup; + enddef ; + + % We started out with immediate: + + % def MakePunkFont (expr name, filename, slant, weight, squeeze, extend) = + % begingroup ; + % save PunkName, PunkFileName, PunkSlant, PunkWeight, PunkSqueeze, PunkExend, PunkVariants ; + % string PunkName, PunkFileName ; + % PunkFileName := filename ; + % PunkName := name ; + % PunkSlant := slant ; + % PunkWeight := weight ; + % PunkSqueeze := squeeze ; + % PunkExtend := extend ; + % PunkVariants := 0 ; + % beginpunkfont ; + % loadfile(PunkFileName) ; + % endpunkfont ; + % endgroup ; + % enddef ; + % + % MakePunkFont("punk", "punkfont-characters.mp", 1, 0 ) ; + % MakePunkFont("punkbold", "punkfont-characters.mp", 2, 0 ) ; + % MakePunkFont("punkslanted", "punkfont-characters.mp", 1, 0.15) ; + % MakePunkFont("punkboldslanted", "punkfont-characters.mp", 2, 0.15) ; + + % And ended up with delayed: + + def punkpreroll = + begingroup ; + save PunkName, PunkFileName, PunkSlant, PunkWeight, PunkSqueeze, PunkExtend, PunkVariants ; + string PunkName, PunkFileName ; + PunkName := getparameterdefault "mpsfont" "name" "punk" ; + PunkFileName := getparameterdefault "mpsfont" "filename" "punkfont-characters.mp" ; + PunkSlant := scantokens(getparameterdefault "mpsfont" "slant" "0") ; + PunkWeight := scantokens(getparameterdefault "mpsfont" "weight" "1") ; + PunkSqueeze := scantokens(getparameterdefault "mpsfont" "squeeze" "1") ; + PunkExtend := scantokens(getparameterdefault "mpsfont" "extend" "1") ; + PunkVariants := scantokens(getparameterdefault "mpsfont" "variants" "0"); + beginpunkfont ; + loadfile(PunkFileName) ; + if PunkVariants > 0 : + PunkBase := 57344 ; % 0xE000 ; 0xF0000 ; + for i=1 upto PunkVariants : + loadfile(PunkFileName) ; + endfor ; + fi ; + endpunkfont ; + endgroup ; + enddef ; + +\stopMPcalculation + +% Are these names okay? If so it can go into the core. + +\permanent\protected\def\enablerandomvariants{\setcharactercasing[randomvariant]} +\permanent\protected\def\randomvariants {\groupedcommand\enablerandomvariants\donothing} +\permanent\protected\def\startrandomvariants {\begingroup\enablerandomvariants} +\permanent\protected\def\stoprandomvariants {\endgroup} + +\definefontfeature [punk] [metapost={category=punk,preroll=punkpreroll}] +\definefontfeature [punkrandom] [metapost={category=punk,preroll=punkpreroll,variants=10}] +\definefontfeature [punkbold] [metapost={category=punk,preroll=punkpreroll,weight=2}] +\definefontfeature [punkslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15}] +\definefontfeature [punkboldslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15,weight=2}] +\definefontfeature [punkveryslanted] [metapost={category=punk,preroll=punkpreroll,slant=-.15}] +\definefontfeature [punksqueezed] [metapost={category=punk,preroll=punkpreroll,squeeze=.5}] +\definefontfeature [punkextended] [metapost={category=punk,preroll=punkpreroll,extend=1.3}] + +\continueifinputfile{meta-imp-punk.mkxl} + +% immediate: +% +% \definefontfeature [punk] [metapost=punk] +% \definefontfeature [punkbold] [metapost=punkbold] +% \definefontfeature [punkslanted] [metapost=punkslanted] +% \definefontfeature [punkboldslanted] [metapost=punkboldslanted] + +% delayed: + +% name=punk +% filename=punkfont-characters.mp + +\setupbodyfont[dejavu] + +\definefont[PunkA][Serif*punk] +\definefont[PunkB][Serif*punkbold] +\definefont[PunkC][Serif*punkslanted] +\definefont[PunkD][Serif*punkboldslanted] +\definefont[PunkE][Serif*punkveryslanted] +\definefont[PunkF][Serif*punkrandom] +\definefont[PunkG][Serif*punksqueezed] +\definefont[PunkH][Serif*punkextended] + +\starttext + +\startTEXpage[offset=10pt,width=30cm] + % \showglyphs + {\darkcyan \PunkA \samplefile{tufte} \par} + {\darkmagenta \PunkB \samplefile{tufte} \par} + {\darkred \PunkC \samplefile{tufte} \par} + {\darkgreen \PunkD \samplefile{tufte} \par} + {\darkblue \PunkE \samplefile{tufte} \par} + {\darkyellow \PunkF \enablerandomvariants \samplefile{tufte} \par} + {\darkgray \PunkG \samplefile{tufte} \par} + {\darkorange \PunkH \samplefile{tufte} \par} +\stopTEXpage + +\startTEXpage[offset=10pt,width=2cm] + \PunkF \enablerandomvariants + \dostepwiserecurse{1}{2000}{1}{\glyphscale#1\relax f } +\stopTEXpage + +% \setupbodyfont[dejavu] + +\setupbodyfont[punk] %one first needs to load a bodyfont ! + +\startTEXpage[offset=10pt,width=20cm] + {\darkcyan \tf \samplefile{zapf} \par} + {\darkmagenta \bf \samplefile{zapf} \par} + {\darkred \sl \samplefile{zapf} \par} + {\darkgreen \bs \samplefile{zapf} \par} +\stopTEXpage + +\stoptext diff --git a/tex/context/base/mkxl/mlib-mpf.lmt b/tex/context/base/mkxl/mlib-mpf.lmt index 6bd31376c..d66491a16 100644 --- a/tex/context/base/mkxl/mlib-mpf.lmt +++ b/tex/context/base/mkxl/mlib-mpf.lmt @@ -86,12 +86,10 @@ do else runscripts[nofscripts] = name end --- print("set",name,nofscripts,f) return nofscripts end function metapost.scriptindex(name) --- print("get",name,runnames[name] or 0) return runnames[name] or 0 end @@ -945,9 +943,14 @@ do registerscript("setcount", function() setcount(scanstring(),scannumeric()) end) registerscript("settoks", function() settoks (scanstring(),scanstring()) end) + local utfnum = utf.byte local utflen = utf.len local utfsub = utf.sub + registerscript("utfnum", function() + injectnumeric(utfnum(scanstring())) + end) + registerscript("utflen", function() injectnumeric(utflen(scanstring())) end) diff --git a/tex/context/base/mkxl/node-ext.lmt b/tex/context/base/mkxl/node-ext.lmt new file mode 100644 index 000000000..2f909cd3d --- /dev/null +++ b/tex/context/base/mkxl/node-ext.lmt @@ -0,0 +1,650 @@ +if not modules then modules = { } end modules ['back-out'] = { + version = 1.001, + comment = "companion to back-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, unpack, rawset = type, unpack, type +local loadstring = loadstring +local sind, cosd, abs = math.sind, math.cosd, math.abs +local insert, remove = table.insert, table.remove + +local context = context +local implement = interfaces.implement + +local allocate = utilities.storage.allocate + +local formatters = string.formatters + +local get = token.get_index -- getters +local scanners = tokens.scanners +local scaninteger = scanners.integer +local scanstring = scanners.string +local scankeyword = scanners.keyword +local scantokenlist = scanners.tokenlist +local scannumber = scanners.number + +local nuts = nodes.nuts +local tonode = nuts.tonode +local copynut = nuts.copy +local nutpool = nuts.pool +local nodepool = nodes.pool + +local nodeproperties = nodes.properties.data + +local register = nutpool.register +local newnut = nuts.new +local tonode = nodes.tonode + +-- Whatsits are a generic node type with very few fields. We use them to implement +-- whatever we like. Some are good old tex whatsits but many are specific to the +-- macro package. They are part of the backend. + +backends = backends or { } +local backends = backends + +local whatsit_code = nodes.nodecodes.whatsit +local whatsitcodes = allocate { } +nodes.whatsitcodes = whatsitcodes +local lastwhatsit = 0 + +nodes.subtypes.whatsit = whatsitcodes + +local function registerwhatsit(name) + lastwhatsit = lastwhatsit + 1 + whatsitcodes[lastwhatsit] = name + whatsitcodes[name] = lastwhatsit + return lastwhatsit +end + +local function registerwhatsitnode(name) + return register(newnut(whatsit_code,registerwhatsit(name))) +end + +-- We only have a subset of literals. In fact, we try to avoid literals. + +do + + local literalvalues = allocate { } + nodes.literalvalues = literalvalues + local lastliteral = 0 + local literalnode = registerwhatsitnode("literal") + + local function registerliteral(name,alias) + lastliteral = lastliteral + 1 + literalvalues[lastliteral] = name + literalvalues[name] = lastliteral + if alias then + literalvalues[alias] = lastliteral + end + return lastliteral + end + + local originliteral_code = registerliteral("origin") + local pageliteral_code = registerliteral("page") + local directliteral_code = registerliteral("always","direct") + local rawliteral_code = registerliteral("raw") + local textliteral_code = registerliteral("text") -- not to be used + local fontliteral_code = registerliteral("font") -- not to be used + + function nutpool.originliteral(str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end + function nutpool.pageliteral (str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end + function nutpool.directliteral(str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end + function nutpool.rawliteral (str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end + + local pdfliterals = { + [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code, + [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code, + [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code, + [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code, + } + + function nutpool.literal(mode,str) + local t = copynut(literalnode) + if str then + nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code } + else + nodeproperties[t] = { data = mode, mode = pageliteral_code } + end + return t + end + +end + +-- The latelua node is just another whatsit and we handle the \LUA\ code with +-- other \LUA\ code, contrary to \LUATEX\ where it's a native node. + +do + + local getdata = nuts.getdata + local serialize = token.serialize + + local lateluanode = registerwhatsitnode("latelua") + local noflatelua = 0 + + function nutpool.latelua(code) + local n = copynut(lateluanode) + nodeproperties[n] = { data = code } + return n + end + + function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) + local p = nodeproperties[current] + if p then + data = p.data + else + data = getdata(current) + end + noflatelua = noflatelua + 1 + local kind = type(data) + if kind == "table" then + data.action(data.specification or data) + elseif kind == "function" then + data() + else + if kind ~= "string" then + data = serialize(data) + end + if #data ~= "" then + local code = loadstring(data) + if code then + code() + end + end + end + end + + function backends.getcallbackstate() + return { count = noflatelua } + end + + implement { + name = "latelua", + public = true, + protected = true, + actions = function() + local node = copynut(lateluanode) + local name = "latelua" + if scankeyword("name") then + name = scanstring() + end + local data = scantokenlist() + nodeproperties[node] = { name = name, data = data } + return context(tonode(node)) + end, + } + +end + +-- This can be anything. Dealing with these nodes is done via properties, as with +-- the other whatsits. + +do + + local usernode = registerwhatsitnode("userdefined") + + local userids = allocate() + local lastid = 0 + + setmetatable(userids, { + __index = function(t,k) + if type(k) == "string" then + lastid = lastid + 1 + rawset(userids,lastid,k) + rawset(userids,k,lastid) + return lastid + else + rawset(userids,k,k) + return k + end + end, + __call = function(t,k) + return t[k] + end + } ) + + function nutpool.userdefined(id,data) + local n = copynut(usernode) + nodeproperties[n] = { id = id, data = data } + return n + end + + nutpool .usernode = nutpool.userdefined + nutpool .userids = userids + nodepool.userids = userids + +end + +-- This one is only used by generic packages. + +do + + local saveposnode = registerwhatsitnode("savepos") + + function nutpool.savepos() + return copynut(saveposnode) + end + +end + +do + + local savenode = registerwhatsitnode("save") + local restorenode = registerwhatsitnode("restore") + local setmatrixnode = registerwhatsitnode("setmatrix") + + local stack = { } + local restore = true -- false + + -- these are old school nodes + + function nutpool.save() + return copynut(savenode) + end + + function nutpool.restore() + return copynut(restorenode) + end + + function nutpool.setmatrix(rx,sx,sy,ry,tx,ty) + local t = copynut(setmatrixnode) + nodeproperties[t] = { matrix = { rx, sx, sy, ry, tx, ty } } + return t + end + + -- common + + local function stopcommon(n) + local top = remove(stack) + if top == false then + return -- not wrapped + elseif top == true then + return copynut(n) + elseif top then + local t = copynut(n) + nodeproperties[t] = { matrix = { unpack(top) } } + return t + else + return -- nesting error + end + end + + -- matrix + + local startmatrixnode = registerwhatsitnode("startmatrix") + local stopmatrixnode = registerwhatsitnode("stopmatrix") + + local function startmatrix(rx, sx, sy, ry) + if rx == 1 and sx == 0 and sy == 0 and ry == 1 then + insert(stack,false) + else + local t = copynut(startmatrixnode) + nodeproperties[t] = { matrix = { rx, sx, sy, ry } } + insert(stack,store and { -rx, -sx, -sy, -ry } or true) + return t + end + end + + local function stopmatrix() + return stopcommon(stopmatrixnode) + end + + implement { + name = "startmatrix", + actions = function() + 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 + local t = startmatrix(rx,sx,sy,ry) + if t then + context(tonode(t)) + end + end, + } + + implement { + name = "stopmatrix", + actions = function() + local t = stopmatrix(n) + if t then + context(tonode(t)) + end + end, + } + + -- scale + + local startscalingnode = registerwhatsitnode("startscaling") + local stopscalingnode = registerwhatsitnode("stopscaling") + + local function startscaling(rx, ry) -- at the tex end we use sx and sy instead of rx and ry + 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 + local t = copynut(startscalingnode) + nodeproperties[t] = { matrix = { rx, 0, 0, ry } } + insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true) + return t + end + end + + local function stopscaling() -- at the tex end we use sx and sy instead of rx and ry + return stopcommon(stopscalingnode) + end + + implement { + name = "startscaling", + actions = function() + local rx, ry = 1, 1 + while true do + if scankeyword("rx") then + rx = scannumber() + elseif scankeyword("ry") then + ry = scannumber() + else + break + end + end + local t = startscaling(rx,ry) + if t then + context(tonode(t)) + end + end, + } + + implement { + name = "stopscaling", + actions = function() + local t = stopscaling(n) + if t then + context(tonode(t)) + end + end, + } + + -- rotate + + local startrotationnode = registerwhatsitnode("startrotation") + local stoprotationnode = registerwhatsitnode("stoprotation") + + local function startrotation(a) + 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 + local t = copynut(startrotationnode) + nodeproperties[t] = { matrix = { c, s, -s, c } } + insert(stack,restore and { c, -s, s, c } or true) + return t + end + end + + local function stoprotation() + return stopcommon(stoprotationnode) + end + + nutpool.startrotation = startrotation + + implement { + name = "startrotation", + actions = function() + local n = scannumber() + local t = startrotation(n) + if t then + context(tonode(t)) + end + end, + } + + implement { + name = "stoprotation", + actions = function() + local t = stoprotation() + if t then + context(tonode(t)) + end + end, + } + + -- mirror + + local startmirroringnode = registerwhatsitnode("startmirroring") + local stopmirroringnode = registerwhatsitnode("stopmirroring") + + local function startmirroring() + local t = copynut(startmirroringnode) + nodeproperties[t] = { matrix = { -1, 0, 0, 1 } } + return t + end + + local function stopmirroring() + local t = copynut(stopmirroringnode) + nodeproperties[t] = { matrix = { -1, 0, 0, 1 } } + return t + end + + implement { + name = "startmirroring", + actions = function() + context(tonode(startmirroring())) + end, + } + + implement { + name = "stopmirroring", + actions = function() + context(tonode(stopmirroring())) + end, + } + + -- clip + + local startclippingnode = registerwhatsitnode("startclipping") + local stopclippingnode = registerwhatsitnode("stopclipping") + + local function startclipping(path) + local t = copynut(startclippingnode) + nodeproperties[t] = { path = path } + return t + end + + local function stopclipping() + return copynut(stopclippingnode) + end + + implement { + name = "startclipping", + actions = function() + context(tonode(startclipping(scanstring()))) + end + } + + implement { + name = "stopclipping", + actions = function() + context(tonode(stopclipping())) + end, + } + +end + +-- The (delayed and immediate) write operations are emulated in \LUA\ and presented +-- as primitives at the \TEX\ end. + +do + + local logwriter = logs.writer + local openfile = io.open + local flushio = io.flush + local serialize = token.serialize + + local opennode = registerwhatsitnode("open") + local writenode = registerwhatsitnode("write") + local closenode = registerwhatsitnode("close") + local channels = { } + local immediate_code = tex.flagcodes.immediate + + function backends.openout(n) + local p = nodeproperties[n] + if p then + local handle = openfile(p.filename,"wb") or false + if handle then + channels[p.channel] = handle + else + -- error + end + end + end + + function backends.writeout(n) + local p = nodeproperties[n] + if p then + local handle = channels[p.channel] + local content = serialize(p.data) + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end + end + + function backends.closeout(n) + local p = nodeproperties[n] + if p then + local channel = p.channel + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end + end + + local function immediately(prefix) + return prefix and (prefix & immediate_code) ~= 0 + end + + implement { + name = "openout", + public = true, + usage = "value", + actions = function(prefix) + local channel = scaninteger() + scankeyword("=") -- hack + local filename = scanstring() + if not immediately(prefix) then + local n = copynut(opennode) + nodeproperties[n] = { channel = channel, filename = filename } -- action = "open" + return context(tonode(n)) + elseif not channels[channel] then + local handle = openfile(filename,"wb") or false + if handle then + channels[channel] = handle + else + -- error + end + end + end, + } + + implement { + name = "write", + public = true, + usage = "value", + actions = function(prefix) + local channel = scaninteger() + if not immediately(prefix) then + local t = scantokenlist() + local n = copynut(writenode) + nodeproperties[n] = { channel = channel, data = t } -- action = "write" + return context(tonode(n)) + else + local content = scanstring() + local handle = channels[channel] + if handle then + handle:write(content,"\n") + else + logwriter(content,"\n") + end + end + end, + } + + implement { + name = "closeout", + public = true, + usage = "value", + actions = function(prefix) + local channel = scaninteger() + if not immediately(prefix) then + local n = copynut(closenode) + nodeproperties[n] = { channel = channel } -- action = "close" + return context(tonode(n)) + else + local handle = channels[channel] + if handle then + handle:close() + channels[channel] = false + flushio() + else + -- error + end + end + end, + } + + -- why ... + + local open_command = get(token.create("openout")) + local write_command = get(token.create("write")) + local close_command = get(token.create("closeout")) + +end + +-- states: these get injected independent of grouping + +do + + local setstatenode = registerwhatsitnode("setstate") + + function nutpool.setstate(data) + local n = copynut(setstatenode) + nodeproperties[n] = { data = data } + return n + end + +end + +-- We don't support specials so we make them dummies. + +do + implement { + name = "special", + actions = scanstring, + public = true, + protected = true, + } +end diff --git a/tex/context/base/mkxl/node-fin.lmt b/tex/context/base/mkxl/node-fin.lmt index dab90863a..a9180ddb2 100644 --- a/tex/context/base/mkxl/node-fin.lmt +++ b/tex/context/base/mkxl/node-fin.lmt @@ -36,6 +36,7 @@ local setlist = nuts.setlist local setleader = nuts.setleader local copy_node = nuts.copy +local find_tail = nuts.tail local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after @@ -165,13 +166,15 @@ function states.finalize(namespace,attribute,head) -- is this one ok? if id == hlist_code or id == vlist_code then local content = getlist(head) if content then - local list = insert_node_before(content,content,copy_node(nsnone)) -- two return values +-- local list = insert_node_before(content,content,copy_node(nsnone)) -- two return values + local list = insert_node_after(content,find_tail(content),copy_node(nsnone)) -- two return values if list ~= content then setlist(head,list) end end else - head = insert_node_before(head,head,copy_node(nsnone)) +-- head = insert_node_before(head,head,copy_node(nsnone)) + head = insert_node_after(find_tail(head),head,copy_node(nsnone)) end return head, true end @@ -295,6 +298,75 @@ states.process = function(namespace,attribute,head,default) return process(attribute,head,default) end +local function simple(attribute,head) + local check = false + local leader = nil + for stack, id, subtype, content in nextcontent, head do + if id == glyph_code or id == disc_code then + check = true + elseif id == glue_code then + check = true + leader = content + elseif id == hlist_code or id == vlist_code then + if getorientation(stack) then + local outer = getattr(stack,attribute) + if outer then + if current ~= outer then + if current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + end + head = insert_node_before(head,stack,copy_node(nsdata[c])) + current = outer + end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current = 0 + end + end + local list = simple(attribute,content) + if content ~= list then + setlist(stack,list) + end + elseif id == rule_code then + check = has_dimensions(stack) + end + if check then + local c = getattr(stack,attribute) + if c then + if current ~= c then + if current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + end + head = insert_node_before(head,stack,copy_node(nsdata[c])) + current = c + end + if leader then + local savedcurrent = current + local ci = getid(leader) + if ci == hlist_code or ci == vlist_code then + current = 0 + end + local list = simple(attribute,leader) + if leader ~= list then + setleader(stack,list) + end + current = savedcurrent + leader = false + end + elseif current > 0 then + head = insert_node_before(head,stack,copy_node(nsnone)) + current = 0 + end + check = false + end + end + return head +end + +states.simple = function(namespace,attribute,head,default) + return simple(attribute,head,default) +end + -- we can force a selector, e.g. document wide color spaces, saves a little -- watch out, we need to check both the selector state (like colorspace) and -- the main state (like color), otherwise we get into troubles when a selector diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt index 0fba0a4d9..4ba4b4000 100644 --- a/tex/context/base/mkxl/node-ini.lmt +++ b/tex/context/base/mkxl/node-ini.lmt @@ -65,31 +65,6 @@ local function simplified(t) return r end -local nodecodes = simplified(node.types()) - -local whatcodes = allocate { - literal = 0x1, [0x1] = "literal", - latelua = 0x2, [0x2] = "latelua", - userdefined = 0x3, [0x3] = "userdefined", - savepos = 0x4, [0x4] = "savepos", - save = 0x5, [0x5] = "save", - restore = 0x6, [0x6] = "restore", - setmatrix = 0x7, [0x7] = "setmatrix", - open = 0x8, [0x8] = "open", - close = 0x9, [0x9] = "close", - write = 0xA, [0xA] = "write", -} - -local usercodes = allocate { - [ 97] = "attribute", -- a - [100] = "number", -- d - [102] = "float", -- f - [108] = "lua", -- l - [110] = "node", -- n - [115] = "string", -- s - [116] = "token" -- t -} - local noadoptions = allocate { set = 0x08, unused_1 = 0x00 + 0x08, @@ -102,15 +77,7 @@ local noadoptions = allocate { right = 0x14 + 0x08, } -local literalvalues = allocate { - [0] = "origin", - [1] = "page", - [2] = "always", - [3] = "raw", - [4] = "text", - [5] = "font", - [6] = "special", -} +local nodecodes = simplified(node.types()) gluecodes = allocate(swapped(gluecodes,gluecodes)) dircodes = allocate(swapped(dircodes,dircodes)) @@ -118,7 +85,6 @@ boundarycodes = allocate(swapped(boundarycodes,boundarycodes)) noadcodes = allocate(swapped(noadcodes,noadcodes)) radicalcodes = allocate(swapped(radicalcodes,radicalcodes)) nodecodes = allocate(swapped(nodecodes,nodecodes)) -whatcodes = allocate(swapped(whatcodes,whatcodes)) listcodes = allocate(swapped(listcodes,listcodes)) glyphcodes = allocate(swapped(glyphcodes,glyphcodes)) kerncodes = allocate(swapped(kerncodes,kerncodes)) @@ -129,18 +95,15 @@ accentcodes = allocate(swapped(accentcodes,accentcodes)) fencecodes = allocate(swapped(fencecodes,fencecodes)) parcodes = allocate(swapped(parcodes,parcodes)) rulecodes = allocate(swapped(rulecodes,rulecodes)) -usercodes = allocate(swapped(usercodes,usercodes)) noadoptions = allocate(swapped(noadoptions,noadoptions)) dirvalues = allocate(swapped(dirvalues,dirvalues)) -literalvalues = allocate(swapped(literalvalues,literalvalues)) fillvalues = allocate(swapped(fillvalues,fillvalues)) nodes.gluecodes = gluecodes nodes.dircodes = dircodes nodes.boundarycodes = boundarycodes nodes.noadcodes = noadcodes -nodes.whatcodes = whatcodes nodes.listcodes = listcodes nodes.glyphcodes = glyphcodes nodes.kerncodes = kerncodes @@ -152,13 +115,11 @@ nodes.radicalcodes = radicalcodes nodes.fencecodes = fencecodes nodes.parcodes = parcodes nodes.rulecodes = rulecodes -nodes.usercodes = usercodes nodes.noadoptions = noadoptions nodes.fillvalues = fillvalues nodes.fillcodes = fillvalues -- for now nodes.dirvalues = dirvalues -nodes.literalvalues = literalvalues nodes.nodecodes = nodecodes @@ -167,7 +128,6 @@ local subtypes = allocate { dir = dircodes, boundary = boundarycodes, noad = noadcodes, - whatsit = whatcodes, glyph = glyphcodes, kern = kerncodes, penalty = penaltycodes, @@ -201,11 +161,9 @@ nodes.subtypes = subtypes nodes.skipcodes = gluecodes nodes.directioncodes = dircodes -nodes.whatsitcodes = whatcodes nodes.discretionarycodes = disccodes nodes.directionvalues = dirvalues -nodes.literalvalues = literalvalues glyphcodes.glyph = glyphcodes.character @@ -218,8 +176,6 @@ listcodes.column = listcodes.alignment kerncodes.kerning = kerncodes.fontkern kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new -literalvalues.direct = literalvalues.always - nodes.noadoptions = { set = 0x08, unused_1 = 0x00 + 0x08, diff --git a/tex/context/base/mkxl/node-ini.mkxl b/tex/context/base/mkxl/node-ini.mkxl index 4de4e00b4..b3f17e041 100644 --- a/tex/context/base/mkxl/node-ini.mkxl +++ b/tex/context/base/mkxl/node-ini.mkxl @@ -22,6 +22,7 @@ \registerctxluafile{node-met}{autosuffix} \registerctxluafile{node-nut}{autosuffix} \registerctxluafile{node-res}{autosuffix} +\registerctxluafile{node-ext}{autosuffix} %registerctxluafile{node-ppt}{} % experimental, not used so probably useless \registerctxluafile{node-aux}{autosuffix} \registerctxluafile{node-gcm}{autosuffix} @@ -33,11 +34,10 @@ \registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used \registerctxluafile{node-pro}{autosuffix} \registerctxluafile{node-ser}{autosuffix} -%registerctxluafile{node-ext}{} \registerctxluafile{node-acc}{autosuffix} % experimental %registerctxluafile{node-prp}{} % makes no sense (yet) \registerctxluafile{node-scn}{autosuffix} -\registerctxluafile{node-syn}{} +\registerctxluafile{node-syn}{autosuffix} \registerctxluafile{node-par}{autosuffix} %D This might go away (needs checking anyway, very old code): diff --git a/tex/context/base/mkxl/node-res.lmt b/tex/context/base/mkxl/node-res.lmt index 7a37b1b9e..fbb1d1fe2 100644 --- a/tex/context/base/mkxl/node-res.lmt +++ b/tex/context/base/mkxl/node-res.lmt @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['node-res'] = { license = "see context related readme files" } -local type, next = type, next +local type, next, rawset = type, next, rawset local gmatch, format = string.gmatch, string.format --[[ldx-- @@ -21,7 +21,6 @@ local report_nodes = logs.reporter("nodes","housekeeping") nodes.pool = nodes.pool or { } local nodepool = nodes.pool -local whatsitcodes = nodes.whatsitcodes local gluecodes = nodes.gluecodes local kerncodes = nodes.kerncodes local rulecodes = nodes.rulecodes @@ -36,7 +35,6 @@ local rule_code = nodecodes.rule local kern_code = nodecodes.kern local glue_code = nodecodes.glue local gluespec_code = nodecodes.gluespec -local whatsit_code = nodecodes.whatsit local currentfont = font.current local texgetcount = tex.getcount @@ -45,25 +43,6 @@ local allocate = utilities.storage.allocate local reserved = { } local nofreserved = 0 -local userids = allocate() -local lastid = 0 - -setmetatable(userids, { - __index = function(t,k) - if type(k) == "string" then - lastid = lastid + 1 - rawset(userids,lastid,k) - rawset(userids,k,lastid) - return lastid - else - rawset(userids,k,k) - return k - end - end, - __call = function(t,k) - return t[k] - end -} ) -- nuts overload @@ -149,10 +128,7 @@ local function register_node(n) return n end -nodepool.userids = userids nodepool.register = register_node - -nutpool.userids = userids nutpool.register = register_node -- could be register_nut -- so far @@ -168,11 +144,6 @@ local glyph = register_nut(new_nut(glyph_code,0)) local textdir = register_nut(new_nut(nodecodes.dir)) -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_code,whatsitcodes.userdefined) - local left_margin_kern = register_nut(new_nut(kern_code,kerncodes.leftmargincode)) local right_margin_kern = register_nut(new_nut(kern_code,kerncodes.rightmargincode)) @@ -414,16 +385,6 @@ function nutpool.leader(width,list) return n end -function nutpool.savepos() - return copy_nut(savepos) -end - -function nutpool.latelua(code) - local n = copy_nut(latelua) - nodeproperties[n] = { data = code } - return n -end - function nutpool.leftmarginkern(glyph,width) local n = copy_nut(left_margin_kern) if not glyph then diff --git a/tex/context/base/mkxl/node-syn.lmt b/tex/context/base/mkxl/node-syn.lmt new file mode 100644 index 000000000..ce5f0d2dd --- /dev/null +++ b/tex/context/base/mkxl/node-syn.lmt @@ -0,0 +1,782 @@ +if not modules then modules = { } end modules ['node-syn'] = { + 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" +} + +-- Because we have these fields in some node that are used by synctex, and because +-- some users seem to like that feature, I decided to implement a variant that might +-- work out better for ConTeXt. This is experimental code. I don't use it myself so +-- it will take a while to mature. There will be some helpers that one can use in +-- more complex situations like included xml files. Currently (somewhere else) we +-- take care of valid files, that is: we prohibit access to files in the tree +-- because we don't want users to mess up styles. +-- +-- It is unclear how the output gets interpreted but by reverse engineering (and +-- stripping) the file generated by generic synctex, I got there eventually. For +-- instance, we only need to be able to go back to a place where text is entered, +-- but still we need all that redundant box wrapping. Anyway, I was able to get a +-- minimal output and cross my fingers that the parser used in editors is not +-- changed in fundamental ways. +-- +-- 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" $ +-- +-- 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 +-- intermediate file. This is no big deal in context (which has a runner) but +-- definitely not nice. +-- +-- The visualizer code is only needed for testing so we don't use fancy colors or +-- provide more detail. After all we're only interested in rendered source text +-- anyway. We try to play safe which sometimes means that we'd better no go +-- somewhere than go someplace wrong. +-- +-- A previous version had a mode for exporting boxes and such but I removed that +-- as it made no sense. Also, collecting output in a table was not faster than +-- directly piping to the file, probably because the amount is not that large. We +-- keep some left-overs commented. +-- +-- A significate reduction in file size can be realized when reusing the same +-- values. Actually that triggered the current approach in ConTeXt. In the latest +-- synctex parser vertical positions can be repeated by an "=" sign but for some +-- reason only for that field. It's probably trivial to do that for all of "w h d v +-- h" but it currently not the case so I'll delay that till all are supported. (We +-- could benefit a lot from such a repetition scheme but not much from a "v" alone +-- which -alas- indicates that synctex is still mostly a latex targeted story.) +-- +-- It's kind of hard to fight the parser because it really wants to go to some file +-- but maybe some day I can figure it out. Some untagged text (in the pdf) somehow +-- gets seen as part of the last box. Anonymous content is simply not part of the +-- concept. Using a dummy name doesn't help either as the editor gets a signal to +-- open that dummy. Even an empty filename doesn't work. +-- +-- We output really simple and compact code, like: +-- +-- SyncTeX Version:1 +-- Input:1:e:/tmp/oeps.tex +-- Input:2:c:/data/develop/context/sources/klein.tex +-- Output:pdf +-- Magnification:1000 +-- Unit:1 +-- X Offset:0 +-- Y Offset:0 +-- Content: +-- !160 +-- {1 +-- h0,0:0,0,0,0,0 +-- v0,0:0,55380990:39158276,55380990,0 +-- h2,1:4661756,9176901:27969941,655360,327680 +-- h2,2:4661756,10125967:26048041,655360,327680 +-- h2,3:30962888,10125967:1668809,655360,327680 +-- h2,3:4661756,11075033:23142527,655360,327680 +-- h2,4:28046650,11075033:4585047,655360,327680 +-- h2,4:4661756,12024099:22913954,655360,327680 +-- h2,5:27908377,12024099:4723320,655360,327680 +-- h2,5:4661756,12973165:22918783,655360,327680 +-- h2,6:27884864,12973165:4746833,655360,327680 +-- h2,6:4661756,13922231:18320732,655360,327680 +-- ] +-- !533 +-- }1 +-- Input:3:c:/data/develop/context/sources/ward.tex +-- !57 +-- {2 +-- h0,0:0,0,0,0,0 +-- v0,0:0,55380990:39158276,55380990,0 +-- h3,1:4661756,9176901:18813145,655360,327680 +-- h3,2:23713999,9176901:8917698,655360,327680 +-- h3,2:4661756,10125967:10512978,655360,327680 +-- h3,3:15457206,10125967:17174491,655360,327680 +-- h3,3:4661756,11075033:3571223,655360,327680 +-- h3,4:8459505,11075033:19885281,655360,327680 +-- h3,5:28571312,11075033:4060385,655360,327680 +-- h3,5:4661756,12024099:15344870,655360,327680 +-- ] +-- !441 +-- }2 +-- !8 +-- Postamble: +-- Count:22 +-- !23 +-- Post scriptum: +-- +-- But for some reason, when the pdf file has some extra content (like page numbers) +-- the main document is consulted. Bah. It would be nice to have a mode for *only* +-- looking at marked areas. It somehow works not but maybe depends on the parser. +-- +-- Supporting reuseable objects makes not much sense as these are often graphics or +-- ornamental. They can not have hyperlinks etc (at least not without some hackery +-- which I'm not willing to do) so basically they are sort of useless for text. +-- +-- Some generic (more clever code) has been removed as I don't see things change +-- that much. + +local type, rawset = type, rawset +local concat = table.concat +local formatters = string.formatters +local replacesuffix, suffixonly, nameonly = file.replacesuffix, file.suffix, file.nameonly +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 getid = nuts.getid +local getlist = nuts.getlist +local setlist = nuts.setlist +local getnext = nuts.getnext +local getwhd = nuts.getwhd +local getwidth = nuts.getwidth +local getsubtype = nuts.getsubtype + +local nodecodes = nodes.nodecodes +local kerncodes = nodes.kerncodes + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local kern_code = nodecodes.kern +----- rule_code = nodecodes.rule +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local dir_code = nodecodes.dir +local fontkern_code = kerncodes.fontkern + +local cancel_code = nodes.dircodes.cancel + +local insert_before = nuts.insert_before +local insert_after = nuts.insert_after + +local nodepool = nuts.pool +local new_latelua = nodepool.latelua +local new_rule = nodepool.rule +local new_kern = nodepool.kern + +local getdimensions = nuts.dimensions +local getrangedimensions = nuts.rangedimensions + +local getsynctexfields = nuts.getsynctexfields or nuts.get_synctex_fields +local forcesynctextag = tex.forcesynctextag or tex.force_synctex_tag +local forcesynctexline = tex.forcesynctexline or tex.force_synctex_line +local getsynctexline = tex.getsynctexline or tex.get_synctex_line +local setsynctexmode = tex.setsynctexmode or tex.set_synctex_mode + +local foundintree = resolvers.foundintree + +local getpagedimensions = layouts.getpagedimensions + +local eol = "\010" + +----- f_glue = formatters["g%i,%i:%i,%i\010"] +----- f_glyph = formatters["x%i,%i:%i,%i\010"] +----- f_kern = formatters["k%i,%i:%i,%i:%i\010"] +----- f_rule = formatters["r%i,%i:%i,%i:%i,%i,%i\010"] +----- f_form = formatters["f%i,%i,%i\010"] +local z_hlist = "[0,0:0,0:0,0,0\010" +local z_vlist = "(0,0:0,0:0,0,0\010" +----- z_xform = "<0,0:0,0,0\010" -- or so +local s_hlist = "]\010" +local s_vlist = ")\010" +----- s_xform = ">\010" +local f_hlist_1 = formatters["h%i,%i:%i,%i:%i,%i,%i\010"] +local f_hlist_2 = formatters["h%i,%i:%i,%s:%i,%i,%i\010"] +local f_vlist_1 = formatters["v%i,%i:%i,%i:%i,%i,%i\010"] +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 +local paused = 0 +local used = false +local never = false + +-- the file name stuff + +local noftags = 0 +local stnums = { } +local nofblocked = 0 +local blockedfilenames = { } +local blockedsuffixes = { + mkii = true, + mkiv = true, + mkvi = true, + mkxl = true, + mklx = true, + mkix = true, + mkxi = true, + -- lfg = true, +} + +local sttags = table.setmetatableindex(function(t,name) + if blockedsuffixes[suffixonly(name)] then + -- Just so that I don't get the ones on my development tree. + nofblocked = nofblocked + 1 + return 0 + elseif blockedfilenames[nameonly(name)] then + -- So we can block specific files. + nofblocked = nofblocked + 1 + return 0 + elseif foundintree(name) then + -- One shouldn't edit styles etc this way. + nofblocked = nofblocked + 1 + return 0 + else + noftags = noftags + 1 + t[name] = noftags + stnums[noftags] = name + return noftags + end +end) + +function synctex.blockfilename(name) + blockedfilenames[nameonly(name)] = name +end + +function synctex.setfilename(name,line) + if paused == 0 and name then + forcesynctextag(sttags[name]) + if line then + forcesynctexline(line) + end + end +end + +function synctex.resetfilename() + if paused == 0 then + forcesynctextag(0) + forcesynctexline(0) + end +end + +do + + local nesting = 0 + local ignored = false + + function synctex.pushline() + nesting = nesting + 1 + if nesting == 1 then + local l = getsynctexline() + ignored = l and l > 0 + if not ignored then + forcesynctexline(texget("inputlineno")) + end + end + end + + function synctex.popline() + if nesting == 1 then + if not ignored then + forcesynctexline() + ignored = false + end + end + nesting = nesting - 1 + end + +end + +-- the node stuff + +local filehandle = nil +local nofsheets = 0 +local nofobjects = 0 +local last = 0 +local filesdone = 0 +local tmpfile = false +local logfile = false + +local function writeanchor() + local size = filehandle:seek("end") + filehandle:write("!",size-last,eol) + last = size +end + +local function writefiles() + local total = #stnums + if filesdone < total then + for i=filesdone+1,total do + filehandle:write("Input:",i,":",stnums[i],eol) + end + filesdone = total + end +end + +local function makenames() + logfile = replacesuffix(tex.jobname,"synctex") + tmpfile = replacesuffix(logfile,"syncctx") +end + +local function flushpreamble() + makenames() + filehandle = openfile(tmpfile,"wb") + if filehandle then + filehandle:write("SyncTeX Version:1",eol) + writefiles() + filehandle:write("Output:pdf",eol) + filehandle:write("Magnification:1000",eol) + filehandle:write("Unit:1",eol) + filehandle:write("X Offset:0",eol) + filehandle:write("Y Offset:0",eol) + filehandle:write("Content:",eol) + flushpreamble = function() + writefiles() + return filehandle + end + else + enabled = false + end + return filehandle +end + +function synctex.wrapup() + if tmpfile then + renamefile(tmpfile,logfile) + tmpfile = nil + end +end + +local function flushpostamble() + if not filehandle then + return + end + writeanchor() + filehandle:write("Postamble:",eol) + filehandle:write("Count:",nofobjects,eol) + writeanchor() + filehandle:write("Post scriptum:",eol) + filehandle:close() + enabled = false +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,pageheight-y,w,h,d)) + nofobjects = nofobjects + 1 + end + + local lasty = false + + local function doaction_2(t,l,w,h,d) + local pagewidth, pageheight = getpagedimensions() + local x, y = getpos() + y = pageheight - y + filehandle:write(f_hlist_2(t,l,x,y == lasty and "=" or y,w,h,d)) + lasty = y + nofobjects = nofobjects + 1 + end + + local doaction = doaction_1 + + x_hlist = function(head,current,t,l,w,h,d) + if filehandle then + return insert_before(head,current,new_latelua(function() doaction(t,l,w,h,d) end)) + else + return head + end + end + + directives.register("system.synctex.compression", function(v) + doaction = tonumber(v) == 2 and doaction_2 or doaction_1 + end) + +end + +-- color is already handled so no colors + +local collect = nil +local fulltrace = false +local trace = false +local height = 10 * 65536 +local depth = 5 * 65536 +local traceheight = 32768 +local tracedepth = 32768 + +trackers.register("system.synctex.visualize", function(v) + trace = v + fulltrace = v == "real" +end) + +local function inject(head,first,last,tag,line) + local w, h, d = getdimensions(first,getnext(last)) + if h < height then + h = height + end + if d < depth then + d = depth + end + if trace then + head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth)) + head = insert_before(head,first,new_kern(-w)) + end + head = x_hlist(head,first,tag,line,w,h,d) + return head +end + +local function collect_min(head) + local current = head + while current do + local id = getid(current) + if id == glyph_code then + local first = current + local last = current + local tag = 0 + local line = 0 + while true do + if id == glyph_code then + local tc, lc = getsynctexfields(current) + if tc and tc > 0 then + tag = tc + line = lc + end + last = current + elseif id == disc_code or (id == kern_code and getsubtype(current) == fontkern_code) then + last = current + else + if tag > 0 then + head = inject(head,first,last,tag,line) + end + break + end + current = getnext(current) + if current then + id = getid(current) + else + if tag > 0 then + head = inject(head,first,last,tag,line) + end + return head + end + end + end + -- pick up (as id can have changed) + if id == hlist_code or id == vlist_code then + local list = getlist(current) + if list then + local l = collect(list) + if l ~= list then + setlist(current,l) + end + end + end + current = getnext(current) + end + return head +end + +local function inject(parent,head,first,last,tag,line) + local w, h, d = getrangedimensions(parent,first,getnext(last)) + if h < height then + h = height + end + if d < depth then + d = depth + end + if trace then + head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth)) + head = insert_before(head,first,new_kern(-w)) + end + head = x_hlist(head,first,tag,line,w,h,d) + return head +end + +local function collect_max(head,parent) + local current = head + while current do + local id = getid(current) + if id == glyph_code then + local first = current + local last = current + local tag = 0 + local line = 0 + while true do + if id == glyph_code then + local tc, lc = getsynctexfields(current) + if tc and tc > 0 then + if tag > 0 and (tag ~= tc or line ~= lc) then + head = inject(parent,head,first,last,tag,line) + first = current + end + tag = tc + line = lc + last = current + else + if tag > 0 then + head = inject(parent,head,first,last,tag,line) + tag = 0 + end + first = nil + last = nil + end + elseif id == disc_code then + if not first then + first = current + end + last = current + elseif id == kern_code and getsubtype(current) == fontkern_code then + if first then + last = current + end + elseif id == glue_code then + if tag > 0 then + local tc, lc = getsynctexfields(current) + if tc and tc > 0 then + if tag ~= tc or line ~= lc then + head = inject(parent,head,first,last,tag,line) + tag = 0 + break + end + else + head = inject(parent,head,first,last,tag,line) + tag = 0 + break + end + else + tag = 0 + break + end + id = nil -- so no test later on + elseif id == penalty_code then + -- go on (and be nice for math) + else + if tag > 0 then + head = inject(parent,head,first,last,tag,line) + tag = 0 + end + break + end + current = getnext(current) + if current then + id = getid(current) + else + if tag > 0 then + head = inject(parent,head,first,last,tag,line) + end + return head + end + end + end + -- pick up (as id can have changed) + if id == hlist_code or id == vlist_code then + local list = getlist(current) + if list then + local l = collect(list,current) + if l and l ~= list then + setlist(current,l) + end + end + end + current = getnext(current) + end + return head +end + +collect = collect_max + +function synctex.collect(head,where) + if enabled and where ~= "object" then + return collect(head,head) + else + return head + end +end + +-- also no solution for bad first file resolving in sumatra + +function synctex.start() + if enabled then + nofsheets = nofsheets + 1 -- could be realpageno + if flushpreamble() then + writeanchor() + filehandle:write("{",nofsheets,eol) + -- this seems to work: + local pagewidth, pageheight = getpagedimensions() + filehandle:write(z_hlist) + filehandle:write(f_vlist_1(0,0,0,pageheight,pagewidth,pageheight,0)) + end + end +end + +function synctex.stop() + if enabled then + -- filehandle:write(s_vlist,s_hlist) + filehandle:write(s_hlist) + writeanchor() + filehandle:write("}",nofsheets,eol) + nofobjects = nofobjects + 2 + end +end + +local enablers = { } +local disablers = { } + +function synctex.registerenabler(f) + enablers[#enablers+1] = f +end + +function synctex.registerdisabler(f) + disablers[#disablers+1] = f +end + +function synctex.enable() + if not never and not enabled then + enabled = true + setsynctexmode(3) -- we want details + if not used then + nodes.tasks.enableaction("shipouts","luatex.synctex.collect") + report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!") + used = true + end + for i=1,#enablers do + enablers[i](true) + end + end +end + +function synctex.disable() + if enabled then + setsynctexmode(0) + report_system("synctex functionality is disabled!") + enabled = false + for i=1,#disablers do + disablers[i](false) + end + end +end + +function synctex.finish() + if enabled then + flushpostamble() + else + makenames() + removefile(logfile) + removefile(tmpfile) + end +end + +local filename = nil + +function synctex.pause() + paused = paused + 1 + if enabled and paused == 1 then + setsynctexmode(0) + end +end + +function synctex.resume() + if enabled and paused == 1 then + setsynctexmode(3) + end + paused = paused - 1 +end + +-- not the best place + +luatex.registerstopactions(synctex.finish) + +statistics.register("synctex tracing",function() + if used then + return string.format("%i referenced files, %i files ignored, %i objects flushed, logfile: %s", + noftags,nofblocked,nofobjects,logfile) + end +end) + +local implement = interfaces.implement +local variables = interfaces.variables + +function synctex.setup(t) + if t.state == variables.never then + synctex.disable() -- just in case + never = true + return + end + if t.method == variables.max then + collect = collect_max + else + collect = collect_min + end + if t.state == variables.start then + synctex.enable() + else + synctex.disable() + end +end + +implement { + name = "synctexblockfilename", + arguments = "string", + actions = synctex.blockfilename, +} + +implement { + name = "synctexsetfilename", + arguments = "string", + actions = synctex.setfilename, +} + +implement { + name = "synctexresetfilename", + actions = synctex.resetfilename, +} + +implement { + name = "setupsynctex", + actions = synctex.setup, + arguments = { + { + { "state" }, + { "method" }, + }, + }, +} + +implement { + name = "synctexpause", + actions = synctex.pause, +} + +implement { + name = "synctexresume", + actions = synctex.resume, +} + +implement { + name = "synctexpushline", + actions = synctex.pushline, +} + +implement { + name = "synctexpopline", + actions = synctex.popline, +} + +implement { + name = "synctexdisable", + actions = synctex.disable, +} diff --git a/tex/context/base/mkxl/node-tra.lmt b/tex/context/base/mkxl/node-tra.lmt index da3cb1d33..6060522be 100644 --- a/tex/context/base/mkxl/node-tra.lmt +++ b/tex/context/base/mkxl/node-tra.lmt @@ -704,7 +704,7 @@ table.setmetatableindex(nodestracerpool,function(t,k,v) return v end) -function nutstracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup) +function nutstracerpool.rule(w,h,d,c,s) return setproperties(new_rule(w,h,d),c,s) end diff --git a/tex/context/base/mkxl/page-lin.lmt b/tex/context/base/mkxl/page-lin.lmt index 9ea502899..f50031ab3 100644 --- a/tex/context/base/mkxl/page-lin.lmt +++ b/tex/context/base/mkxl/page-lin.lmt @@ -192,7 +192,7 @@ local function resolve(n,m) -- we can now check the 'line' flag (todo) if content then if id == hlist_code then for current, subtype in nextwhatsit, content do - if subtype == latelua_code then + if subtype == latelua_code then -- this has to change! local a = getattr(current,a_linereference) if a then cross_references[a] = m diff --git a/tex/context/base/mkxl/scrn-pag.lmt b/tex/context/base/mkxl/scrn-pag.lmt new file mode 100644 index 000000000..210a57707 --- /dev/null +++ b/tex/context/base/mkxl/scrn-pag.lmt @@ -0,0 +1,56 @@ +if not modules then modules = { } end modules ['scrn-pag'] = { + version = 1.001, + comment = "companion to scrn-pag.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +interactions = interactions or { } +interactions.pages = interactions.pages or { } +local pages = interactions.pages + +local implement = interfaces.implement + +pages.setupcanvas = layouts.setupcanvas + +local codeinjections = backends.codeinjections + +function pages.setpagetransition(specification) + codeinjections.setpagetransition(specification) +end + +implement { + name = "setupcanvas", + actions = pages.setupcanvas, + arguments = { + { + { "mode" }, + { "singlesided", "boolean" }, + { "doublesided", "boolean" }, + { "leftoffset", "dimen" }, + { "topoffset", "dimen" }, + { "width", "dimen" }, + { "height", "dimen" }, + { "paperwidth", "dimen" }, + { "paperheight", "dimen" }, + { "cropoffset", "dimen" }, + { "bleedoffset", "dimen" }, + { "artoffset", "dimen" }, + { "trimoffset", "dimen" }, + { "copies", "integer" }, + { "print", "string" }, -- , tohash + } + } +} + +implement { + name = "setpagetransition", + actions = pages.setpagetransition, + arguments = { + { + { "n" }, + { "delay", "integer" }, + } + } +} diff --git a/tex/context/base/mkxl/scrn-pag.mklx b/tex/context/base/mkxl/scrn-pag.mklx index 80e16f63d..67e24178e 100644 --- a/tex/context/base/mkxl/scrn-pag.mklx +++ b/tex/context/base/mkxl/scrn-pag.mklx @@ -15,7 +15,7 @@ \writestatus{loading}{ConTeXt Screen Macros / Pages} -\registerctxluafile{scrn-pag}{} +\registerctxluafile{scrn-pag}{autosuffix} \unprotect diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl index 426580c7d..13d1f9021 100644 --- a/tex/context/base/mkxl/spac-hor.mkxl +++ b/tex/context/base/mkxl/spac-hor.mkxl @@ -677,6 +677,29 @@ \newskip \s_spac_narrower_right_last \newconditional\s_spac_narrower_last_swap +% \def\spac_narrower_start_apply#1% +% {\narrowerparameter\c!before +% \global\s_spac_narrower_left \zeropoint +% \global\s_spac_narrower_right \zeropoint +% \global\s_spac_narrower_middle\zeropoint +% \edef\askednarrower{#1}% +% \ifx\askednarrower\v!reverse +% \ifconditional\s_spac_narrower_last_swap +% \leftskip \s_spac_narrower_right_last +% \rightskip\s_spac_narrower_left_last +% \setfalse\s_spac_narrower_last_swap +% \else +% \leftskip \s_spac_narrower_left_last +% \rightskip\s_spac_narrower_right_last +% \settrue\s_spac_narrower_last_swap +% \fi +% \else +% \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize +% \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax +% \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax +% \fi +% \seteffectivehsize} + \def\spac_narrower_start_apply#1% {\narrowerparameter\c!before \global\s_spac_narrower_left \zeropoint @@ -685,18 +708,18 @@ \edef\askednarrower{#1}% \ifx\askednarrower\v!reverse \ifconditional\s_spac_narrower_last_swap - \leftskip \s_spac_narrower_right_last - \rightskip\s_spac_narrower_left_last + \frozen\leftskip \s_spac_narrower_right_last + \frozen\rightskip\s_spac_narrower_left_last \setfalse\s_spac_narrower_last_swap \else - \leftskip \s_spac_narrower_left_last - \rightskip\s_spac_narrower_right_last + \frozen\leftskip \s_spac_narrower_left_last + \frozen\rightskip\s_spac_narrower_right_last \settrue\s_spac_narrower_last_swap \fi \else \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize - \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax - \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax + \frozen\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax + \frozen\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax \fi \seteffectivehsize} diff --git a/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl index af98ca481..dcfdd0946 100644 --- a/tex/context/base/mkxl/strc-reg.mkxl +++ b/tex/context/base/mkxl/strc-reg.mkxl @@ -40,6 +40,20 @@ % \index[pageclass::] {textclass::entry} % \index[pageclass::key]{textclass::entry} +% nice example: +% +% \setupregister[index] +% [n=1, +% pageleft=\hfilll, +% pageright=\frozen\parfillleftskip 0pt plus 1fill\frozen\parfillrightskip 0pt\par] +% +% \starttext +% +% {\showmakeup \placeindex \page} +% +% % \dorecurse{10}{\dontleavehmode \index{AAA}\page} +% \dorecurse{100}{\dontleavehmode\index{AAA}\page} + % tzt variant with n entries, parameters and userdata (altnum) \installcorenamespace{register} diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt index 8c04a0372..6e9bd8e8c 100644 --- a/tex/context/base/mkxl/trac-vis.lmt +++ b/tex/context/base/mkxl/trac-vis.lmt @@ -595,17 +595,28 @@ local whatsit do local w_cache = caches["whatsit"] local tags = { - open = "OPN", - write = "WRI", - close = "CLS", - special = "SPE", - latelua = "LUA", - savepos = "POS", - userdefined = "USR", - literal = "LIT", - setmatrix = "MAT", - save = "SAV", - restore = "RES", + [whatsitcodes.open] = "OPN", + [whatsitcodes.write] = "WRI", + [whatsitcodes.close] = "CLS", + -- [whatsitcodes.special] = "SPE", + [whatsitcodes.latelua] = "LUA", + [whatsitcodes.savepos] = "POS", + [whatsitcodes.userdefined] = "USR", + [whatsitcodes.literal] = "LIT", + [whatsitcodes.setmatrix] = "MAT", + [whatsitcodes.save] = "SAV", + [whatsitcodes.restore] = "RES", + [whatsitcodes.startscaling] = "+SCA", + [whatsitcodes.stopscaling] = "-SCA", + [whatsitcodes.startrotation] = "+ROT", + [whatsitcodes.stoprotation] = "-ROT", + [whatsitcodes.startmirroring] = "+MIR", + [whatsitcodes.stopmirroring] = "-MIR", + [whatsitcodes.startclipping] = "+CLP", + [whatsitcodes.stopclipping] = "-CLP", + [whatsitcodes.startmatrix] = "+MAT", + [whatsitcodes.stopmatrix] = "-MAT", + [whatsitcodes.setstate] = "SET", -- can't happen because these are added after visualizing } whatsit = function(head,current) @@ -614,7 +625,7 @@ local whatsit do if info then -- print("hit whatsit") else - info = sometext(formatters["W:%s"](what),usedfont,nil,c_white) + info = sometext(formatters["W:%s"](tags[what] or what),usedfont,nil,c_white) setattr(info,a_layer,l_whatsit) w_cache[what] = info end @@ -880,20 +891,13 @@ local ruledglyph do setboth(current) local linewidth = emwidth/(2*fraction) local x_offset, y_offset, l_margin, r_margin, raise = getoffsets(current) - wd = wd - l_margin - r_margin - local info = (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { + local info = setlink((dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { width = wd, height = ht, depth = dp, line = linewidth, type = "box", - } - if l_margin == 0 then - info = setlink(info,new_kern(-wd)) - else - info = setlink(new_kern(-l_margin),info,new_kern(-wd+l_margin)) - end - -- + },new_kern(-wd)) local c, f = isglyph(current) local char = chardata[f][c] if char and type(char.unicode) == "table" then -- hackery test @@ -1409,7 +1413,7 @@ do trace_marginkern = band(a,0x100000) ~= 0 trace_mathlistkern = band(a,0x200000) ~= 0 trace_dir = band(a,0x400000) ~= 0 - trace_whatsit = band(a,0x800000) ~= 0 + trace_par = band(a,0x800000) ~= 0 end elseif a == unsetvalue then goto list diff --git a/tex/context/base/mkxl/typo-cap.lmt b/tex/context/base/mkxl/typo-cap.lmt index dbf6950c8..67acb2535 100644 --- a/tex/context/base/mkxl/typo-cap.lmt +++ b/tex/context/base/mkxl/typo-cap.lmt @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['typo-cap'] = { local next, type, tonumber = next, type, tonumber local format, insert = string.format, table.insert -local div, getrandom = math.div, utilities.randomizer.get +local div, getrandom, random = math.div, utilities.randomizer.get, math.random local trace_casing = false trackers.register("typesetters.casing", function(v) trace_casing = v end) @@ -435,3 +435,24 @@ interfaces.implement { actions = cases.set, arguments = { "argument" } } + +-- An example of a special plug, see type-imp-punk for usage. + +cases.register("randomvariant", function(start) + local char, fnt = isglyph(start) + local data = fontchar[fnt][char] + if data then + local variants = data.variants + if variants then + local n = #variants + local i = getrandom("variant",1,n+1) + if i > n then + -- we keep the original + else + setchar(start,variants[i]) + end + return start, true + end + end + return start, false +end) diff --git a/tex/context/fonts/mkiv/bonum-math.lfg b/tex/context/fonts/mkiv/bonum-math.lfg index 8dfa63405..51ca2d7f1 100644 --- a/tex/context/fonts/mkiv/bonum-math.lfg +++ b/tex/context/fonts/mkiv/bonum-math.lfg @@ -1,5 +1,8 @@ -local kern_200 = { bottomright = { { kern = -200 } } } -local kern_100 = { bottomright = { { kern = -100 } } } +local kern_V = { bottomright = { { kern = -200 } } } +local kern_W = { bottomright = { { kern = -100 } } } +local offset_f = { xoffset = "llx" } + +-- Beware of updates in ssty slots! return { name = "bonum-math", @@ -10,12 +13,21 @@ return { mathematics = { dimensions = { default = { - [0x1D453] = { xoffset = "llx" },-- ð‘“ + -- [0x1D453] = offset_f, -- ð‘“ + -- ["1:0x1D453"] = offset_f, -- needed for compact + -- ["2:0x1D453"] = offset_f, -- needed for compact + ["*:0x1D453"] = offset_f, -- ð‘“ }, }, kerns = { - [0x1D449] = kern_200, -- 𑉠- [0x1D44A] = kern_100, -- ð‘Š + -- [0x1D449] = kern_V, -- 𑉠+ -- ["1:0x1D449"] = kern_V, -- needed for compact + -- ["2:0x1D449"] = kern_V, -- needed for compact + -- [0x1D44A] = kern_W, -- ð‘Š + -- ["1:0x1D44A"] = kern_W, -- needed for compact + -- ["2:0x1D44A"] = kern_W, -- needed for compact + ["*:0x1D449"] = kern_V, -- 𑉠+ ["*:0x1D44A"] = kern_W, -- ð‘Š }, alternates = { dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, diff --git a/tex/context/fonts/mkiv/dejavu-math.lfg b/tex/context/fonts/mkiv/dejavu-math.lfg index d28c69060..608b396f8 100644 --- a/tex/context/fonts/mkiv/dejavu-math.lfg +++ b/tex/context/fonts/mkiv/dejavu-math.lfg @@ -1,4 +1,7 @@ -local kern_250 = { bottomright = { { kern = -250 } } } +local kern_V = { bottomright = { { kern = -250 } } } +local kern_W = kern_W + +-- Beware of updates in ssty slots! return { name = "dejavu-math", @@ -8,8 +11,14 @@ return { copyright = "ConTeXt development team", mathematics = { kerns = { - [0x1D449] = kern_250, -- - [0x1D44A] = kern_250, -- ð‘Š + -- [0x1D449] = kern_V, -- 𑉠+ -- ["1:0x1D449"] = kern_V, -- needed for compact + -- ["2:0x1D449"] = kern_V, -- needed for compact + -- [0x1D44A] = kern_W, -- ð‘Š + -- ["1:0x1D44A"] = kern_W, -- needed for compact + -- ["2:0x1D44A"] = kern_W, -- needed for compact + ["*:0x1D449"] = kern_V, -- 𑉠+ ["*:0x1D44A"] = kern_W, -- ð‘Š }, alternates = { dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, diff --git a/tex/context/fonts/mkiv/minion-math.lfg b/tex/context/fonts/mkiv/minion-math.lfg index a4f539ec7..863836c1c 100644 --- a/tex/context/fonts/mkiv/minion-math.lfg +++ b/tex/context/fonts/mkiv/minion-math.lfg @@ -1,6 +1,5 @@ -local kern_100 = { bottomright = { { kern = -100 } } } -local kern_150 = { bottomright = { { kern = -150 } } } -local kern_200 = { bottomright = { { kern = -200 } } } +local kern_W = { bottomright = { { kern = -150 } } } +local kern_V = { bottomright = { { kern = -200 } } } return { name = "minion-math", @@ -23,8 +22,9 @@ return { }, mathematics = { kerns = { - [0x1D449] = kern_200, -- 𑉠- [0x1D44A] = kern_150, -- ð‘Š + [0x1D449] = kern_V, -- 𑉠+ [0x1D44A] = kern_W, -- ð‘Š + -- todo: ssty 1/2 }, }, } diff --git a/tex/context/fonts/mkiv/pagella-math.lfg b/tex/context/fonts/mkiv/pagella-math.lfg index c85ff3f6b..d4ae14162 100644 --- a/tex/context/fonts/mkiv/pagella-math.lfg +++ b/tex/context/fonts/mkiv/pagella-math.lfg @@ -1,7 +1,8 @@ -local kern_200 = { bottomright = { { kern = -200 } } } -local kern_100 = { bottomright = { { kern = -100 } } } +local kern_V = { bottomright = { { kern = -200 } } } +local kern_W = { bottomright = { { kern = -100 } } } +local offset_f = { xoffset = "llx" } --- Beware of updates ! +-- Beware of updates in ssty slots! return { name = "pagella-math", @@ -12,13 +13,22 @@ return { mathematics = { dimensions = { default = { - -- [0x1D453] = { xoffset = 162, width = 278 + 162 },-- ð‘“ - [0x1D453] = { xoffset = "llx" },-- ð‘“ + -- [0x1D453] = { xoffset = 162, width = 278 + 162 },-- ð‘“ + -- [0x1D453] = offset_f, -- ð‘“ + -- ["1:0x1D453"] = offset_f, -- needed for compact + -- ["2:0x1D453"] = offset_f, -- needed for compact + ["*:0x1D453"] = offset_f, -- ð‘“ }, }, kerns = { - [0x1D449] = kern_200, -- 𑉠- [0x1D44A] = kern_100, -- ð‘Š + -- [0x1D449] = kern_V, -- 𑉠+ -- ["1:0x1D449"] = kern_V, -- needed for compact + -- ["2:0x1D449"] = kern_V, -- needed for compact + -- [0x1D44A] = kern_W, -- ð‘Š + -- ["1:0x1D44A"] = kern_W, -- needed for compact + -- ["2:0x1D44A"] = kern_W, -- needed for compact + ["*:0x1D449"] = kern_V, -- 𑉠+ ["*:0x1D44A"] = kern_W, -- ð‘Š }, alternates = { dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, diff --git a/tex/context/fonts/mkiv/schola-math.lfg b/tex/context/fonts/mkiv/schola-math.lfg index 9787c18a9..b60bc6d99 100644 --- a/tex/context/fonts/mkiv/schola-math.lfg +++ b/tex/context/fonts/mkiv/schola-math.lfg @@ -1,5 +1,7 @@ -local kern_200_050 = { bottomright = { { kern = -200 } }, topright = { { kern = 50 } } } -local kern_100_050 = { bottomright = { { kern = -100 } }, topright = { { kern = 50 } } } +local kern_V = { bottomright = { { kern = -200 } }, topright = { { kern = 50 } } } +local kern_W = { bottomright = { { kern = -100 } }, topright = { { kern = 50 } } } + +-- Beware of updates in ssty slots! return { name = "schola-math", @@ -9,8 +11,14 @@ return { copyright = "ConTeXt development team", mathematics = { kerns = { - [0x1D449] = kern_200_050, -- - [0x1D44A] = kern_100_050, -- ð‘Š + -- [0x1D449] = kern_V, -- 𑉠+ -- ["1:0x1D449"] = kern_V, -- needed for compact + -- ["2:0x1D449"] = kern_V, -- needed for compact + -- [0x1D44A] = kern_W, -- ð‘Š + -- ["1:0x1D44A"] = kern_W, -- needed for compact + -- ["2:0x1D44A"] = kern_W, -- needed for compact + ["*:0x1D449"] = kern_V, -- 𑉠+ ["*:0x1D44A"] = kern_W, -- ð‘Š }, alternates = { dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, diff --git a/tex/context/fonts/mkiv/termes-math.lfg b/tex/context/fonts/mkiv/termes-math.lfg index 1501fd536..3cf8685eb 100644 --- a/tex/context/fonts/mkiv/termes-math.lfg +++ b/tex/context/fonts/mkiv/termes-math.lfg @@ -1,5 +1,8 @@ -local kern_200 = { bottomright = { { kern = -200 } } } -local kern_100 = { bottomright = { { kern = -100 } } } +local kern_V = { bottomright = { { kern = -200 } } } +local kern_W = { bottomright = { { kern = -100 } } } +local offset_f = { xoffset = "llx" } + +-- Beware of updates in ssty slots! return { name = "termes-math", @@ -10,12 +13,21 @@ return { mathematics = { dimensions = { default = { - [0x1D453] = { xoffset = "llx" },-- ð‘“ + -- [0x1D453] = offset_f, -- ð‘“ + -- ["1:0x1D453"] = offset_f, -- needed for compact + -- ["2:0x1D453"] = offset_f, -- needed for compact + ["*:0x1D453"] = offset_f, -- ð‘“ }, }, kerns = { - [0x1D449] = kern_200, -- 𑉠- [0x1D44A] = kern_100, -- ð‘Š + -- [0x1D449] = kern_V, -- 𑉠+ -- ["1:0x1D449"] = kern_V, -- needed for compact + -- ["2:0x1D449"] = kern_V, -- needed for compact + -- [0x1D44A] = kern_W, -- ð‘Š + -- ["1:0x1D44A"] = kern_W, -- needed for compact + -- ["2:0x1D44A"] = kern_W, -- needed for compact + ["*:0x1D449"] = kern_V, -- 𑉠+ ["*:0x1D44A"] = kern_W, -- ð‘Š }, alternates = { dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, diff --git a/tex/context/fonts/mkiv/type-imp-punk.mkxl b/tex/context/fonts/mkiv/type-imp-punk.mkxl new file mode 100644 index 000000000..aa01a1d4e --- /dev/null +++ b/tex/context/fonts/mkiv/type-imp-punk.mkxl @@ -0,0 +1,54 @@ +%D \module +%D [ file=type-imp-punk, +%D version=2020.01.17, +%D title=\CONTEXT\ Typescript Macros, +%D subtitle=Punk Again, +%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 Yet another look at punk. + +\ifdefined\enablerandomvariants\else + \useMPlibrary[punk] +\fi + +\doifelse {\truefontname{Serif}} {unknown} { + \writestatus{fonts}{you need to load a base bodyfont first} + \endinput +} { + % we're ok +} + +\starttypescriptcollection[punk] + + \definefontfeature [punk] [metapost={category=punk,preroll=punkpreroll}] + \definefontfeature [punkrandom] [metapost={category=punk,preroll=punkpreroll,variants=5}] + \definefontfeature [punkbold] [metapost={category=punk,preroll=punkpreroll,weight=2}] + \definefontfeature [punkslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15}] + \definefontfeature [punkboldslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15,weight=2}] + \definefontfeature [punkveryslanted] [metapost={category=punk,preroll=punkpreroll,slant=-.15}] + \definefontfeature [punksqueezed] [metapost={category=punk,preroll=punkpreroll,squeeze=.5}] + \definefontfeature [punkextended] [metapost={category=punk,preroll=punkpreroll,extend=1.3}] + + \definefontsynonym [punkbase] [\truefontname{Serif}] + + \starttypescript [\s!serif] [punk] + \definefontsynonym [\s!Serif] [punkbase] [\s!features=punk] + \definefontsynonym [\s!SerifSlanted] [punkbase] [\s!features=punkslanted] + \definefontsynonym [\s!SerifBold] [punkbase] [\s!features=punkbold] + \definefontsynonym [\s!SerifBoldSlanted][punkbase] [\s!features=punkboldslanted] + \definefontsynonym [\s!SerifItalic] [\s!SerifSlanted] + \definefontsynonym [\s!SerifBoldItalic] [\s!SerifBoldSlanted] + \stoptypescript + + \starttypescript [punk] + \definetypeface [punk] [\s!rm] [\s!serif] [punk] [\s!default] + \stoptypescript + +\stoptypescriptcollection + diff --git a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv index d10fe505f..72d3b3588 100644 --- a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv +++ b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv @@ -247,8 +247,8 @@ \starttypescript [\s!math][times,termes][\s!all] % \loadfontgoodies[texgyre] % \definefontsynonym[\s!MathRoman][file:texgyre-termes-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre] - \definefontsynonym[\s!MathRoman] [file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=termes-math] - \definefontsynonym[\s!MathRomanBold][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,termes-math-bold,mathextra},\s!goodies=termes-math] + \definefontsynonym[\s!MathRoman] [file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=termes-math] + \definefontsynonym[\s!MathRomanBold][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,termes-math-bold,mathextra},\s!goodies=termes-math] \stoptypescript \stoptypescriptcollection @@ -276,8 +276,8 @@ \starttypescript [\s!math][palatino,pagella][\s!all] % \loadfontgoodies[texgyre] % \definefontsynonym[\s!MathRoman][file:texgyre-pagella-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre] - \definefontsynonym[\s!MathRoman] [file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=pagella-math] - \definefontsynonym[\s!MathRomanBold][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,pagella-math-bold,mathextra},\s!goodies=pagella-math] + \definefontsynonym[\s!MathRoman] [file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=pagella-math] + \definefontsynonym[\s!MathRomanBold][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,pagella-math-bold,mathextra},\s!goodies=pagella-math] \stoptypescript \stoptypescriptcollection @@ -289,8 +289,8 @@ \starttypescript [\s!math][bookman,bonum][\s!all] % \loadfontgoodies[texgyre] % \definefontsynonym[\s!MathRoman][file:texgyre-bonum-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre] - \definefontsynonym[\s!MathRoman] [file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=bonum-math] - \definefontsynonym[\s!MathRomanBold][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,bonum-math-bold,mathextra},\s!goodies=bonum-math] + \definefontsynonym[\s!MathRoman] [file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=bonum-math] + \definefontsynonym[\s!MathRomanBold][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,bonum-math-bold,mathextra},\s!goodies=bonum-math] \stoptypescript \stoptypescriptcollection @@ -300,8 +300,8 @@ \starttypescript [\s!math][schoolbook,schola][\s!all] % \loadfontgoodies[texgyre] % \definefontsynonym[\s!MathRoman][file:texgyre-schola-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre] - \definefontsynonym[\s!MathRoman] [file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=schola-math] - \definefontsynonym[\s!MathRomanBold][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,schola-math-bold,mathextra},\s!goodies=schola-math] + \definefontsynonym[\s!MathRoman] [file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=schola-math] + \definefontsynonym[\s!MathRomanBold][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,schola-math-bold,mathextra},\s!goodies=schola-math] \stoptypescript \stoptypescriptcollection diff --git a/tex/context/fonts/mkiv/xits-math.lfg b/tex/context/fonts/mkiv/xits-math.lfg index b37ab1277..88d3a8d45 100644 --- a/tex/context/fonts/mkiv/xits-math.lfg +++ b/tex/context/fonts/mkiv/xits-math.lfg @@ -14,6 +14,7 @@ local italics = { -- [0x1D44E] = 0.99, -- a (fraction of quad) -- [0x1D44F] = 100, -- b (font points) [0x1D453] = -0.0375, -- f + -- todo: ssty 1/2 } } diff --git a/tex/context/modules/mkiv/m-punk.mkiv b/tex/context/modules/mkiv/m-punk.mkiv index 47f1a0177..9eb7411ba 100644 --- a/tex/context/modules/mkiv/m-punk.mkiv +++ b/tex/context/modules/mkiv/m-punk.mkiv @@ -17,6 +17,11 @@ %D https://www.youtube.com/watch?v=g5c2Htj8Vtw %D \stoptyping +\ifcase\contextlmtxmode\else + \writestatus{punk}{use metapost library punk instead} + \endinput +\fi + \startluacode local concat = table.concat local round = math.round diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index c1300a71b..552559e96 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-01-11 16:28 +-- merge date : 2021-01-17 21:39 do -- begin closure to overcome local limits and interference |