diff options
author | Marius <mariausol@gmail.com> | 2010-08-14 15:56:20 +0300 |
---|---|---|
committer | Marius <mariausol@gmail.com> | 2010-08-14 15:56:20 +0300 |
commit | b469b8ec1b494ab72cd462bfc539ce01440e6aaf (patch) | |
tree | 3a9c3fb8433c5f75020fef1d531bedb7c948f66c /tex/context/base | |
parent | 39e30629c15ae4a899532d84c4abea127f2847a6 (diff) | |
download | context-b469b8ec1b494ab72cd462bfc539ce01440e6aaf.tar.gz |
beta 2010.08.10 17:14
Diffstat (limited to 'tex/context/base')
142 files changed, 3668 insertions, 1672 deletions
diff --git a/tex/context/base/attr-div.lua b/tex/context/base/attr-div.lua index e618a35c1..4397936d9 100644 --- a/tex/context/base/attr-div.lua +++ b/tex/context/base/attr-div.lua @@ -14,7 +14,10 @@ local format, gmatch = string.format, string.gmatch local concat = table.concat local texsprint = tex.sprint -local report_attributes = logs.new("attributes") +local report_attributes = logs.new("attributes") +local report_colors = logs.new("colors") +local report_transparencies = logs.new("transparencies") +local report_viewerlayers = logs.new("viewerlayers") local ctxcatcodes = tex.ctxcatcodes local unsetvalue = attributes.unsetvalue @@ -70,6 +73,7 @@ colors.selector = attributes.private('colormodel') colors.default = 1 colors.main = nil colors.triggering = true +colors.supported = true storage.register("colors/values", colors.values, "colors.values") storage.register("colors/registered", colors.registered, "colors.registered") @@ -248,7 +252,7 @@ local function cmykcolor(...) cmykcolor = nodeinjections.cmykcolor return cmykco local function spotcolor(...) spotcolor = nodeinjections.spotcolor return spotcolor(...) end local function extender(colors,key) - if key == "none" then + if colors.supported and key == "none" then local d = graycolor(0) colors.none = d return d @@ -256,31 +260,33 @@ local function extender(colors,key) end local function reviver(data,n) - local v = values[n] - local d - if not v then - local gray = graycolor(0) - d = { gray, gray, gray, gray } - report_attributes("unable to revive color %s",n or "?") - else - local kind = v[1] - if kind == 2 then - local gray= graycolor(v[2]) + if colors.supported then + local v = values[n] + local d + if not v then + local gray = graycolor(0) d = { gray, gray, gray, gray } - elseif kind == 3 then - local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) - d = { rgb, gray, rgb, cmyk } - elseif kind == 4 then - local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) - d = { cmyk, gray, rgb, cmyk } - elseif kind == 5 then - local spot = spotcolor(v[10],v[11],v[12],v[13]) - -- d = { spot, gray, rgb, cmyk } - d = { spot, spot, spot, spot } + report_attributes("unable to revive color %s",n or "?") + else + local kind = colors.forcedmodel(v[1]) + if kind == 2 then + local gray= graycolor(v[2]) + d = { gray, gray, gray, gray } + elseif kind == 3 then + local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) + d = { rgb, gray, rgb, cmyk } + elseif kind == 4 then + local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9]) + d = { cmyk, gray, rgb, cmyk } + elseif kind == 5 then + local spot = spotcolor(v[10],v[11],v[12],v[13]) + -- d = { spot, gray, rgb, cmyk } + d = { spot, spot, spot, spot } + end end + data[n] = d + return d end - data[n] = d - return d end setmetatable(colors, { __index = extender }) @@ -325,8 +331,18 @@ shipouts.handle_color = nodes.install_attribute_handler { resolver = function() return colors.main end, } -function colors.enable() - tasks.enableaction("shipouts","shipouts.handle_color") +function colors.enable(value) + if value == false or not colors.supported then + tasks.disableaction("shipouts","shipouts.handle_color") + else + tasks.enableaction("shipouts","shipouts.handle_color") + end +end + +function colors.forcesupport(value) -- can move to attr-div + colors.supported = value + report_colors("color is %ssupported",value and "" or "not ") + colors.enable(value) end -- transparencies @@ -337,6 +353,7 @@ transparencies.data = transparencies.data or { } transparencies.values = transparencies.values or { } transparencies.triggering = true transparencies.attribute = attributes.private('transparency') +transparencies.supported = true storage.register("transparencies/registered", transparencies.registered, "transparencies.registered") storage.register("transparencies/values", transparencies.values, "transparencies.values") @@ -377,7 +394,7 @@ function transparencies.register(name,a,t,force) -- name is irrelevant here (can end local function extender(transparencies,key) - if key == "none" then + if colors.supported and key == "none" then local d = inject_transparency(0) transparencies.none = d return d @@ -385,16 +402,20 @@ local function extender(transparencies,key) end local function reviver(data,n) - local v = values[n] - local d - if not v then - d = inject_transparency(0) + if transparencies.supported then + local v = values[n] + local d + if not v then + d = inject_transparency(0) + else + d = inject_transparency(n) + register_transparency(n,v[1],v[2]) + end + data[n] = d + return d else - d = inject_transparency(n) - register_transparency(n,v[1],v[2]) + return "" end - data[n] = d - return d end setmetatable(transparencies, { __index = extender }) @@ -414,8 +435,18 @@ shipouts.handle_transparency = nodes.install_attribute_handler { processor = states.process, } -function transparencies.enable() - tasks.enableaction("shipouts","shipouts.handle_transparency") +function transparencies.enable(value) -- nil is enable + if value == false or not transparencies.supported then + tasks.disableaction("shipouts","shipouts.handle_transparency") + else + tasks.enableaction("shipouts","shipouts.handle_transparency") + end +end + +function transparencies.forcesupport(value) -- can move to attr-div + transparencies.supported = value + report_transparencies("transparency is %ssupported",value and "" or "not ") + transparencies.enable(value) end --- colorintents: overprint / knockout @@ -591,6 +622,8 @@ viewerlayers.registered = viewerlayers.registered or { } viewerlayers.values = viewerlayers.values or { } viewerlayers.listwise = viewerlayers.listwise or { } viewerlayers.attribute = attributes.private("viewerlayer") +viewerlayers.supported = true +viewerlayers.hasorder = true storage.register("viewerlayers/registered", viewerlayers.registered, "viewerlayers.registered") storage.register("viewerlayers/values", viewerlayers.values, "viewerlayers.values") @@ -604,7 +637,7 @@ local template = "%s" -- stacked local function extender(viewerlayers,key) - if key == "none" then + if viewerlayers.supported and key == "none" then local d = nodeinjections.stoplayer() viewerlayers.none = d return d @@ -612,13 +645,15 @@ local function extender(viewerlayers,key) end local function reviver(data,n) - local v = values[n] - if v then - local d = nodeinjections.startlayer(v) - data[n] = d - return d - else - logs.report("viewerlayers","error, unknown reference '%s'",tostring(n)) + if viewerlayers.supported then + local v = values[n] + if v then + local d = nodeinjections.startlayer(v) + data[n] = d + return d + else + logs.report("viewerlayers","error, unknown reference '%s'",tostring(n)) + end end end @@ -649,6 +684,20 @@ shipouts.handle_viewerlayer = nodes.install_attribute_handler { processor = states.stacked, } -function viewerlayers.enable() - tasks.enableaction("shipouts","shipouts.handle_viewerlayer") +function viewerlayers.enable(value) + if value == false or not viewerlayers.supported then + tasks.disableaction("shipouts","shipouts.handle_viewerlayer") + else + tasks.enableaction("shipouts","shipouts.handle_viewerlayer") + end +end + +function viewerlayers.forcesupport(value) + viewerlayers.supported = value + report_viewerlayers("viewerlayers are %ssupported",value and "" or "not ") + viewerlayers.enable(value) +end + +function viewerlayers.setfeatures(hasorder) + viewerlayers.hasorder = hasorder end diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua index 655500055..7331758ac 100644 --- a/tex/context/base/back-ini.lua +++ b/tex/context/base/back-ini.lua @@ -94,6 +94,8 @@ backends.codeinjections = { mergereferences = nothing, mergelayers = nothing, + setformat = nothing, + getformatoption = nothing, } backends.registrations = { diff --git a/tex/context/base/back-ini.mkiv b/tex/context/base/back-ini.mkiv index b7bbdb56f..db37cf61f 100644 --- a/tex/context/base/back-ini.mkiv +++ b/tex/context/base/back-ini.mkiv @@ -165,4 +165,14 @@ \unexpanded\def\setupoutput[#1]{} % will be command line switch +%D New: + +\newtoks\everysetupbackend + +\def\backendparameter#1{\csname\ifcsname\??bc#1\endcsname\??bc#1\else\s!empty\fi\endcsname} + +\def\setupbackend[#1]% + {\getparameters[\??bc][#1]% + \the\everysetupbackend} + \protect \endinput diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua index b3ab0c2a7..0cf8c8804 100644 --- a/tex/context/base/buff-ini.lua +++ b/tex/context/base/buff-ini.lua @@ -59,7 +59,6 @@ function buffers.append(name, str) data[name] = (data[name] or "") .. str end - buffers.flags.store_as_table = true -- to be sorted out: crlf + \ ; slow now @@ -314,7 +313,7 @@ end local printer = (lpeg.patterns.textline/texprint)^0 function buffers.get(name) - local b = buffers.data[name] + local b = data[name] if b then if type(b) == "table" then for i=1,#b do diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv index 59b484983..8c4e7a557 100644 --- a/tex/context/base/buff-ver.mkiv +++ b/tex/context/base/buff-ver.mkiv @@ -21,6 +21,10 @@ \ifdefined\stoplinenumbering \else \let\stoplinenumbering \relax \fi \ifdefined\setuplinenumbering\else \unexpanded\def\setuplinenumbering[#1]{} \fi +\definesystemattribute[verbatim-line] \chardef\verbatimlineattribute \dogetattributeid{verbatim-line} + +\appendtoksonce \attribute\verbatimlineattribute \attributeunsetvalue \to \everyforgetall + % D \macros % D {iflinepar} % D @@ -606,19 +610,6 @@ \def\doverbatimgoodbreak {\ifoptimizeverbatim\penalty\linepenalty\fi} -% \def\doflushverbatimline -% {\expandafter\dodoverbatimline\expandafter{\savedverbatimline}} -% \def\doverbatimbeginofline#1% linenumber (optional provided by mkiv / todo) -% {\dontleavehmode -% \strut -% \the\everyline} -% \def\doverbatimendofline -% {\par} -% \def\doverbatimemptyline -% {\strut -% \par} -% \let\handleverbatimline=\relax - % we need this hack because otherwise verbatim skips % the first line (everything after the initial command) @@ -1177,8 +1168,12 @@ \def\doverbatimendofinline {\the\everyverbatimendofinline} +\newcount\nofverbatimlines + \def\doverbatimbeginofline#1% linenumber - {\bgroup % due to pretty status + {\global\advance\nofverbatimlines\plusone + \attribute\verbatimlineattribute\nofverbatimlines + \bgroup % due to pretty status \iflinepar\else\EveryPar{}\fi \noindent % was wrong: \dontleavehmode \xdef\dokeepverbatimlinedata % hm, still needed? @@ -1196,7 +1191,8 @@ \def\doverbatimendofline {%\endverbatimline \global\lineparfalse - \obeyedline\par} + \obeyedline\par + \attribute\verbatimlineattribute\attributeunsetvalue} \def\doverbatimemptyline {\strut diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 99ac18978..38769404a 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -8696,7 +8696,7 @@ characters.data={ [0x0390]={ adobename="iotadieresistonos", category="ll", - contextname="greekiotadialytikatonos", + contextname="greekiotadialytikatonos", -- double description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS", direction="l", linebreak="al", diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua index 5c4a40bad..e61f1ce78 100644 --- a/tex/context/base/char-ini.lua +++ b/tex/context/base/char-ini.lua @@ -566,12 +566,17 @@ end function characters.uccode(n) return data[n].uccode or n end function characters.lccode(n) return data[n].lccode or n end -function characters.flush(n) +function characters.flush(n,direct) local c = data[n] if c and c.contextname then - texsprint(texcatcodes, "\\"..c.contextname) + c = "\\" .. c.contextname else - texsprint(utfchar(n)) + c = utfchar(n) + end + if direct then + return c + else + texsprint(c) end end diff --git a/tex/context/base/colo-icc.lua b/tex/context/base/colo-icc.lua new file mode 100644 index 000000000..724ff3241 --- /dev/null +++ b/tex/context/base/colo-icc.lua @@ -0,0 +1,118 @@ +if not modules then modules = { } end modules ['colo-ini'] = { + version = 1.000, + comment = "companion to colo-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local char, byte, gsub, match, format, strip = string.char, string.byte, string.gsub, string.match, string.format, string.strip +local readstring, readnumber = io.readstring, io.readnumber + +colors = colors or { } -- can also be used in mtxrun + +local R, Cs, lpegmatch = lpeg.R, lpeg.Cs, lpeg.match + +local invalid = R(char(0)..char(31)) +local cleaned = invalid^0 * Cs((1-invalid)^0) + +function colors.iccprofile(filename,verbose) + local fullname = resolvers.find_file(filename,"icc") or "" + if fullname == "" then + local locate = resolvers.finders.loc -- not in mtxrun + if locate then + fullname = locate(filename) -- could be specific to the project + end + end + if fullname == "" then + return nil, false, format("profile '%s' cannot be found",filename) + end + local f = io.open(fullname,"rb") + if not f then + return nil, false, format("profile '%s'cannot be loaded",fullname) + end + local header = { + size = readnumber(f,4), + cmmtype = readnumber(f,4), + version = readnumber(f,4), + deviceclass = strip(readstring(f,4)), + colorspace = strip(readstring(f,4)), + connectionspace = strip(readstring(f,4)), + datetime = { + year = readnumber(f,2), + month = readnumber(f,2), + day = readnumber(f,2), + hour = readnumber(f,2), + minutes = readnumber(f,2), + seconds = readnumber(f,2), + }, + filesignature = strip(readstring(f,4)), + platformsignature = strip(readstring(f,4)), + options = readnumber(f,4), + devicemanufacturer = strip(readstring(f,4)), + devicemodel = strip(readstring(f,4)), + deviceattributes = readnumber(f,4), + renderingintent = readnumber(f,4), + illuminantxyz = { + x = readnumber(f,4), + y = readnumber(f,4), + z = readnumber(f,4), + }, + profilecreator = readnumber(f,4), + id = strip(readstring(f,16)), + } + local tags = { } + for i=1,readnumber(f,128,4) do + tags[readstring(f,4)] = { + offset = readnumber(f,4), + length = readnumber(f,4), + } + end + local o = header.options + header.options = + o == 0 and "embedded" or + o == 1 and "dependent" or "unknown" + local d = header.deviceattributes + header.deviceattributes = { + [number.hasbit(d,1) and "transparency" or "reflective"] = true, + [number.hasbit(d,2) and "mate" or "glossy" ] = true, + [number.hasbit(d,3) and "negative" or "positive" ] = true, + [number.hasbit(d,4) and "bw" or "color" ] = true, + } + local r = header.renderingintent + header.renderingintent = + r == 0 and "perceptual" or + r == 1 and "relative" or + r == 2 and "saturation" or + r == 3 and "absolute" or "unknown" + for tag, spec in next, tags do + if tag then + local offset, length = spec.offset, spec.length + local kind = readstring(f,offset,4) + if kind == "text" or kind == "desc" then + local str = readstring(f,length-4) + tags[tag] = { + data = str, + cleaned = lpegmatch(cleaned,str), + } + else + if verbose then + logs.simple("ignoring tag '%s' or type '%s' in profile '%s'",tag,kind,fullname) + end + tags[tag] = nil + end + end + end + f:close() + local profile = { + filename = filename, + fullname = fullname, + header = header, + tags = tags, + } + return profile, true, format("profile '%s' loaded",fullname) +end + +--~ local profile, error, message = colors.iccprofile("ussheetfedcoated.icc") +--~ print(error,message) +--~ table.print(profile) diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua index 30b18983d..28ce4ac6a 100644 --- a/tex/context/base/colo-ini.lua +++ b/tex/context/base/colo-ini.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['colo-ini'] = { license = "see context related readme files" } -local type = type +local type, tonumber = type, tonumber local concat = table.concat local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find local texsprint = tex.sprint @@ -14,6 +14,8 @@ local ctxcatcodes = tex.ctxcatcodes local trace_define = false trackers.register("colors.define",function(v) trace_define = v end) +local report_colors = logs.new("colors") + local settings_to_hash_strict = aux.settings_to_hash_strict colors = colors or { } @@ -133,6 +135,60 @@ local transparent = { exclusion = 12, } +-- backend driven limitations + +colors.supported = true -- always true +transparencies.supported = true + +local gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = true, true, true, true, true, false + +function colors.forcesupport(gray,rgb,cmyk,spot,multichannel) -- pdfx driven + gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = gray, rgb, cmyk, spot, multichannel, true + report_colors("supported models: gray=%s, rgb=%s, cmyk=%s, spot=%s", -- multichannel=%s + tostring(gray), tostring(rgb), tostring(cmyk), tostring(spot)) -- tostring(multichannel) +end + +local function forcedmodel(model) -- delayed till the backend but mp directly + if not forced then + return model + elseif model == 2 then -- gray + if gray_okay then + -- okay + elseif cmyk_okay then + return 4 + elseif rgb_okay then + return 3 + end + elseif model == 3 then -- rgb + if rgb_okay then + -- okay + elseif cmyk_okay then + return 4 + elseif gray_okay then + return 2 + end + elseif model == 4 then -- cmyk + if cmyk_okay then + -- okay + elseif rgb_okay then + return 3 + elseif gray_okay then + return 2 + end + elseif model == 5 then -- spot + if cmyk_okay then + return 4 + elseif rgb_okay then + return 3 + elseif gray_okay then + return 2 + end + end + return model +end + +colors.forcedmodel = forcedmodel + -- By coupling we are downward compatible. When we decouple we need to do more tricky -- housekeeping (e.g. persist color independent transparencies when color bound ones -- are nil.) @@ -319,13 +375,14 @@ function colors.definemultitonecolor(name,multispec,colorspec,selfspec) end end -function colors.mp(model,ca,ta,default) - local cv = colors.value(ca) -- faster when direct colors.values[ca] +function colors.mp(model,ca,ta,default) -- will move to mlib-col + local cv = colors.supported and colors.value(ca) -- faster when direct colors.values[ca] if cv then - local tv = transparencies.value(ta) + local tv = transparencies.supported and transparencies.value(ta) if model == 1 then model = cv[1] end + model = forcedmodel(model) if tv then if model == 2 then return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5]) diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv index 1bceb5aa7..0d1dd50e5 100644 --- a/tex/context/base/colo-ini.mkiv +++ b/tex/context/base/colo-ini.mkiv @@ -20,6 +20,7 @@ %D different approach, this module only implements a few generic mechanisms. \registerctxluafile{colo-ini}{1.000} +\registerctxluafile{colo-icc}{1.000} \registerctxluafile{lpdf-col}{1.000} \unprotect diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index cae797270..b59c65679 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2010.07.30 11:35} +\newcontextversion{2010.08.10 17:14} %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/context.mkiv b/tex/context/base/context.mkiv index 13e091ea8..9590eb652 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -70,6 +70,7 @@ \loadcorefile{mult-def} \loadmarkfile{mult-chk} \loadmarkfile{mult-cld} +\loadmarkfile{mult-aux} \loadmarkfile{luat-ini} diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index 4abee1332..5e3324eb7 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2010.07.30 11:35} +\edef\contextversion{2010.08.10 17:14} %D For those who want to use this: diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua index f8f54e9e7..257de625b 100644 --- a/tex/context/base/core-con.lua +++ b/tex/context/base/core-con.lua @@ -23,6 +23,23 @@ local tonumber, tostring = tonumber, tostring local ctxcatcodes = tex.ctxcatcodes +local function flush(...) + texsprint(ctxcatcodes,...) +end + +function converters.convert(method,n,direct) + local method = converters[method] + if method then + return method(n,direct) + else + return direct and n or flush(n) + end +end + +function converters.numberst(n,direct) + return direct and n or flush(n) +end + converters = converters or { } languages = languages or { } @@ -123,24 +140,61 @@ counters['kr-c'] = counters['korean-circle'] local fallback = utf.byte('0') -local function chr(n,m) - if n > 0 and n < 27 then - texsprint(utfchar(n+m)) - end +local function chr(n,m,direct) + local s = (n > 0 and n < 27 and utfchar(n+m)) or "" + if direct then return s else flush(s) end end -local function chrs(n,m) + +--~ local function chrs(n,m,direct) +--~ if n > 26 then +--~ chrs(floor((n-1)/26),m) +--~ n = (n-1)%26 + 1 +--~ end +--~ flush(utfchar(n+m)) +--~ end + +local function chrs(n,m,direct,t) + if not t then + t = { } + end if n > 26 then - chrs(floor((n-1)/26),m) + chrs(floor((n-1)/26),m,direct,t) n = (n-1)%26 + 1 end - texsprint(utfchar(n+m)) + t[#t+1] = utfchar(n+m) + if n <= 26 then + if direct then + return concat(t) + else + flush(concat(t)) + end + end end -local function maxchrs(n,m,cmd) + +--~ local function maxchrs(n,m,cmd,direct) +--~ if n > m then +--~ maxchrs(floor((n-1)/m),m,cmd) +--~ n = (n-1)%m + 1 +--~ end +--~ flush(format("%s{%s}",cmd,n)) +--~ end + +local function maxchrs(n,m,cmd,direct,t) -- direct is not ok + if not t then + t = { } + end if n > m then maxchrs(floor((n-1)/m),m,cmd) n = (n-1)%m + 1 end - texsprint(ctxcatcodes, format("%s{%s}",cmd,n)) + t[#t+1] = format("%s{%s}",cmd,n) + if n <= m then + if direct then + return concat(t) + else + flush(concat(t)) + end + end end converters.chr = chr @@ -158,7 +212,7 @@ converters.maxchrs = maxchrs --~ n = (n-1)%max+1 --~ end --~ n = chr(n,mapping) ---~ texsprint(ctxcatcodes,escapes[n] or utfchar(n)) +--~ flush(escapes[n] or utfchar(n)) --~ end --~ local lccodes, uccodes = characters.lccode, characters.uccode @@ -183,35 +237,52 @@ converters.maxchrs = maxchrs --~ do_alphabetic(n,counters[code] or counters['**'],uppercased) --~ end --- +local flushcharacter = characters and characters.flush or function(s) return utfchar(s) end +local lowercharacter = characters and characters.lccode or function(s) return s end +local uppercharacter = characters and characters.uccode or function(s) return s end -local function do_alphabetic(n,mapping,mapper) - local chr = mapper(mapping[n] or fallback) +local function do_alphabetic(n,mapping,mapper,direct,verbose,t) + if not t then + t = { } + end + local chr = mapping[n] or fallback + if mapper then + chr = mapper(chr) + end local max = #mapping if n > max then - do_alphabetic(floor((n-1)/max),mapping,mapper) + do_alphabetic(floor((n-1)/max),mapping,mapper,direct,verbose,t) n = (n-1)%max+1 end - characters.flush(chr) + if verbose or type(chr) ~= "number" then + t[#t+1] = chr + else + t[#t+1] = utfchar(chr) -- flushcharacter(chr,true) -- force direct here; can't we just use utfchar(chr) nowadays? + end + if n <= max then + if direct then + return concat(t) + else + flush(concat(t)) + end + end end -function converters.alphabetic(n,code) - do_alphabetic(n,counters[code] or counters['**'],characters.lccode) +function converters.alphabetic(n,code,direct) + return do_alphabetic(n,counters[code] or counters['**'],lowercharacter,direct) end - -function converters.Alphabetic(n,code) - do_alphabetic(n,counters[code] or counters['**'],characters.uccode) +function converters.Alphabetic(n,code,direct) + return do_alphabetic(n,counters[code] or counters['**'],uppercharacter,direct) end --- - -function converters.character (n) chr (n,96) end -function converters.Character (n) chr (n,64) end -function converters.characters(n) chrs(n,96) end -function converters.Characters(n) chrs(n,64) end +function converters.character (n,direct) return chr (n,96,direct) end +function converters.Character (n,direct) return chr (n,64,direct) end +function converters.characters(n,direct) return chrs(n,96,direct) end +function converters.Characters(n,direct) return chrs(n,64,direct) end -function converters.weekday(day,month,year) - texsprint(date("%w",time{year=year,month=month,day=day})+1) +function converters.weekday(day,month,year,direct) + local s = date("%w",time{year=year,month=month,day=day}) + 1 + if direct then return s else flush(s) end end function converters.isleapyear(year) @@ -219,7 +290,8 @@ function converters.isleapyear(year) end function converters.leapyear(year) - if converters.isleapyear(year) then texsprint(1) else texsprint(0) end + local s = converters.isleapyear(year) and 1 or 0 + if direct then return s else flush(s) end end local days = { @@ -227,16 +299,19 @@ local days = { [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } } -function converters.nofdays(year,month) - texsprint(days[converters.isleapyear(year)][month]) +function converters.nofdays(year,month,direct) + local s = days[converters.isleapyear(year)][month] + if direct then return s else flush(s) end end -function converters.year () texsprint(date("%Y")) end -function converters.month () texsprint(date("%m")) end -function converters.hour () texsprint(date("%H")) end -function converters.minute () texsprint(date("%M")) end -function converters.second () texsprint(date("%S")) end -function converters.textime() texsprint(tonumber(date("%H"))*60+tonumber(date("%M"))) end +function converters.year (direct) local s = date("%Y") if direct then return s else flush(s) end end +function converters.year (direct) local s = date("%Y") if direct then return s else flush(s) end end +function converters.month (direct) local s = date("%m") if direct then return s else flush(s) end end +function converters.hour (direct) local s = date("%H") if direct then return s else flush(s) end end +function converters.minute (direct) local s = date("%M") if direct then return s else flush(s) end end +function converters.second (direct) local s = date("%S") if direct then return s else flush(s) end end +function converters.textime(direct) local s = tonumber(date("%H")) * 60 + tonumber(date("%M")) + if direct then return s else flush(s) end end local roman = { { [0] = '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX' }, @@ -248,13 +323,12 @@ local function toroman(n) if n >= 4000 then return toroman(floor(n/1000)) .. " " .. toroman(n%1000) else - return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. - roman[2][floor((n%100)/10)] .. roman[1][floor((n% 10)/1)] + return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n% 10)/1)] end end -function converters.romannumerals(n) return texsprint(lower(toroman(n))) end -function converters.Romannumerals(n) return texsprint( toroman(n) ) end +function converters.romannumerals(n,direct) local s = lower(toroman(n)) if direct then return s else flush(s) end end +function converters.Romannumerals(n,direct) local s = toroman(n) if direct then return s else flush(s) end end converters.toroman = toroman @@ -304,8 +378,8 @@ function converters.toabjad(n,what) end end -function converters.abjadnumerals (n) return texsprint(converters.toabjad(n,false)) end -function converters.abjadnodotnumerals(n) return texsprint(converters.toabjad(n,true)) end +function converters.abjadnumerals (n,direct) local s = converters.toabjad(n,false) if direct then return s else flush(s) end end +function converters.abjadnodotnumerals(n,direct) local s = converters.toabjad(n,true ) if direct then return s else flush(s) end end local vector = { normal = { @@ -363,61 +437,6 @@ local vector = { } } ---~ function tochinese(n,name) -- normal, caps, all ---~ local result = { } ---~ local vector = vector[name] or vector.normal ---~ while true do ---~ if n == 0 then ---~ break ---~ elseif n >= 100000000 then ---~ local m = floor(n/100000000) ---~ if m > 1 then result[#result+1] = tochinese(m) end ---~ result[#result+1] = vector[100000000] ---~ n = n % 100000000 ---~ elseif n >= 10000000 then ---~ result[#result+1] = tochinese(floor(n/10000)) ---~ result[#result+1] = vector[10000] ---~ n = n % 10000 ---~ elseif n >= 1000000 then ---~ result[#result+1] = tochinese(floor(n/10000)) ---~ result[#result+1] = vector[10000] ---~ n = n % 10000 ---~ elseif n >= 100000 then ---~ result[#result+1] = tochinese(floor(n/10000)) ---~ result[#result+1] = vector[10000] ---~ n = n % 10000 ---~ elseif n >= 10000 then ---~ local m = floor(n/10000) ---~ if m > 1 then result[#result+1] = vector[m] end ---~ result[#result+1] = vector[10000] ---~ n = n % 10000 ---~ elseif n >= 1000 then ---~ local m = floor(n/1000) ---~ if m > 1 then result[#result+1] = vector[m] end ---~ result[#result+1] = vector[1000] ---~ n = n % 1000 ---~ elseif n >= 100 then ---~ local m = floor(n/100) ---~ if m > 1 then result[#result+1] = vector[m] end ---~ result[#result+1] = vector[100] ---~ n = n % 100 ---~ elseif n >= 10 then ---~ local m = floor(n/10) ---~ if vector[m*10] then ---~ result[#result+1] = vector[m*10] ---~ else ---~ result[#result+1] = vector[m] ---~ result[#result+1] = vector[10] ---~ end ---~ n = n % 10 ---~ else ---~ result[#result+1] = vector[n] ---~ break ---~ end ---~ end ---~ return concat(result) ---~ end - local function tochinese(n,name) -- normal, caps, all -- improved version by Li Yanrui local result = { } @@ -500,9 +519,9 @@ end --~ print(v,tochinese(v),tochinese(v,"all"),tochinese(v,"cap")) --~ end -function converters.chinesenumerals (n) return texsprint(tochinese(n,"normal")) end -function converters.chinesecapnumerals(n) return texsprint(tochinese(n,"cap" )) end -function converters.chineseallnumerals(n) return texsprint(tochinese(n,"all" )) end +function converters.chinesenumerals (n) local s = tochinese(n,"normal") if direct then return s else flush(s) end end +function converters.chinesecapnumerals(n) local s = tochinese(n,"cap" ) if direct then return s else flush(s) end end +function converters.chineseallnumerals(n) local s = tochinese(n,"all" ) if direct then return s else flush(s) end end --~ Well, since the one asking for this didn't test it the following code is not --~ enabled. @@ -603,3 +622,31 @@ function converters.chineseallnumerals(n) return texsprint(tochinese(n,"all" ) --~ --~ print(gregorian_to_jalali(2009,02,24)) --~ print(jalali_to_gregorian(1387,12,06)) + +converters.sequences = converters.sequences or { } + +storage.register("converters/sequences", converters.sequences, "converters.sequences") + +local sequences = converters.sequences + +function converters.define(name,set) + sequences[name] = aux.settings_to_array(set) +end + +function converters.convert(method,n,direct) -- todo: language + local converter = converters[method] + if converter then + return converter(n,direct) + else + local lowermethod = lower(method) + local linguistic = counters[lowermethod] + local sequence = sequences[method] + if linguistic then + return do_alphabetic(n,linguistic,lowermethod == method and lowercharacter or uppercharacter,direct,false) + elseif sequence then + return do_alphabetic(n,sequence,false,direct,true) + else + return direct and n or flush(n) + end + end +end diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv index 2d2e5d5d7..364372a46 100644 --- a/tex/context/base/core-con.mkiv +++ b/tex/context/base/core-con.mkiv @@ -149,8 +149,8 @@ %D %D Why should we only honour the romans, and not the greek? -\let\greeknumerals\gobbleoneargument -\let\Greeknumerals\gobbleoneargument +% \let\greeknumerals\gobbleoneargument +% \let\Greeknumerals\gobbleoneargument %D \macros %D {oldstylenumerals,oldstyleromannumerals} @@ -586,83 +586,91 @@ %D \defineconversion [en] [whatever] [\something] %D \stoptyping -% \def\dodefineconversion[#1][#2]% -% {\ConvertConstantAfter\doifinstringelse{,}{#2} -% {\scratchcounter=0 +% we can consider conversions to be global in which case we can +% delegate to lua + +% \unexpanded\def\defineconversion +% {\dotripleempty\dodefineconversion} +% +% \def\dodefineconversion[#1][#2][#3]% +% {\ifthirdargument +% \dododefineconversion[#1][#2][#3]% +% \else +% \dododefineconversion[][#1][#2]% +% \fi} +% +% \def\dododefineconversion[#1][#2][#3]% +% {\ConvertConstantAfter\doifinstringelse{,}{#3} +% {\scratchcounter\zerocount % \def\docommand##1% -% {\advance\scratchcounter 1 -% \setvalue{\??cv#1\the\scratchcounter}{##1}}% -% \processcommalist[#2]\docommand -% \setvalue{\??cv#1}##1{\csname\??cv#1##1\endcsname}} -% {\setvalue{\??cv#1}{#2}}} +% {\advance\scratchcounter \plusone +% \setvalue{\??cv#1#2\the\scratchcounter}{##1}}% +% \processcommalist[#3]\docommand +% \setevalue{\??cv#1#2}##1% +% {\noexpand\docheckedconversion{#1#2}{\the\scratchcounter}{##1}}} +% {\setvalue{\??cv#1#2}{#3}}} +% +% \def\docheckedconversion#1#2#3% class maxnumber number +% {\executeifdefined{\??cv#1#3}\unknown} +% +% %D When Gerben reported problems with footnote numbering per page, +% %D Taco came with the following wrap around solution. So, let's +% %D overload the checked conversion macro % -% \unexpanded\def\defineconversion% -% {\dodoubleargument\dodefineconversion} +% %D Taco's modulo code is implemented in the system module +% %D \type {syst-con}. +% +% \def\docheckedconversion#1#2#3% class maxnumber number +% {\executeifdefined{\??cv#1\modulatednumber{#2}{#3}}\unknown} \unexpanded\def\defineconversion {\dotripleempty\dodefineconversion} -\def\dodefineconversion[#1][#2][#3]% +\def\dodefineconversion[#1][#2][#3]% from now on global (maybe local again some day) {\ifthirdargument - \dododefineconversion[#1][#2][#3]% + \dododefineconversion{#1#2}{#1:#2}{#3}% \else - \dododefineconversion[][#1][#2]% + \dododefineconversion{#1}{#1}{#2}% \fi} -%D \starttyping -%D \def\dododefineconversion[#1][#2][#3]% -%D {\ConvertConstantAfter\doifinstringelse{,}{#3} -%D {\scratchcounter\zerocount -%D \def\docommand##1% -%D {\advance\scratchcounter \plusone -%D \setvalue{\??cv#1#2\the\scratchcounter}{##1}}% -%D \processcommalist[#3]\docommand -%D \setvalue{\??cv#1#2}##1{\executeifdefined{\??cv#1#2##1}\unknown}} % catch out-of-range numbers -%D {\setvalue{\??cv#1#2}{#3}}} -%D \stoptyping - -%D This approach has the disadvantage that when you run out of -%D symbols you get unknown results. The following implementation -%D permits overloading of the converter: - -\def\dododefineconversion[#1][#2][#3]% +\def\dododefineconversion#1#2#3% {\ConvertConstantAfter\doifinstringelse{,}{#3} - {\scratchcounter\zerocount - \def\docommand##1% - {\advance\scratchcounter \plusone - \setvalue{\??cv#1#2\the\scratchcounter}{##1}}% - \processcommalist[#3]\docommand - \setevalue{\??cv#1#2}##1% - {\noexpand\docheckedconversion{#1#2}{\the\scratchcounter}{##1}}} - {\setvalue{\??cv#1#2}{#3}}} - -\def\docheckedconversion#1#2#3% class maxnumber number - {\executeifdefined{\??cv#1#3}\unknown} - -%D When Gerben reported problems with footnote numbering per page, -%D Taco came with the following wrap around solution. So, let's -%D overload the checked conversion macro: + {\ctxlua{converters.define("#2",\!!bs\detokenize{#3}\!!es)}% + \setgvalue{\??cv#1}{\docheckedconversion{#2}}} + {\setgvalue{\??cv#1}{#3}}} -\def\docheckedconversion#1#2#3% class maxnumber number - {\executeifdefined{\??cv#1\modulatednumber{#2}{#3}}\unknown} - -%D Taco's modulo code is implemented in the system module -%D \type {syst-con}. +\def\docheckedconversion#1#2% + {\ctxlua{converters.convert("#1",#2)}} %D If a conversion is just a font switch then we need to make sure %D that the number is indeed end up as number in the input, so we %D need to handle the second argument. +% \def\convertnumber#1#2% +% {\csname\??cv +% \ifcsname\??cv\currentlanguage#1\endcsname +% \currentlanguage#1% +% \else\ifcsname\??cv#1\endcsname +% #1% +% \else +% \s!default +% \fi\fi +% \endcsname{\number#2}} + \def\convertnumber#1#2% - {\csname\??cv + {\csname\??cv % we want a fully expandable (no if interference) \ifcsname\??cv\currentlanguage#1\endcsname \currentlanguage#1% + \@EA\firstoftwoarguments % dirty, gobble {#1} \else\ifcsname\??cv#1\endcsname #1% + \@EAEAEA\firstoftwoarguments % dirty, gobble {#1} \else - \s!default + ->\s!default \fi\fi - \endcsname{\number#2}} + \endcsname{#1}{\number#2}} + +\letvalue{\??cv->\s!default}\docheckedconversion \def\doifconversiondefinedelse#1% {\ifcsname\??cv\currentlanguage#1\endcsname @@ -762,9 +770,6 @@ \defineconversion [g] [\greeknumerals] \defineconversion [G] [\Greeknumerals] -\defineconversion [arabicnumerals] [\arabicnumerals] -\defineconversion [persiannumerals] [\persiannumerals] - \defineconversion [abjadnumerals] [\abjadnumerals] \defineconversion [abjadnodotnumerals] [\adjadnodotnumerals] \defineconversion [abjadnaivenumerals] [\adjadnaivenumerals] diff --git a/tex/context/base/core-ctx.mkiv b/tex/context/base/core-ctx.mkiv index 9bf456952..56d17ec88 100644 --- a/tex/context/base/core-ctx.mkiv +++ b/tex/context/base/core-ctx.mkiv @@ -23,6 +23,6 @@ % \prependtoks\loadctxpreplist\to\everyjob -\appendtoks\loadctxpreplist\to\everystarttext +\appendtoks\loadctxpreplist\to\everystarttext % maybe too late but don't change it now \protect \endinput diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua index f99cb47f5..f3997b989 100644 --- a/tex/context/base/data-env.lua +++ b/tex/context/base/data-env.lua @@ -31,6 +31,7 @@ formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', ' formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' } formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' } formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' } +formats['icc'] = 'ICCPROFILES' suffixes['icc'] = { 'icc' } formats['texmfscripts'] = 'TEXMFSCRIPTS' suffixes['texmfscripts'] = { 'rb', 'pl', 'py' } formats['lua'] = 'LUAINPUTS' suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' } formats['lib'] = 'CLUAINPUTS' suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' } @@ -46,6 +47,7 @@ alternatives['truetype fonts'] = 'ttf' alternatives['truetype collections'] = 'ttc' alternatives['truetype dictionary'] = 'dfont' alternatives['type1 fonts'] = 'pfb' +alternatives['icc profiles'] = 'icc' --[[ldx-- <p>If you wondered about some of the previous mappings, how about diff --git a/tex/context/base/enco-agr.mkii b/tex/context/base/enco-agr.mkii index cfd86dfd3..1dbb9b577 100644 --- a/tex/context/base/enco-agr.mkii +++ b/tex/context/base/enco-agr.mkii @@ -16,6 +16,8 @@ \definecasemaps 87 to 90 lc +32 uc 0 \definecasemaps 91 to 255 lc 0 uc 0 + \definecaseself 4 % apostrofe + \stopmapping \startencoding[agr] diff --git a/tex/context/base/enco-ans.mkii b/tex/context/base/enco-ans.mkii index 7a48b5b55..88baf0ad0 100644 --- a/tex/context/base/enco-ans.mkii +++ b/tex/context/base/enco-ans.mkii @@ -40,7 +40,7 @@ % \definecaseself 129 % quotesingle % \definecaseself 130 % quotesinglebase % \definecaseself 145 % quoteleft -% \definecaseself 146 % quoteright +\definecaseself 146 % quoteright \stopmapping diff --git a/tex/context/base/enco-ec.mkii b/tex/context/base/enco-ec.mkii index 1ac41cadf..f0964897f 100644 --- a/tex/context/base/enco-ec.mkii +++ b/tex/context/base/enco-ec.mkii @@ -56,7 +56,7 @@ % \definecaseself 39 % quotesingle % \definecaseself 13 % quotesinglebase % \definecaseself 96 % quoteleft -% \definecaseself 39 % quoteright +\definecaseself 39 % quoteright %D So far for the mapping. diff --git a/tex/context/base/enco-qx.mkii b/tex/context/base/enco-qx.mkii index 407d60bd7..798a18249 100644 --- a/tex/context/base/enco-qx.mkii +++ b/tex/context/base/enco-qx.mkii @@ -75,6 +75,8 @@ \definecasemaps 217 to 222 lc +32 uc 0 \definecasemaps 249 to 254 lc 0 uc -32 +\definecaseself 39 % quoteright + \stopmapping \startencoding[qx] diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua index 072b3e59f..75b3cddef 100644 --- a/tex/context/base/font-afm.lua +++ b/tex/context/base/font-afm.lua @@ -480,7 +480,8 @@ function afm.copy_to_tfm(data) local metadata, luatex = data.metadata, data.luatex local unicodes, indices = luatex.unicodes, luatex.indices local characters, parameters, descriptions = { }, { }, { } - -- todo : merge into tfm + local mode = data.mode or "base" + -- todo : merge into tfm for u, i in next, indices do local d = glyphs[i] characters[u] = { } @@ -561,6 +562,7 @@ function afm.copy_to_tfm(data) unicodes = unicodes, luatex = luatex, encodingbytes = 2, + mode = mode, filename = filename, fontname = fontname, fullname = fullname, @@ -602,7 +604,7 @@ function afm.set_features(tfmdata) local afmdata = shared.afmdata local features = shared.features if features and next(features) then - local mode = tfmdata.mode or fonts.mode + local mode = tfmdata.mode or features.mode or "base" local initializers = fonts.initializers local fi = initializers[mode] local fiafm = fi and fi.afm @@ -623,7 +625,7 @@ function afm.set_features(tfmdata) report_afm("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown') end fiafm[f](tfmdata,value) - mode = tfmdata.mode or fonts.mode + mode = tfmdata.mode or features.mode or "base" fiafm = initializers[mode].afm end end diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index 5e4d598f1..a6945e39d 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -18,8 +18,12 @@ local round = math.round local ctxcatcodes = tex.ctxcatcodes local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) +local trace_usage = false trackers.register("fonts.usage", function(v) trace_usage = v end) +local trace_mapfiles = false trackers.register("fonts.mapfiles", function(v) trace_mapfiles = v end) -local report_define = logs.new("define fonts") +local report_define = logs.new("define fonts") +local report_usage = logs.new("fonts usage") +local report_mapfiles = logs.new("mapfiles") local tfm = fonts.tfm local define = fonts.define @@ -37,6 +41,9 @@ local merged = specify.context_merged local synonyms = specify.synonyms local triggers = fonts.triggers +-- Beware, number can be shared between redefind features but as it is +-- applied only for special cases it probably doesn't matter. + --[[ldx-- <p>So far we haven't really dealt with features (or whatever we want to pass along with the font definition. We distinguish the following @@ -113,7 +120,8 @@ local function preset_context(name,parent,features) -- currently otf only if v then t[k] = v end end -- needed for dynamic features - local number = (setups[name] and setups[name].number) or 0 + -- maybe number should always be renewed as we can redefine features + local number = (setups[name] and setups[name].number) or 0 -- hm, numbers[name] if number == 0 then number = #numbers + 1 numbers[number] = name @@ -233,6 +241,7 @@ function fonts.withset(name,what) end tex_attribute[0] = done end + function fonts.withfnt(name,what) local font = current_font() local hash = font .. "*" .. name .. "*" .. what @@ -248,18 +257,59 @@ function specify.show_context(name) return setups[name] or setups[numbers[name]] or setups[numbers[tonumber(name)]] or { } end -local function split_context(features) +-- todo: support a,b,c + +local function split_context(features) -- preset_context creates dummy here return setups[features] or (preset_context(features,"","") and setups[features]) end +--~ local splitter = lpeg.splitat("=") + +--~ local function split_context(features) +--~ local setup = setups[features] +--~ if setup then +--~ return setup +--~ elseif find(features,",") then +--~ -- This is not that efficient but handy anyway for quick and dirty tests +--~ -- beware, due to the way of caching setups you can get the wrong results +--~ -- when components change. A safeguard is to nil the cache. +--~ local merge = nil +--~ for feature in gmatch(features,"[^, ]+") do +--~ if find(feature,"=") then +--~ local k, v = lpegmatch(splitter,feature) +--~ if k and v then +--~ if not merge then +--~ merge = { k = v } +--~ else +--~ merge[k] = v +--~ end +--~ end +--~ else +--~ local s = setups[feature] +--~ if not s then +--~ -- skip +--~ elseif not merge then +--~ merge = s +--~ else +--~ for k, v in next, s do +--~ merge[k] = v +--~ end +--~ end +--~ end +--~ end +--~ setup = merge and preset_context(features,"",merge) and setups[features] +--~ -- actually we have to nil setups[features] in order to permit redefinitions +--~ setups[features] = nil +--~ end +--~ return setup or (preset_context(features,"","") and setups[features]) -- creates dummy +--~ end + specify.split_context = split_context function specify.context_tostring(name,kind,separator,yes,no,strict,omit) -- not used return aux.hash_to_string(table.merged(fonts[kind].features.default or {},setups[name] or {}),separator,yes,no,strict,omit) end -local splitter = lpeg.splitat(",") - function specify.starred(features) -- no longer fallbacks here local detail = features.detail if detail and detail ~= "" then @@ -396,7 +446,7 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal report_define("defining %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,id,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks) end -- resolved (when designsize is used): - texsprint(ctxcatcodes,format("\\def\\somefontsize{%isp}",tfmdata.size)) + texsprint(ctxcatcodes,format("\\def\\somefontsize{%isp}",tfmdata.size or 655360)) --~ if specification.fallbacks then --~ fonts.collections.prepare(specification.fallbacks) --~ end @@ -511,6 +561,9 @@ local loaded = { -- prevent loading (happens in cont-sys files) function fonts.map.loadfile(name) name = file.addsuffix(name,"map") if not loaded[name] then + if trace_mapfiles then + report_mapfiles("loading map file '%s'",name) + end pdf.mapfile(name) loaded[name] = true end @@ -526,6 +579,9 @@ function fonts.map.loadline(how,line) how = "= " .. line end if not loaded[how] then + if trace_mapfiles then + report_mapfiles("processing map line '%s'",line) + end pdf.mapline(how) loaded[how] = true end @@ -611,3 +667,57 @@ function fonts.show_font_parameters() end end +function fonts.report_defined_fonts() + if trace_usage then + local t = { } + for id, data in table.sortedhash(fonts.ids) do + t[#t+1] = { + format("%03i",id), + format("%09i",data.size or 0), + data.type or "real", + (data.mode or "base") .. "mode", + data.auto_expand and "expanded" or "", + data.auto_protrude and "protruded" or "", + data.has_math and "math" or "", + data.extend_factor and "extended" or "", + data.slant_factor and "slanted" or "", + data.name or "", + data.psname or "", + data.fullname or "", + data.hash or "", + } + end + aux.formatcolumns(t," ") + report_usage() + report_usage("defined fonts:") + report_usage() + for k=1,#t do + report_usage(t[k]) + end + end +end + +luatex.register_stop_actions(fonts.report_defined_fonts) + +function fonts.report_used_features() + -- numbers, setups, merged + if trace_usage then + local t = { } + for i=1,#numbers do + local name = numbers[i] + local setup = setups[name] + local n = setup.number + setup.number = nil -- we have no reason to show this + t[#t+1] = { i, name, table.sequenced(setup,false,true) } -- simple mode + setup.number = n -- restore it (normally not needed as we're done anyway) + end + aux.formatcolumns(t," ") + report_usage() + report_usage("defined featuresets:") + report_usage() + for k=1,#t do + report_usage(t[k]) + end + end +end +luatex.register_stop_actions(fonts.report_used_features) diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index ea5b69a6b..e3c7d934a 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -559,7 +559,7 @@ function define.register(fontdata,id) end fonts.identifiers[id] = fontdata fonts.characters [id] = fontdata.characters - fonts.quads [id] = fontdata.parameters.quad + fonts.quads [id] = fontdata.parameters and fontdata.parameters.quad -- todo: extra functions, e.g. setdigitwidth etc in list tfm.internalized[hash] = id end @@ -637,7 +637,6 @@ function define.read(specification,size,id) -- id can be optional, name can alre fontdata.encodingname or "unicode", fontdata.fullname or "?", file.basename(fontdata.filename or "?")) - end statistics.stoptiming(fonts) return fontdata diff --git a/tex/context/base/font-enh.lua b/tex/context/base/font-enh.lua index 137044f5b..31f2b2387 100644 --- a/tex/context/base/font-enh.lua +++ b/tex/context/base/font-enh.lua @@ -68,7 +68,7 @@ function tfm.set_features(tfmdata) -- local tfmdata = shared.tfmdata local features = shared.features if features and next(features) then - local mode = tfmdata.mode or fonts.mode + local mode = tfmdata.mode or features.mode or "base" local fi = fonts.initializers[mode] if fi and fi.tfm then local function initialize(list) -- using tex lig and kerning @@ -81,7 +81,7 @@ function tfm.set_features(tfmdata) report_define("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown') end fi.tfm[f](tfmdata,value) - mode = tfmdata.mode or fonts.mode + mode = tfmdata.mode or features.mode or "base" fi = fonts.initializers[mode] end end diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua index f0d52974a..79a1417d3 100644 --- a/tex/context/base/font-gds.lua +++ b/tex/context/base/font-gds.lua @@ -90,21 +90,21 @@ end -- featuresets -local function flattened(t,tt) +local function flattened_features(t,tt) -- first set value dominates local tt = tt or { } for i=1,#t do local ti = t[i] if type(ti) == "table" then - flattened(ti,tt) + flattened_features(ti,tt) elseif tt[ti] == nil then tt[ti] = true end end for k, v in next, t do - if type(k) ~= "number" then + if type(k) ~= "number" then -- not tonumber(k) if type(v) == "table" then - flattened(v,tt) + flattened_features(v,tt) elseif tt[k] == nil then tt[k] = v end @@ -113,11 +113,11 @@ local function flattened(t,tt) return tt end -fonts.flattened_features = flattened +fonts.flattened_features = flattened_features function fonts.goodies.prepare_features(goodies,name,set) if set then - local ff = fonts.flattened_features(set) + local ff = flattened_features(set) local fullname = goodies.name .. "::" .. name local n, s = preset_context(fullname,"",ff) goodies.featuresets[name] = s -- set diff --git a/tex/context/base/font-ini.lua b/tex/context/base/font-ini.lua index 94522130c..290d031f9 100644 --- a/tex/context/base/font-ini.lua +++ b/tex/context/base/font-ini.lua @@ -34,7 +34,6 @@ fonts.qua = fonts.qua or { } fonts.quads = fonts.qua -- aka quaddata fonts.tfm = fonts.tfm or { } -fonts.mode = 'base' fonts.private = 0xF0000 -- 0x10FFFF fonts.verbose = false -- more verbose cache tables diff --git a/tex/context/base/font-ini.mkiv b/tex/context/base/font-ini.mkiv index e08f5bdd9..abcfba8d8 100644 --- a/tex/context/base/font-ini.mkiv +++ b/tex/context/base/font-ini.mkiv @@ -2748,9 +2748,9 @@ % for the moment here, this will change but we need it for mk.tex -\definefontfeature[math-text] [virtualmath][ssty=no] -\definefontfeature[math-script] [virtualmath][ssty=1,mathsize=yes] -\definefontfeature[math-scriptscript][virtualmath][ssty=2,mathsize=yes] +\definefontfeature[math-text] [virtualmath][mathalternates=yes,ssty=no] +\definefontfeature[math-script] [virtualmath][mathalternates=yes,ssty=1,mathsize=yes] +\definefontfeature[math-scriptscript][virtualmath][mathalternates=yes,ssty=2,mathsize=yes] \definefontfeature [math-nostack-text] [math-text] [nostackmath=yes] \definefontfeature [math-nostack-script] [math-script] [nostackmath=yes] diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index 1eee45aaa..62522f916 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -58,6 +58,7 @@ function otf.set_dynamics(font,dynamics,attribute) features = tfmdata.shared.features } tfmdata.mode = "node" + tfmdata.dynamics = true -- handy for tracing tfmdata.language = language tfmdata.script = script tfmdata.shared.features = { } diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index 5749d8fd7..5e1117acb 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -1388,22 +1388,23 @@ end -- for context this will become a task handler +local lists = { -- why local + fonts.triggers, + fonts.processors, + fonts.manipulators, +} + function otf.set_features(tfmdata,features) local processes = { } if features and next(features) then - local lists = { -- why local - fonts.triggers, - fonts.processors, - fonts.manipulators, - } - local mode = tfmdata.mode or fonts.mode -- or features.mode + local mode = tfmdata.mode or features.mode or "base" local initializers = fonts.initializers local fi = initializers[mode] if fi then local fiotf = fi.otf if fiotf then local done = { } - for l=1,4 do + for l=1,#lists do local list = lists[l] if list then for i=1,#list do @@ -1415,7 +1416,7 @@ function otf.set_features(tfmdata,features) report_otf("initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown', tfmdata.fullname or 'unknown') end fiotf[f](tfmdata,value) -- can set mode (no need to pass otf) - mode = tfmdata.mode or fonts.mode -- keep this, mode can be set local ! + mode = tfmdata.mode or features.mode or "base" local im = initializers[mode] if im then fiotf = initializers[mode].otf @@ -1428,11 +1429,12 @@ function otf.set_features(tfmdata,features) end end end +tfmdata.mode = mode local fm = fonts.methods[mode] -- todo: zonder node/mode otf/... if fm then local fmotf = fm.otf if fmotf then - for l=1,4 do + for l=1,#lists do local list = lists[l] if list then for i=1,#list do @@ -1535,7 +1537,8 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { } local luatex = data.luatex local unicodes = luatex.unicodes -- names to unicodes - local indices = luatex.indices + local indices = luatex.indices local mode = data.mode or "base" + local characters, parameters, math_parameters, descriptions = { }, { }, { }, { } local designsize = metadata.designsize or metadata.design_size or 100 if designsize == 0 then @@ -1677,6 +1680,7 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th designsize = (designsize/10)*65536, spacer = "500 units", encodingbytes = 2, + mode = mode, filename = filename, fontname = fontname, fullname = fullname, diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index c56e98498..638fd8efc 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -691,38 +691,40 @@ otf.meanings.checkers = { local checkers = otf.meanings.checkers function otf.meanings.normalize(features) - local h = { } - for k,v in next, features do - k = lower(k) - if k == "language" or k == "lang" then - v = gsub(lower(v),"[^a-z0-9%-]","") - if not languages[v] then - h.language = to_languages[v] or "dflt" - else - h.language = v - end - elseif k == "script" then - v = gsub(lower(v),"[^a-z0-9%-]","") - if not scripts[v] then - h.script = to_scripts[v] or "dflt" - else - h.script = v - end - else - if type(v) == "string" then - local b = v:is_boolean() - if type(b) == "nil" then - v = tonumber(v) or lower(v) + if features then + local h = { } + for k,v in next, features do + k = lower(k) + if k == "language" or k == "lang" then + v = gsub(lower(v),"[^a-z0-9%-]","") + if not languages[v] then + h.language = to_languages[v] or "dflt" else - v = b + h.language = v + end + elseif k == "script" then + v = gsub(lower(v),"[^a-z0-9%-]","") + if not scripts[v] then + h.script = to_scripts[v] or "dflt" + else + h.script = v + end + else + if type(v) == "string" then + local b = v:is_boolean() + if type(b) == "nil" then + v = tonumber(v) or lower(v) + else + v = b + end end + k = to_features[k] or k + local c = checkers[k] + h[k] = c and c(v) or v end - k = to_features[k] or k - local c = checkers[k] - h[k] = c and c(v) or v end + return h end - return h end -- When I feel the need ... diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index b698fe27f..23030588e 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -1466,32 +1466,3 @@ function names.getlookups(pattern,name,reload) end return lastlookups end - -function table.formatcolumns(result) - if result and #result > 0 then - local widths = { } - local first = result[1] - local n = #first - for i=1,n do - widths[i] = 0 - end - for i=1,#result do - local r = result[i] - for j=1,n do - local w = #r[j] - if w > widths[j] then - widths[j] = w - end - end - end - for i=1,n do - widths[i] = "%-" .. widths[i] .. "s" - end - local template = concat(widths," ") - for i=1,#result do - local str = format(template,unpack(result[i])) - result[i] = string.strip(str) - end - end - return result -end diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index 83f07e9f4..57e10f3b1 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -253,6 +253,10 @@ function tfm.do_scale(tfmtable, scaledpoints, relativeid) local hasitalic = tfmtable.has_italic local descriptions = tfmtable.descriptions or { } -- + if hasmath then + t.has_math = true -- this will move to elsewhere + end + -- t.parameters = { } t.characters = { } t.MathConstants = { } diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index 6fa611694..8b81099a5 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -988,7 +988,8 @@ local gifconverter = { } figures.converters.gif = gifconverter figures.programs.convert = { - command = "convert" -- imagemagick + command = "convert" -- imagemagick + -- command = "gm convert" -- graphicmagick } function gifconverter.pdf(oldname,newname) diff --git a/tex/context/base/java-ini.lua b/tex/context/base/java-ini.lua index f64a8a18f..61b57cbc5 100644 --- a/tex/context/base/java-ini.lua +++ b/tex/context/base/java-ini.lua @@ -7,7 +7,8 @@ if not modules then modules = { } end modules ['java-ini'] = { } local format = string.format -local lpegmatch = lpeg.match +local concat = table.concat +local lpegmatch, lpegP, lpegR, lpegS, lpegC = lpeg.match, lpeg.P, lpeg.R, lpeg.S, lpeg.C javascripts = javascripts or { } javascripts.codes = javascripts.codes or { } @@ -22,20 +23,20 @@ local function storefunction(s) functions[s] = true end -local uses = lpeg.P("uses") -local used = lpeg.P("used") -local left = lpeg.P("{") -local right = lpeg.P("}") -local space = lpeg.S(" \r\n") +local uses = lpegP("uses") +local used = lpegP("used") +local left = lpegP("{") +local right = lpegP("}") +local space = lpegS(" \r\n") local spaces = space^0 -local braced = left * lpeg.C((1-right-space)^1) * right -local unbraced = lpeg.C((1-space)^1) +local braced = left * lpegC((1-right-space)^1) * right +local unbraced = lpegC((1-space)^1) local name = spaces * (braced + unbraced) * spaces -local any = lpeg.P(1) -local script = lpeg.C(any^1) -local funct = lpeg.P("function") -local leftp = lpeg.P("(") -local rightp = lpeg.P(")") +local any = lpegP(1) +local script = lpegC(any^1) +local funct = lpegP("function") +local leftp = lpegP("(") +local rightp = lpegP(")") local fname = spaces * funct * spaces * (((1-space-left)^1)/storefunction) * spaces * leftp local parsecode = name * ((uses * name) + lpeg.Cc("")) * spaces * script @@ -85,6 +86,8 @@ function javascripts.usepreamblenow(name) -- now later end end +local splitter = lpeg.Ct(lpeg.splitat(lpeg.patterns.commaspacer)) + function javascripts.code(name,arguments) local c = codes[name] if c then @@ -99,9 +102,12 @@ function javascripts.code(name,arguments) end local f = functions[name] if f then - -- temporary hack, i need a more clever approach if arguments then - return format("%s(%s)",name,'"' .. arguments.gsub(arguments,'%s*,%s*','"%1",') .. '"') + local args = lpegmatch(splitter,arguments) + for i=1,#args do -- can be a helper + args[i] = format("%q",args[i]) + end + return format("%s(%s)",name,concat(args,",")) else return format("%s()",name) end diff --git a/tex/context/base/l-aux.lua b/tex/context/base/l-aux.lua index aeea79173..28d4f88b2 100644 --- a/tex/context/base/l-aux.lua +++ b/tex/context/base/l-aux.lua @@ -163,14 +163,24 @@ function aux.array_to_string(a,separator) end end -function aux.settings_to_set(str,t) +function aux.settings_to_set(str,t) -- tohash? t = t or { } - for s in gmatch(str,"%s*([^,]+)") do + for s in gmatch(str,"%s*([^, ]+)") do -- space added t[s] = true end return t end +function aux.simple_hash_to_string(h, separator) + local t = { } + for k, v in table.sortedhash(h) do + if v then + t[#t+1] = k + end + end + return concat(t,separator or ",") +end + local value = lbrace * lpeg.C((nobrace + nested)^0) * rbrace local pattern = lpeg.Ct((space + value)^0) @@ -255,3 +265,57 @@ end --~ end --~ return reminder, cache --~ end + +function aux.formatcolumns(result,between) + if result and #result > 0 then + between = between or " " + local widths, numbers = { }, { } + local first = result[1] + local n = #first + for i=1,n do + widths[i] = 0 + end + for i=1,#result do + local r = result[i] + for j=1,n do + local rj = r[j] + local tj = type(rj) + if tj == "number" then + numbers[j] = true + end + if tj ~= "string" then + rj = tostring(rj) + r[j] = rj + end + local w = #rj + if w > widths[j] then + widths[j] = w + end + end + end + for i=1,n do + local w = widths[i] + if numbers[i] then + if w > 80 then + widths[i] = "%s" .. between + else + widths[i] = "%0" .. w .. "i" .. between + end + else + if w > 80 then + widths[i] = "%s" .. between + elseif w > 0 then + widths[i] = "%-" .. w .. "s" .. between + else + widths[i] = "%s" + end + end + end + local template = string.strip(concat(widths)) + for i=1,#result do + local str = format(template,unpack(result[i])) + result[i] = string.strip(str) + end + end + return result +end diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua index 66e279309..89227a63f 100644 --- a/tex/context/base/l-io.lua +++ b/tex/context/base/l-io.lua @@ -185,3 +185,36 @@ function io.ask(question,default,options) end end end + +function io.readnumber(f,n,m) + if m then + f:seek("set",n) + n = m + end + if n == 1 then + return byte(f:read(1)) + elseif n == 2 then + local a, b = byte(f:read(2),1,2) + return 256*a + b + elseif n == 4 then + local a, b, c, d = byte(f:read(4),1,4) + return 256^3 * a + 256^2 * b + 256*c + d + elseif n == 8 then + local a, b = readnumber(f,4), readnumber(f,4) + return 256 * b + c + elseif n == 12 then + local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) + return 256^2 * a + 256 * b + c + else + return 0 + end +end + +function io.readstring(f,n,m) + if m then + f:seek("set",n) + n = m + end + local str = gsub(f:read(n),"%z","") + return str +end diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index 05bbebab9..cffcc86e1 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -38,7 +38,8 @@ patterns.hexadecimal = P("0x") * R("09","AF","af")^1 patterns.lowercase = R("az") patterns.uppercase = R("AZ") patterns.letter = patterns.lowercase + patterns.uppercase -patterns.space = S(" ") +patterns.space = P(" ") +patterns.tab = P("\t") patterns.eol = S("\n\r") patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto) patterns.newline = crlf + cr + lf @@ -49,6 +50,9 @@ patterns.nonwhitespace = 1 - patterns.whitespace patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191') patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false) +patterns.comma = P(",") +patterns.commaspacer = P(",") * patterns.spacer^0 +patterns.period = P(".") patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/"" patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/"" @@ -169,15 +173,41 @@ local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 6 patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 +--~ local str = " a b c d " + +--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") +--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpeg.match(s,str).."]") +--~ local s = lpeg.stripper("ab") print("["..lpeg.match(s,str).."]") +--~ local s = lpeg.keeper("ab") print("["..lpeg.match(s,str).."]") + local cache = { } function lpeg.stripper(str) - local s = cache[str] - if not s then - s = Cs(((S(str)^1)/"" + 1)^0) - cache[str] = s + if type(str) == "string" then + local s = cache[str] + if not s then + s = Cs(((S(str)^1)/"" + 1)^0) + cache[str] = s + end + return s + else + return Cs(((str^1)/"" + 1)^0) + end +end + +local cache = { } + +function lpeg.keeper(str) + if type(str) == "string" then + local s = cache[str] + if not s then + s = Cs((((1-S(str))^1)/"" + 1)^0) + cache[str] = s + end + return s + else + return Cs((((1-str)^1)/"" + 1)^0) end - return s end function lpeg.replacer(t) diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua index a1249f055..7a59e1b2a 100644 --- a/tex/context/base/l-number.lua +++ b/tex/context/base/l-number.lua @@ -56,3 +56,21 @@ function number.bits(n,zero) end return t end + +--~ http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html + +function number.bit(p) + return 2 ^ (p - 1) -- 1-based indexing +end + +function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ... + return x % (p + p) >= p +end + +function number.setbit(x, p) + return hasbit(x, p) and x or x + p +end + +function number.clearbit(x, p) + return hasbit(x, p) and x - p or x +end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 23477c655..c3ef364a5 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -126,7 +126,7 @@ end table.sortedkeys = sortedkeys table.sortedhashkeys = sortedhashkeys -function table.sortedhash(t) +local function sortedhash(t) local s = sortedhashkeys(t) -- maybe just sortedkeys local n = 0 local function kv(s) @@ -137,7 +137,8 @@ function table.sortedhash(t) return kv, s end -table.sortedpairs = table.sortedhash +table.sortedhash = sortedhash +table.sortedpairs = sortedhash function table.append(t, list) for _,v in next, list do @@ -832,12 +833,26 @@ function table.count(t) return n end -function table.swapped(t) - local s = { } +function table.swapped(t,s) + local n = { } + if s then +--~ for i=1,#s do +--~ n[i] = s[i] +--~ end + for k, v in next, s do + n[k] = v + end + end +--~ for i=1,#t do +--~ local ti = t[i] -- don't ask but t[i] can be nil +--~ if ti then +--~ n[ti] = i +--~ end +--~ end for k, v in next, t do - s[v] = k + n[v] = k end - return s + return n end --~ function table.are_equal(a,b) @@ -860,7 +875,7 @@ function table.hexed(t,seperator) return concat(tt,seperator or " ") end -function table.reverse_hash(h) +function table.reverse_hash(h) -- needs another name local r = { } for k,v in next, h do r[v] = lower(gsub(k," ","")) @@ -908,10 +923,18 @@ function table.insert_after_value(t,value,extra) insert(t,#t+1,extra) end -function table.sequenced(t,sep) +function table.sequenced(t,sep,simple) -- hash only local s = { } - for k, v in next, t do -- indexed? - s[#s+1] = k .. "=" .. tostring(v) + for k, v in sortedhash(t) do + if simple then + if v == true then + s[#s+1] = k + elseif v and v~= "" then + s[#s+1] = k .. "=" .. tostring(v) + end + else + s[#s+1] = k .. "=" .. tostring(v) + end end return concat(s, sep or " | ") end diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua index 0c5a60142..dc78f7325 100644 --- a/tex/context/base/l-unicode.lua +++ b/tex/context/base/l-unicode.lua @@ -32,7 +32,7 @@ end utf = utf or unicode.utf8 local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub -local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs +local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format -- 0 EF BB BF UTF-8 -- 1 FF FE UTF-16-little-endian @@ -197,3 +197,13 @@ function unicode.utf8_to_utf16(str,littleendian) return char(254,255) .. utfgsub(str,".",big) end end + +function unicode.utfcodes(str) + local t = { } + for k,v in string.utfvalues(str) do + t[#t+1] = format("0x%04X",k) + end + return concat(t,separator or " ") +end + +--~ print(unicode.utfcodes(str)) diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua index c2b5ff6ac..6e3caed12 100644 --- a/tex/context/base/lang-wrd.lua +++ b/tex/context/base/lang-wrd.lua @@ -23,13 +23,14 @@ words.threshold = 4 local set_attribute = node.set_attribute local unset_attribute = node.unset_attribute local traverse_nodes = node.traverse -local node_id = node.id local wordsdata = words.data local chardata = characters.data -local glyph_node = node_id('glyph') -local disc_node = node_id('disc') -local kern_node = node_id('kern') +local nodecodes = nodes.nodecodes + +local glyph_node = nodecodes.glyph +local disc_node = nodecodes.disc +local kern_node = nodecodes.kern words.colors = { ["known"] = "green", diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua index 18aa848ff..fc2b9cabc 100644 --- a/tex/context/base/lpdf-col.lua +++ b/tex/context/base/lpdf-col.lua @@ -16,37 +16,43 @@ local registercolor = colors.register local registertransparancy = transparencies.register local colorsvalue = colors.value local transparenciesvalue = transparencies.value +local forcedmodel = colors.forcedmodel -- Literals needed to inject code in the mp stream, we cannot use attributes there -- since literals may have qQ's, much may go away once we have mplib code in place. -- -- This module assumes that some functions are defined in the colors namespace --- which mostlikely will be loaded later. +-- which most likely will be loaded later. function lpdf.color(model,ca,default) -- todo: use gray when no color - local cv = colorsvalue(ca) - if cv then - if model == 1 then - model = cv[1] - end - if model == 2 then - local s = cv[2] - return format("%s g %s G",s,s) - elseif model == 3 then - local r, g, b = cv[3], cv[4], cv[5] - return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b) - elseif model == 4 then - local c, m, y, k = cv[6],cv[7],cv[8],cv[9] - return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k) - else - local n,f,d,p = cv[10],cv[11],cv[12],cv[13] - if type(p) == "string" then - p = gsub(p,","," ") -- brr misuse of spot + if colors.supported then + local cv = colorsvalue(ca) + if cv then + if model == 1 then + model = cv[1] end - return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p) + model = forcedmodel(model) + if model == 2 then + local s = cv[2] + return format("%s g %s G",s,s) + elseif model == 3 then + local r, g, b = cv[3], cv[4], cv[5] + return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b) + elseif model == 4 then + local c, m, y, k = cv[6],cv[7],cv[8],cv[9] + return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k) + else + local n,f,d,p = cv[10],cv[11],cv[12],cv[13] + if type(p) == "string" then + p = gsub(p,","," ") -- brr misuse of spot + end + return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p) + end + else + return format("%s g %s G",default or 0,default or 0) end else - return format("%s g %s G",default or 0,default or 0) + return "" end end @@ -54,11 +60,15 @@ function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode -- beware, we need this hack because normally transparencies are not -- yet registered and therefore the number is not not known ... we -- might use the attribute number itself in the future - local ct = transparenciesvalue(ct) - if ct then - return format("/Tr%s gs",registertransparancy(nil,ct[1],ct[2],true)) + if transparencies.supported then + local ct = transparenciesvalue(ct) + if ct then + return format("/Tr%s gs",registertransparancy(nil,ct[1],ct[2],true)) + else + return "/Tr0 gs" + end else - return "/Tr0 gs" + return "" end end @@ -68,6 +78,7 @@ function lpdf.colorvalue(model,ca,default) if model == 1 then model = cv[1] end + model = forcedmodel(model) if model == 2 then return format("%s",cv[2]) elseif model == 3 then @@ -88,6 +99,7 @@ function lpdf.fdfcolor(model,ca,default) if model == 1 then model = cv[1] end + model = forcedmodel(model) if model == 2 then return format("[%s]",cv[2]) elseif model == 3 then @@ -108,6 +120,7 @@ function lpdf.colorspace(model,ca) if model == 1 then model = cv[1] end + model = forcedmodel(model) if model == 2 then return "DeviceGray" elseif model == 3 then @@ -125,23 +138,47 @@ local intransparency = false local pdfcolor = lpdf.color function lpdf.rgbcode(model,r,g,b) - return pdfcolor(model,registercolor(nil,'rgb',r,g,b)) + if colors.supported then + return pdfcolor(model,registercolor(nil,'rgb',r,g,b)) + else + return "" + end end + function lpdf.cmykcode(model,c,m,y,k) - return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k)) + if colors.supported then + return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k)) + else + return "" + end end + function lpdf.graycode(model,s) - return pdfcolor(model,registercolor(nil,'gray',s)) + if colors.supported then + return pdfcolor(model,registercolor(nil,'gray',s)) + else + return "" + end end + function lpdf.spotcode(model,n,f,d,p) - return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect + if colors.supported then + return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect + else + return "" + end end + function lpdf.transparencycode(a,t) - intransparency = true - return format("/Tr%s gs",registertransparancy(nil,a,t,true)) -- true forces resource + if transparencies.supported then + intransparency = true + return format("/Tr%s gs",registertransparancy(nil,a,t,true)) -- true forces resource + else + return "" + end end function lpdf.finishtransparencycode() - if intransparency then + if transparencies.supported and intransparency then intransparency = false return "/Tr0 gs" -- we happen to know this -) else diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua index 23ab0674c..680c39e18 100644 --- a/tex/context/base/lpdf-epd.lua +++ b/tex/context/base/lpdf-epd.lua @@ -20,6 +20,13 @@ local setmetatable, rawset = setmetatable, rawset -- getNum getString getBool getName getRef -- getResourceDict getMediaBox getCropBox getBleedBox getTrimBox getArtBox -- getPageRef getKindName findDestgetNumPages getDests getPage getCatalog getAnnots +-- +-- needed: +-- +-- add accessor methods to the resource dict +-- a function to mark objects as to be included + +lpdf = lpdf or { } -- -- -- helpers -- -- -- @@ -100,17 +107,17 @@ local basic_resources_access = { -- == dictionary_access end } -local basic_box_access = { +local basic_box_access = { -- here it makes sense to do the rawset __index = function(t,k) local d = t.__data__ - if k == "all" then return { d.x1, d.y1, d.x2, d.y2 } - elseif k == "width" then return d.x2 - d.x1 - elseif k == "height" then return d.y2 - d.y1 - elseif k == 1 then return d.x1 - elseif k == 2 then return d.y1 - elseif k == 3 then return d.x2 - elseif k == 4 then return d.y2 - else return 0 end + if k == "all" then return { d.x1, d.y1, d.x2, d.y2 } + elseif k == "width" then return d.x2 - d.x1 + elseif k == "height" then return d.y2 - d.y1 + elseif k == 1 or k == "llx" then return d.x1 + elseif k == 2 or k == "lly" then return d.y1 + elseif k == 3 or k == "urx" then return d.x2 + elseif k == 4 or k == "lly" then return d.y2 + else return 0 end end } diff --git a/tex/context/base/lpdf-pdx.lua b/tex/context/base/lpdf-pdx.lua index db1217c53..dbf8eadf2 100644 --- a/tex/context/base/lpdf-pdx.lua +++ b/tex/context/base/lpdf-pdx.lua @@ -6,7 +6,10 @@ if not modules then modules = { } end modules ['lpdf-pdx'] = { license = "see context related readme files", } -local trace_colorprofiles = false trackers.register("backend.colorprofiles", function(v) trace_colorprofiles = v end) +-- context --directives="backend.format=PDF/X-1a:2001" --trackers=backend.format yourfile + +local trace_pdfx = false trackers.register("backend.pdfx", function(v) trace_pdfx = v end) +local trace_format = false trackers.register("backend.format", function(v) trace_format = v end) local report_backends = logs.new("backends") @@ -22,7 +25,10 @@ local pdfstring = lpdf.string local pdfverbose = lpdf.verbose local pdfobject = lpdf.object -local lower, gmatch = string.lower, string.gmatch +local addtoinfo, injectxmpinfo, insertxmpinfo = lpdf.addtoinfo, lpdf.injectxmpinfo, lpdf.insertxmpinfo + +local lower, gmatch, format, find = string.lower, string.gmatch, string.format, string.find +local concat, serialize = table.concat, table.serialize local channels = { gray = 1, @@ -38,90 +44,587 @@ local prefixes = { cmyk = "DefaultCMYK", } -local profiles = { } -local defaults = { } -local intents = pdfarray() -local lastprofile = nil - -function codeinjections.useinternalICCprofile(colorspace,filename) - local name = lower(file.basename(filename)) - local profile = profiles[name] - if not profile then - local colorspace = lower(colorspace) - local filename = resolvers.findctxfile(filename) or "" - local channel = channels[colorspace] - if channel and filename ~= "" then - local a = pdfdictionary { N = channel } - profile = pdfobject { - compresslevel = 0, - immediate = true, -- ! - type = "stream", - file = filename, - attr = a(), - } - profiles[name] = profile +local pdfxspecification, pdfxformat = nil, nil + +-- * correspondent document wide flags (write once) needed for permission tests + +local pdfx = { + ["version"] = { + external_icc_profiles = 1.4, -- 'p' in name; URL reference of output intent + jbig2_compression = 1.4, + jpeg2000_compression = 1.5, -- not supported yet + nchannel_colorspace = 1.6, -- 'n' in name; n-channel colorspace support + open_prepress_interface = 1.3, -- 'g' in name; reference to external graphics + opentype_fonts = 1.6, + optional_content = 1.5, + transparency = 1.4, + object_compression = 1.5, + }, + ["default"] = { + pdf_version = 1.7, -- todo: block tex primitive + format_name = "default", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + spot_colors = true, + calibrated_rgb_colors = true, -- unknown + cielab_colors = true, -- unknown + nchannel_colorspace = true, -- unknown + internal_icc_profiles = true, -- controls profile inclusion + external_icc_profiles = true, -- controls profile inclusion + include_intents = true, + open_prepress_interface = true, -- unknown + opentype_fonts = true, -- out of our control + optional_content = true, -- todo: block at lua level + transparency = true, -- todo: block at lua level + jbig2_compression = true, -- todo: block at lua level + jpeg2000_compression = true, -- todo: block at lua level + inject_metadata = function() + -- nothing + end + }, + ["pdf/x-1a:2001"] = { + pdf_version = 1.3, + format_name = "PDF/X-1a:2001", + gray_scale = true, + cmyk_colors = true, + spot_colors = true, + internal_icc_profiles = true, + inject_metadata = function() + addtoinfo("GTS_PDFXVersion","PDF/X-1a:2001") + injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-1a:2001</pdfxid:GTS_PDFXVersion></rdf:Description>",false) + end + }, + ["pdf/x-1a:2003"] = { + pdf_version = 1.4, + format_name = "PDF/X-1a:2003", + gray_scale = true, + cmyk_colors = true, + spot_colors = true, + internal_icc_profiles = true, + inject_metadata = function() + addtoinfo("GTS_PDFXVersion","PDF/X-1a:2003") + injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-1a:2003</pdfxid:GTS_PDFXVersion></rdf:Description>",false) + end + }, + ["pdf/x-3:2002"] = { + pdf_version = 1.3, + format_name = "PDF/X-3:2002", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + include_intents = true, + inject_metadata = function() + addtoinfo("GTS_PDFXVersion","PDF/X-3:2002") + end + }, + ["pdf/x-3:2003"] = { + pdf_version = 1.4, + format_name = "PDF/X-3:2003", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + include_intents = true, + jbig2_compression = true, + inject_metadata = function() + addtoinfo("GTS_PDFXVersion","PDF/X-3:2003") + end + }, + ["pdf/x-4"] = { + pdf_version = 1.6, + format_name = "PDF/X-4", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + include_intents = true, + opentype_fonts = true, + optional_content = true, + transparency = true, + jbig2_compression = true, + jpeg2000_compression = true, + inject_metadata = function() + injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-4</pdfxid:GTS_PDFXVersion></rdf:Description>",false) + insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:VersionID>1</xmpMM:VersionID>",false) + insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:RenditionClass>default</xmpMM:RenditonClass>",false) + end + }, + ["pdf/x-4p"] = { + pdf_version = 1.6, + format_name = "PDF/X-4p", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + external_icc_profiles = true, + include_intents = true, + opentype_fonts = true, + optional_content = true, + transparency = true, + jbig2_compression = true, + jpeg2000_compression = true, + nchannel_colorspace = false, + inject_metadata = function() + injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-4p</pdfxid:GTS_PDFXVersion></rdf:Description>",false) + insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:VersionID>1</xmpMM:VersionID>",false) + insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:RenditionClass>default</xmpMM:RenditonClass>",false) + end + }, + ["pdf/x-5g"] = { + pdf_version = 1.6, + format_name = "PDF/X-5g", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + include_intents = true, + open_prepress_interface = true, + opentype_fonts = true, + optional_content = true, + transparency = true, + jbig2_compression = true, + jpeg2000_compression = true, + inject_metadata = function() + -- todo + end + }, + ["pdf/x-5pg"] = { + pdf_version = 1.6, + format_name = "PDF/X-5pg", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + external_icc_profiles = true, + include_intents = true, + open_prepress_interface = true, + opentype_fonts = true, + optional_content = true, + transparency = true, + jbig2_compression = true, + jpeg2000_compression = true, + inject_metadata = function() + -- todo + end + }, + ["pdf/x-5n"] = { + pdf_version = 1.6, + format_name = "PDF/X-5n", + gray_scale = true, + cmyk_colors = true, + rgb_colors = true, + calibrated_rgb_colors = true, + spot_colors = true, + cielab_colors = true, + internal_icc_profiles = true, + include_intents = true, + opentype_fonts = true, + optional_content = true, + transparency = true, + jbig2_compression = true, + jpeg2000_compression = true, + nchannel_colorspace = true, + inject_metadata = function() + -- todo + end + } +} + +lpdf.pdfx = pdfx -- it does not hurt to have this one visible + +local filenames = { + "colorprofiles.xml", + "colorprofiles.lua", +} + +local function locatefile(filename) + local fullname = resolvers.find_file(filename,"icc") + if not fullname or fullname == "" then + fullname = resolvers.finders.loc(filename) -- could be specific to the project + end + return fullname or "" +end + +local function loadprofile(name,filename) + local profile = false + local databases = filename and filename ~= "" and aux.settings_to_array(filename) or filenames + for i=1,#databases do + local filename = locatefile(databases[i]) + if filename and filename ~= "" then + local suffix = file.extname(filename) + local lname = lower(name) + if suffix == "xml" then + local xmldata = xml.load(filename) -- no need for caching it + if xmldata then + profile = xml.filter(xmldata,format('xml://profiles/profile/(info|filename)[lower(text())=="%s"]/../table()',lname)) + end + elseif suffix == "lua" then + local luadata = loadfile(filename) + luadata = ludata and luadata() + if luadata then + profile = luadata[name] or luadata[lname] -- hashed + if not profile then + for i=1,#luadata do + local li = luadata[i] + if lower(li.info) == lname then -- indexed + profile = li + break + end + end + end + end + end + if profile then + if next(profile) then + report_backends("profile specification '%s' loaded from '%s'",name,filename) + return profile + elseif trace_pdfx then + report_backends("profile specification '%s' loaded from '%s' but empty",name,filename) + end + return false + end end end - lastprofile = profile - return profile + report_backends("profile specification '%s' not found in '%s'",name,concat(filenames, ", ")) end -function codeinjections.useexternalICCprofile(colorspace,name,urls,checksum,version) - local profile = profiles[name] - if not profile then +local function urls(url) + if not url or url == "" then + return nil + else local u = pdfarray() - for url in gmatch(urls,"([^, ]+)") do - u[#u+1] = pdfdictionary { - FS = pdfconstant("URL"), - F = pdfstring(url), + for url in gmatch(url,"([^, ]+)") do + if find(url,"^http") then + u[#u+1] = pdfdictionary { + FS = pdfconstant("URL"), + F = pdfstring(url), + } + end + end + return u + end +end + +local function profilename(filename) + return lower(file.basename(filename)) +end + +local internalprofiles = { } + +local function handleinternalprofile(s,include) + local filename, colorspace = s.filename or "", s.colorspace or "" + if filename == "" or colorspace == "" then + report_backends("error in internal profile specification: %s",serialize(s,false)) + else + local tag = profilename(filename) + local profile = internalprofiles[tag] + if not profile then + local colorspace = lower(colorspace) + if include then + -- local fullname = resolvers.findctxfile(filename) or "" + local fullname = locatefile(filename) + local channel = channels[colorspace] or nil + if fullname == "" then + report_backends("error, couldn't locate profile '%s'",filename) + elseif not channel then + report_backends("error, couldn't resolve channel entry for colorspace '%s'",colorspace) + else + local a = pdfdictionary { N = channel } + profile = pdfobject { -- does a flush too + compresslevel = 0, + immediate = true, -- ! + type = "stream", + file = fullname, + attr = a(), + } + internalprofiles[tag] = profile + if trace_pdfx then + report_backends("including '%s' color profile from '%s'",colorspace,fullname) + end + end + else + internalprofiles[tag] = true + if trace_pdfx then + report_backends("not including '%s' color profile '%s'",colorspace,filename) + end + end + end + return profile + end +end + +local externalprofiles = { } + +local function handleexternalprofile(s,include) -- specification (include ignored here) + local name, url, filename, checksum, version, colorspace = + s.info or s.filename or "", s.url or "", s.filename or "", s.checksum or "", s.version or "", s.colorspace or "" + if false then -- somehow leads to invalid pdf + local iccprofile = colors.iccprofile(filename) + if iccprofile then + name = name ~= "" and name or iccprofile.tags.desc.cleaned or "" + url = url ~= "" and url or iccprofile.tags.dmnd.cleaned or "" + checksum = checksum ~= "" and checksum or file.checksum(iccprofile.fullname) or "" + version = version ~= "" and version or iccprofile.header.version or "" + colorspace = colorspace ~= "" and colorspace or iccprofile.header.colorspace or "" + end + -- table.print(iccprofile) + end + if name == "" or url == "" or checksum == "" or version == "" or colorspace == "" or filename == "" then + local profile = handleinternalprofile(s) + if profile then + report_backends("incomplete external profile specification, falling back to internal") + else + report_backends("error in external profile specification: %s",serialize(s,false)) + end + else + local tag = profilename(filename) + local profile = externalprofiles[tag] + if not profile then + local d = pdfdictionary { + ProfileName = name, -- not file name! + ProfileCS = colorspace, + URLs = urls(url), -- array containing at least one URL + CheckSum = pdfverbose { "<", lower(checksum), ">" }, -- 16byte MD5 hash + ICCVersion = pdfverbose { "<", version, ">" }, -- bytes 8..11 from the header of the ICC profile, as a hex string } + profile = pdfflushobject(d) + externalprofiles[tag] = profile end - local d = pdfdictionary { - ProfileName = name, -- not file name! - ProfileCS = colorspace, - URLs = u, -- array containing at least one URL - CheckSum = pdfverbose { "<", checksum, ">" }, -- 16byte MD5 hash - ICCVersion = pdfverbose { "<", version, ">" }, -- bytes 8..11 from the header of the ICC profile, as a hex string - } - local n = pdfflushobject(d) - profiles[name] = n - lastprofile = n - return n + return profile end end -local loaded = { } +local loadeddefaults = { } -function codeinjections.useICCdefaultprofile(colorspace,filename) - local colorspace = lower(colorspace) - if not loaded[colorspace] then - local n = codeinjections.useinternalICCprofile(colorspace,filename) - if n then +local function handledefaultprofile(s) -- specification + local filename, colorspace = s.filename or "", lower(s.colorspace or "") + if filename == "" or colorspace == "" then + report_backends("error in default profile specification: %s",serialize(s,false)) + elseif not loadeddefaults[colorspace] then + local tag = profilename(filename) + local n = internalprofiles[tag] -- or externalprofiles[tag] + if n == true then -- not internalized + report_backends("no default profile '%s' for colorspace '%s'",filename,colorspace) + elseif n then local a = pdfarray { pdfconstant("ICCBased"), pdfreference(n), } -- used in page /Resources, so this must be inserted at runtime lpdf.adddocumentcolorspace(prefixes[colorspace],pdfreference(pdfflushobject(a))) - if trace_colorprofiles then - report_backends("including color profile '%s' from '%s'",colorspace,filename) + loadeddefaults[colorspace] = true + report_backends("setting '%s' as default '%s' color space",filename,colorspace) + else + report_backends("no default profile '%s' for colorspace '%s'",filename,colorspace) + end + elseif trace_pdfx then + report_backends("a default '%s' colorspace is already in use",colorspace) + end +end + +local loadedintents, intents = { }, pdfarray() + +local function handleoutputintent(s) + local name, url, filename, id, outputcondition, info = s.info or s.filename or "", s.url or "", s.filename or "", s.id or "", s.outputcondition or "", s.info or "" + if name == "" or id == "" then + report_backends("error in output intent specification: %s",serialize(s,false)) + elseif not loadedintents[name] then + local tag = profilename(filename) + local internal, external = internalprofiles[tag], externalprofiles[tag] + if internal or external then + local d = { + Type = pdfconstant("OutputIntent"), + S = pdfconstant("GTS_PDFX"), + OutputConditionIdentifier = id, + RegistryName = url, + OutputCondition = outputcondition, + Info = info, + } + if internal and internal ~= true then + d.DestOutputProfile = pdfreference(internal) + elseif external and external ~= true then + d.DestOutputProfileRef = pdfreference(external) + else + report_backends("omitting reference to profile for intent '%s'",name) + end + intents[#intents+1] = pdfreference(pdfflushobject(pdfdictionary(d))) + if trace_pdfx then + report_backends("setting output intent to '%s' with id '%s' (entry %s)",name,id,#intents) + end + else + report_backends("invalid output intent '%s'",name) + end + loadedintents[name] = true + elseif trace_pdfx then + report_backends("an output intent with name '%s' is already in use",name) + end +end + +local function handleiccprofile(message,name,filename,how,options,alwaysinclude) + if name and name ~= "" then + local list = aux.settings_to_array(name) + for i=1,#list do + local name = list[i] + local profile = loadprofile(name,filename) + if trace_pdfx then + report_backends("handling %s '%s'",message,name) + end + if profile then + if pdfxspecification.cmyk_colors then + profile.colorspace = profile.colorspace or "CMYK" + else + profile.colorspace = profile.colorspace or "RGB" + end + local external = pdfxspecification.external_icc_profiles + local internal = pdfxspecification.internal_icc_profiles + local include = pdfxspecification.include_intents + local always, never = options[variables.always], options[variables.never] + if always or alwaysinclude then + if trace_pdfx then + report_backends("forcing internal profiles") -- can make preflight unhappy + end + -- internal, external = true, false + internal, external = not never, false + elseif never then + if trace_pdfx then + report_backends("forcing external profiles") -- can make preflight unhappy + end + internal, external = false, true + end + if external then + if trace_pdfx then + report_backends("handling external profiles cf. '%s'",name) + end + handleexternalprofile(profile,false) + else + if trace_pdfx then + report_backends("handling internal profiles cf. '%s'",name) + end + if internal then + handleinternalprofile(profile,always or include) + else + report_backends("no profile inclusion for '%s'",pdfxformat) + end + end + how(profile) + elseif trace_pdfx then + report_backends("unknown profile '%s'",name) + end + end + end +end + +local function flushoutputintents() + if #intents > 0 then + lpdf.addtocatalog("OutputIntents",pdfreference(pdfflushobject(intents))) + end +end + +lpdf.registerdocumentfinalizer(flushoutputintents,2,"output intents") + +directives.register("backend.format", function(v) + codeinjections.setformat(v) +end) + +function codeinjections.setformat(s) + local format, level, profile, intent, option, filename = + s.format or "", s.level or "", s.profile or "", s.intent or "", s.option or "", s.file or "" + if format == "" then + -- we ignore this as we hook it in \everysetupbackend + else + local spec = pdfx[lower(format)] + if spec then + pdfxspecification, pdfxformat = spec, spec.format_name + report_backends("setting format to '%s'",pdfxformat) + local pdf_version, inject_metadata = spec.pdf_version * 10, spec.inject_metadata + local majorversion, minorversion = math.div(pdf_version,10), math.mod(pdf_version,10) + local objectcompression = pdf_version >= 15 + tex.pdfcompresslevel = level and tonumber(level) or tex.pdfobjcompresslevel -- keep default + tex.pdfobjcompresslevel = objectcompression and tex.pdfobjcompresslevel or 0 -- keep default + tex.pdfmajorversion = majorversion + tex.pdfminorversion = minorversion + report_backends("forcing pdf version %s.%s, compression level %s, object compression %sabled", + majorversion,minorversion,tex.pdfcompresslevel,compression and "en" or "dis") + -- + -- context.setupcolors { -- not this way + -- cmyk = spec.cmyk_colors and variables.yes or variables.no, + -- rgb = spec.rgb_colors and variables.yes or variables.no, + -- } + -- + colors.forcesupport( + spec.gray_scale or false, + spec.rgb_colors or false, + spec.cmyk_colors or false, + spec.spot_colors or false, + spec.nchannel_colorspace or false + ) + transparencies.forcesupport( + spec.transparency or false + ) + viewerlayers.forcesupport( + spec.optional_content or false + ) + viewerlayers.setfeatures( + spec.has_order or false -- new + ) + -- + -- spec.jbig2_compression : todo, block in image inclusion + -- spec.jpeg2000_compression : todo, block in image inclusion + -- + if type(inject_metadata) == "function" then + inject_metadata() + end + local options = aux.settings_to_hash(option) + handleiccprofile("color profile",profile,filename,handledefaultprofile,options,true) + handleiccprofile("output intent",intent,filename,handleoutputintent,options,false) + if trace_format then + for k, v in table.sortedhash(pdfx.default) do + local v = pdfxspecification[k] + if type(v) ~= "function" then + report_backends("%s = %s",k,tostring(v or false)) + end + end end - elseif trace_colorprofiles then - report_backends("no color profile '%s' in '%s'",colorspace,filename) + function codeinjections.setformat(noname) + report_backends("error, format is already set to '%s', ignoring '%s'",pdfxformat,noname) + end + else + report_backends("error, format '%s' is not supported",format) end - loaded = true - elseif trace_colorprofiles then - report_backends("color profile '%s' is already included",colorspace) end end +function codeinjections.getformatoption(key) + return pdfxspecification and pdfxspecification[key] +end + --~ The following is somewhat cleaner but then we need to flag that there are --~ color spaces set so that the page flusher does not optimize the (at that --~ moment) still empty array away. So, next(d_colorspaces) should then become --~ a different test, i.e. also on flag. I'll add that when we need more forward --~ referencing. --~ ---~ local function embedprofile = codeinjections.useICCdefaultprofile +--~ local function embedprofile = handledefaultprofile --~ --~ local function flushembeddedprofiles() --~ for colorspace, filename in next, defaults do @@ -129,37 +632,8 @@ end --~ end --~ end --~ ---~ function codeinjections.useICCdefaultprofile(colorspace,filename) ---~ defaults[lower(colorspace)] = filename +--~ local function handledefaultprofile(s) +--~ defaults[lower(s.colorspace)] = s.filename --~ end --~ --~ lpdf.registerdocumentfinalizer(flushembeddedprofiles,1,"embedded color profiles") - -function codeinjections.usePDFXoutputintent(id,name,reference,outputcondition,info) - local d = { - Type = pdfconstant("OutputIntent"), - S = pdfconstant("GTS_PDFX"), - OutputConditionIdentifier = id, - RegistryName = name, - OutputCondition = outputcondition, - Info = info, - } - local icc = lastprofile - if reference == variables.yes then - d["DestOutputProfileRef"] = pdfreference(icc) - else - d["DestOutputProfile"] = pdfreference(icc) - end - intents[#intents+1] = pdfreference(pdfflushobject(pdfdictionary(d))) - if trace_colorprofiles then - report_backends("adding output intent '%s' with id '%s' (entry %s)",name,id,#intents) - end -end - -local function flushoutputintents() - if #intents > 0 then - lpdf.addtocatalog("OutputIntents",pdfreference(pdfflushobject(intents))) - end -end - -lpdf.registerdocumentfinalizer(flushoutputintents,2,"output intents") diff --git a/tex/context/base/lpdf-pdx.mkiv b/tex/context/base/lpdf-pdx.mkiv index 738cb3f58..cd13ba24c 100644 --- a/tex/context/base/lpdf-pdx.mkiv +++ b/tex/context/base/lpdf-pdx.mkiv @@ -13,55 +13,19 @@ \writestatus{loading}{ConTeXt Backend Macros / PDF-X} -\unprotect - -% declare default color space -% all device based entries of the same CS are mapped to the defined ICCprofile then; -% i.e. /DeviceRGB --> /ICCBased RGB profile -% TODO: allow multiple default profiles (one per CS) -% -% external ICC profile dictionary (PDF/X-4p and PDF/X-5p) -% -% - ProfileName (not file name!) -% - URLs (array containing at least one URL); the keyword FSA is wrong! -% - CheckSum (16byte MD5 hash) -% - ProfileCS (GRAY,RGB,CMYK) -% - ICCVersion (bytes 8..11 from the header of the ICC profile, as a hex string) - \registerctxluafile{lpdf-pdx}{1.001} -\def\douseinternalICCprofile[#1]% - {\getparameters[\??ic][colorspace=,filename=,#1]% - \ctxlua{backends.codeinjections.useinternalICCprofile( - "\@@iccolorspace","\@@icfilename")}} - -% create a dictionary for an external ICC profile (PDF/X-4p and PDF/X-5pg only) -% the referenced ICC profile is not embedded - -\def\douseexternalICCprofile[#1]% - {\getparameters[\??ic][colorspace=,name=,url=,checksum=,version=,#1]% - \ctxlua{backends.codeinjections.useexternalICCprofile( - "\@@iccolorspace","\@@icname","\@@icurl","\@@icchecksum","\@@icversion")}} - -% use an ICC profile as default colorspace for all device dependend colors; -% all device based entries of the same CS are mapped to the defined ICCprofile then; -% i.e. /DeviceRGB --> /ICCBased RGB profile; always embed the profile! - -\def\douseICCdefaultprofile[#1]% - {\getparameters[\??ic][colorspace=,filename=,#1]% - \ctxlua{backends.codeinjections.useICCdefaultprofile( - "\@@iccolorspace","\@@icfilename")}} - -% embedding rules for output intent profile differ for the PDF/X versions - -\def\dousePDFXoutputintent[#1]% - {\getparameters[\??ic][reference=\v!yes,outputcondition=,info=,id=,name=,#1]% - \ctxlua{backends.codeinjections.usePDFXoutputintent( - "\@@icid","\@@icname","\@@icreference","\@@icoutputcondition","\@@icinfo")}} +\unprotect -\def\useinternalICCprofile{\dosingleempty\douseinternalICCprofile} -\def\useexternalICCprofile{\dosingleempty\douseexternalICCprofile} -\def\useICCdefaultprofile {\dosingleempty\douseICCdefaultprofile } -\def\usePDFXoutputintent {\dosingleempty\dousePDFXoutputintent } +\appendtoks + \doifsomething{\backendparameter\c!format} + {\ctxlua{backends.codeinjections.setformat { + format = "\backendparameter\c!format", + level = "\backendparameter\c!level", + option = "\backendparameter\c!option", + profile = "\backendparameter\c!profile", + intent = "\backendparameter\c!intent", + }}}% +\to \everysetupbackend \protect \endinput diff --git a/tex/context/base/lpdf-ren.lua b/tex/context/base/lpdf-ren.lua index 0e4e34c2a..f942ec2c9 100644 --- a/tex/context/base/lpdf-ren.lua +++ b/tex/context/base/lpdf-ren.lua @@ -29,11 +29,12 @@ local executers = jobreferences.executers local variables = interfaces.variables -local pdfconstant = lpdf.constant -local pdfdictionary = lpdf.dictionary -local pdfarray = lpdf.array -local pdfreference = lpdf.reference -local pdfflushobject = lpdf.flushobject +local pdfconstant = lpdf.constant +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfreference = lpdf.reference +local pdfflushobject = lpdf.flushobject +local pdfreserveobject = lpdf.reserveobject local pdf_ocg = pdfconstant("OCG") local pdf_ocmd = pdfconstant("OCMD") @@ -54,23 +55,84 @@ function backends.pdf.layerreference(name) return pdfln[name] end +-- only flush layers that are used + +--~ function codeinjections.defineviewerlayer(specification) +--~ if textlayers then +--~ local tag = specification.tag +--~ -- todo: reserve +--~ local n = pdfdictionary { +--~ Type = pdf_ocg, +--~ Name = specification.title or "unknown", +--~ Intent = ((specification.kind > 0) and pdf_design) or nil, -- disable layer hiding by user +--~ Usage = ((specification.printable == variables.no) and lpdf_usage) or nil , -- printable or not +--~ } +--~ local nr = pdfreference(pdfflushobject(n)) +--~ pdfln[tag] = nr -- was n +--~ local d = pdfdictionary { +--~ Type = pdf_ocmd, +--~ OCGs = pdfarray { nr }, +--~ } +--~ local dr = pdfreference(pdfflushobject(d)) +--~ pdfld[tag] = dr +--~ textlayers[#textlayers+1] = nr +--~ if specification.visible == variables.start then +--~ videlayers[#videlayers+1] = nr +--~ else +--~ hidelayers[#hidelayers+1] = nr +--~ end +--~ pagelayers[tag] = dr -- check +--~ end +--~ end + +--~ local function flushtextlayers() +--~ if textlayers and #textlayers > 0 then +--~ local d = pdfdictionary { +--~ OCGs = textlayers, +--~ D = pdfdictionary { +--~ Order = textlayers, +--~ ON = videlayers, +--~ OFF = hidelayers, +--~ }, +--~ } +--~ lpdf.addtocatalog("OCProperties",d) +--~ textlayers = nil +--~ end +--~ end + +--~ local function flushpagelayers() -- we can share these +--~ if next(pagelayers) then +--~ lpdf.addtopageresources("Properties",pagelayers) +--~ end +--~ end + +local pagelayers, pagelayersreference, cache = nil, nil, { } + function codeinjections.defineviewerlayer(specification) - if textlayers then + if viewerlayers.supported and textlayers then + if not pagelayers then + pagelayers = pdfdictionary() + pagelayersreference = pdfreserveobject() + end local tag = specification.tag -- todo: reserve - local n = pdfdictionary { + local nn = pdfreserveobject() + local nr = pdfreference(nn) + local nd = pdfdictionary { Type = pdf_ocg, Name = specification.title or "unknown", Intent = ((specification.kind > 0) and pdf_design) or nil, -- disable layer hiding by user Usage = ((specification.printable == variables.no) and lpdf_usage) or nil , -- printable or not } - local nr = pdfreference(pdfflushobject(n)) + cache[#cache+1] = { nn, nd } pdfln[tag] = nr -- was n - local d = pdfdictionary { + local dn = pdfreserveobject() + local dr = pdfreference(dn) + local dd = pdfdictionary { Type = pdf_ocmd, OCGs = pdfarray { nr }, } - local dr = pdfreference(pdfflushobject(d)) + cache[#cache+1] = { dn, dd } pdfld[tag] = dr textlayers[#textlayers+1] = nr if specification.visible == variables.start then @@ -83,23 +145,34 @@ function codeinjections.defineviewerlayer(specification) end local function flushtextlayers() - if textlayers and #textlayers > 0 then - local d = pdfdictionary { - OCGs = textlayers, - D = pdfdictionary { - Order = textlayers, - ON = videlayers, - OFF = hidelayers, - }, - } - lpdf.addtocatalog("OCProperties",d) - textlayers = nil + if viewerlayers.supported then + if pagelayers then + pdfflushobject(pagelayersreference,pagelayers) + end + for i=1,#cache do + local ci = cache[i] + pdfflushobject(ci[1],ci[2]) + end + if textlayers and #textlayers > 0 then -- we can group them if needed, like: layout + local d = pdfdictionary { + OCGs = textlayers, + D = pdfdictionary { + Name = "Document", + Order = (viewerlayers.hasorder and textlayers) or nil, + ON = videlayers, + OFF = hidelayers, + BaseState = pdfconstant("On"), + }, + } + lpdf.addtocatalog("OCProperties",d) + textlayers = nil + end end end -local function flushpagelayers() - if next(pagelayers) then - lpdf.addtopageresources("Properties",pagelayers) +local function flushpagelayers() -- we can share these + if pagelayers then + lpdf.addtopageresources("Properties",pdfreference(pagelayersreference)) -- we could cache this end end diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua index 591def8b1..c5c480458 100644 --- a/tex/context/base/lpdf-tag.lua +++ b/tex/context/base/lpdf-tag.lua @@ -27,12 +27,14 @@ local pdfpagereference = lpdf.pagereference local new_pdfliteral = nodes.pdfliteral -local hlist = node.id("hlist") -local vlist = node.id("vlist") -local glyph = node.id("glyph") -local glue = node.id("glue") -local disc = node.id("disc") -local whatsit = node.id("whatsit") +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local glyph = nodecodes.glyph +local glue = nodecodes.glue +local disc = nodecodes.disc +local whatsit = nodecodes.whatsit local a_tagged = attributes.private('tagged') local a_image = attributes.private('image') diff --git a/tex/context/base/luat-bwc.lua b/tex/context/base/luat-bwc.lua new file mode 100644 index 000000000..e41f241dc --- /dev/null +++ b/tex/context/base/luat-bwc.lua @@ -0,0 +1,27 @@ +if not modules then modules = { } end modules ['luat-bwc'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- backward compatibility + +local box = tex.box + +tex.wd = { } setmetatable(tex.wd, { + __index = function(t,k) local bk = box[k] return bk and bk.width or 0 end, + __newindex = function(t,k,v) local bk = box[k] if bk then bk.width = v end end, +} + +tex.ht = { } setmetatable(tex.ht, { + __index = function(t,k) local bk = box[k] return bk and bk.height or 0 end, + __newindex = function(t,k,v) local bk = box[k] if bk then bk.height = v end end, +} + +tex.dp = { } setmetatable(tex.dp, { + __index = function(t,k) local bk = box[k] return bk and bk.depth or 0 end, + __newindex = function(t,k,v) local bk = box[k] if bk then bk.depth = v end end, +} + diff --git a/tex/context/base/luat-cod.lua b/tex/context/base/luat-cod.lua index a5239e7ae..8d61c269a 100644 --- a/tex/context/base/luat-cod.lua +++ b/tex/context/base/luat-cod.lua @@ -95,6 +95,20 @@ if not environment.luafilechunk then end +if not environment.engineflags then + local engineflags = { } + for i=-10,#arg do + local a = arg[i] + if a then + local flag, content = match(a,"^%-%-([^=]+)=?(.-)$") + if flag then + engineflags[flag] = content or "" + end + end + end + environment.engineflags = engineflags +end + -- We need a few premature callbacks in the format generator. We -- also do this when the format is loaded as otherwise we get -- a kpse error when disabled. Thi sis en angine issue that will diff --git a/tex/context/base/luat-fmt.lua b/tex/context/base/luat-fmt.lua index d9c0e38c8..07a7a1490 100644 --- a/tex/context/base/luat-fmt.lua +++ b/tex/context/base/luat-fmt.lua @@ -8,6 +8,21 @@ if not modules then modules = { } end modules ['luat-fmt'] = { -- helper for mtxrun +local quote = string.quote + +local function primaryflags() + local trackers = environment.argument("trackers") + local directives = environment.argument("directives") + local flags = "" + if trackers and trackers ~= "" then + flags = flags .. "--trackers=" .. quote(trackers) + end + if directives and directives ~= "" then + flags = flags .. "--directives=" .. quote(directives) + end + return flags +end + function environment.make_format(name) -- change to format path (early as we need expanded paths) local olddir = lfs.currentdir() @@ -68,8 +83,7 @@ function environment.make_format(name) return end -- generate format - local q = string.quote - local command = string.format("luatex --ini --lua=%s %s %sdump",q(usedluastub),q(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\") + local command = string.format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\") logs.simple("running command: %s\n",command) os.spawn(command) -- remove related mem files @@ -108,7 +122,7 @@ function environment.run_format(name,data,more) logs.simple("no luc/lua with name: %s",barename) else local q = string.quote - local command = string.format("luatex --fmt=%s --lua=%s %s %s",q(barename),q(luaname),q(data),more ~= "" and q(more) or "") + local command = string.format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "") logs.simple("running command: %s",command) os.spawn(command) end diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv index 2a9d5ecd3..3018d32e2 100644 --- a/tex/context/base/luat-lib.mkiv +++ b/tex/context/base/luat-lib.mkiv @@ -51,6 +51,7 @@ \registerctxluafile{luat-env}{1.001} \registerctxluafile{luat-exe}{1.001} \registerctxluafile{luat-iop}{1.001} +\registerctxluafile{luat-bwc}{1.001} \registerctxluafile{lxml-tab}{1.001} \registerctxluafile{lxml-lpt}{1.001} diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua index c3ec2370a..983d631e9 100644 --- a/tex/context/base/lxml-lpt.lua +++ b/tex/context/base/lxml-lpt.lua @@ -145,17 +145,19 @@ apply_axis['child'] = function(list) for l=1,#list do local ll = list[l] local dt = ll.dt - local en = 0 - for k=1,#dt do - local dk = dt[k] - if dk.tg then - collected[#collected+1] = dk - dk.ni = k -- refresh - en = en + 1 - dk.ei = en + if dt then -- weird that this is needed + local en = 0 + for k=1,#dt do + local dk = dt[k] + if dk.tg then + collected[#collected+1] = dk + dk.ni = k -- refresh + en = en + 1 + dk.ei = en + end end + ll.en = en end - ll.en = en end return collected end diff --git a/tex/context/base/lxml-xml.lua b/tex/context/base/lxml-xml.lua index f791ec0f8..6080e4207 100644 --- a/tex/context/base/lxml-xml.lua +++ b/tex/context/base/lxml-xml.lua @@ -10,6 +10,7 @@ local finalizers = xml.finalizers.xml local xmlfilter = xml.filter -- we could inline this one for speed local xmltostring = xml.tostring local xmlserialize = xml.serialize +local xmlcollected = xml.collected local function first(collected) -- wrong ? return collected and collected[1] @@ -286,3 +287,16 @@ end xml.all = xml.filter xml.index = xml.position xml.found = xml.filter + +-- a nice one: + +local function totable(x) + local t = { } + for e in xmlcollected(x[1] or x,"/*") do + t[e.tg] = xmltostring(e.dt) or "" + end + return next(t) and t or nil +end + +xml.table = totable +finalizers.table = totable diff --git a/tex/context/base/m-punk.mkiv b/tex/context/base/m-punk.mkiv index 6099ee6f4..3ea738003 100644 --- a/tex/context/base/m-punk.mkiv +++ b/tex/context/base/m-punk.mkiv @@ -17,190 +17,195 @@ % ConTeXt MkIV kernel. \startluacode -do - local concat = table.concat - local chardata = characters.data - local fontdata = fonts.ids +local concat = table.concat +local chardata = characters.data +local fontdata = fonts.ids - fonts.mp = fonts.mp or { } +fonts.mp = fonts.mp or { } - fonts.mp.version = fonts.mp.version or 1.11 - fonts.mp.inline = true - fonts.mp.cache = containers.define("fonts", "mp", fonts.mp.version, true) +fonts.mp.version = fonts.mp.version or 1.15 +fonts.mp.inline = true +fonts.mp.cache = containers.define("fonts", "mp", fonts.mp.version, true) - metapost.characters = metapost.characters or { } +metapost.characters = metapost.characters or { } -- todo: use table share as in otf - local characters, descriptions = { }, { } - local factor, l, n, w, h, d, total, variants = 100, { }, 0, 0, 0, 0, 0, 0, true - - -- A next version of mplib will provide the tfm font information which - -- gives better glyph dimensions, plus additional kerning information. - - local flusher = { - startfigure = function(chrnum,llx,lly,urx,ury) - l, n = { }, chrnum - w, h, d = urx - llx, ury, -lly - total = total + 1 - inline = fonts.mp.inline - end, - flushfigure = function(t) - for i=1, #t do - l[#l+1] = t[i] - end - end, - stopfigure = function() - local cd = chardata[n] - if inline then - descriptions[n] = { - -- unicode = n, - name = cd and cd.adobename, - width = w*100, - height = h*100, - depth = d*100, - boundingbox = { 0, -d, w, h }, - } - characters[n] = { - commands = { -- todo: xforms, should happen in backend - { "special", "pdf: " .. concat(l," ") }, - } - } - else - descriptions[n] = { - -- unicode = n, - name = cd and cd.adobename, - width = w*100, - height = h*100, - depth = d*100, - boundingbox = { 0, -d, w, h }, - } - characters[n] = { - commands = { - { "image", { stream = concat(l," "), bbox = { 0, -d*65536, w*65536, h*65536 } } }, - } - } - end +local characters, descriptions = { }, { } +local factor, l, n, w, h, d, total, variants = 100, { }, 0, 0, 0, 0, 0, 0, true + +-- A next version of mplib will provide the tfm font information which +-- gives better glyph dimensions, plus additional kerning information. + +local flusher = { + startfigure = function(chrnum,llx,lly,urx,ury) + l, n = { }, chrnum + w, h, d = urx - llx, ury, -lly + total = total + 1 + inline = fonts.mp.inline + end, + flushfigure = function(t) + for i=1, #t do + l[#l+1] = t[i] end - } - - metapost.characters.instances = metapost.characters.instances or 10 - - function metapost.characters.process(mpxformat, name, instances, scalefactor) - statistics.starttiming(metapost.characters) - scalefactor = scalefactor or 1 - instances = instances or metapost.characters.instances or 10 - local fontname = file.removesuffix(file.basename(name)) - local hash = file.robustname(string.format("%s %05i %03i", fontname, scalefactor*1000, instances)) - local lists = containers.read(fonts.mp.cache, hash) - if not lists then - statistics.starttiming(flusher) - -- we can use a format per font - local data = io.loaddata(resolvers.find_file(name)) - metapost.reset(mpxformat) - metapost.set_outer_color(2) -- no outer color and no reset either - lists = { } - for i=1,instances do - list = { } - characters, descriptions = { }, { } - metapost.process( - mpxformat, - { - "randomseed := " .. i*10 .. ";", - "scale_factor := " .. scalefactor .. " ;", - data - }, - false, - flusher - ) - lists[i] = { - designsize = 655360, - name = string.format("%s-%03i",hash,i), - parameters = { - slant = 0, - space = 333 * scalefactor, - space_stretch = 166.5 * scalefactor, - space_shrink = 111 * scalefactor, - x_height = 431 * scalefactor, - quad =1000 * scalefactor, - extra_space = 0 - }, - ["type"] = "virtual", - characters = characters, - descriptions = descriptions, - -- embedding = "subset", - -- mkiv: - spacer = "space", - unit = 1000, - shared = { }, - unique = { }, + end, + stopfigure = function() + local cd = chardata[n] + if inline then + descriptions[n] = { + -- unicode = n, + name = cd and cd.adobename, + width = w*100, + height = h*100, + depth = d*100, + boundingbox = { 0, -d, w, h }, + } + characters[n] = { + commands = { -- todo: xforms, should happen in backend + { "special", "pdf: " .. concat(l," ") }, } - end - metapost.reset(mpxformat) -- saves memory - lists = containers.write(fonts.mp.cache, hash, lists) - statistics.stoptiming(flusher) + } + else + descriptions[n] = { + -- unicode = n, + name = cd and cd.adobename, + width = w*100, + height = h*100, + depth = d*100, + boundingbox = { 0, -d, w, h }, + } + characters[n] = { + commands = { + { "image", { stream = concat(l," "), bbox = { 0, -d*65536, w*65536, h*65536 } } }, + } + } end - variants = variants + #lists - statistics.stoptiming(metapost.characters) - return lists end - - function fonts.vf.aux.combine.commands.metafont(g,v) - local size = g.specification.size - local data = metapost.characters.process(v[2],v[3],v[4],size/655360) - local list, t = { }, { } - for d=1,#data do - t = data[d] - t = fonts.tfm.scale(t, -1000) - local id = font.nextid() - t.fonts = { { id = id } } - fontdata[id] = t - fonts.vf.aux.compose_characters(t) - list[d] = font.define(t) +} + +metapost.characters.instances = metapost.characters.instances or 10 + +function metapost.characters.process(mpxformat, name, instances, scalefactor) + statistics.starttiming(metapost.characters) + scalefactor = scalefactor or 1 + instances = instances or metapost.characters.instances or 10 + local fontname = file.removesuffix(file.basename(name)) + local hash = file.robustname(string.format("%s %05i %03i", fontname, scalefactor*1000, instances)) + local lists = containers.read(fonts.mp.cache, hash) + if not lists then + statistics.starttiming(flusher) + -- we can use a format per font + local data = io.loaddata(resolvers.find_file(name)) + metapost.reset(mpxformat) + metapost.set_outer_color(2) -- no outer color and no reset either + lists = { } + for i=1,instances do + characters, descriptions = { }, { } + metapost.process( + mpxformat, + { + "randomseed := " .. i*10 .. ";", + "scale_factor := " .. scalefactor .. " ;", + data + }, + false, + flusher + ) + lists[i] = { + designsize = 655360, + name = string.format("%s-%03i",hash,i), + parameters = { + slant = 0, + space = 333 * scalefactor, + space_stretch = 166.5 * scalefactor, + space_shrink = 111 * scalefactor, + x_height = 431 * scalefactor, + quad =1000 * scalefactor, + extra_space = 0 + }, + ["type"] = "virtual", + characters = characters, + descriptions = descriptions, + -- embedding = "subset", + -- mkiv: + spacer = "space", + unit = 1000, + shared = { }, + unique = { }, + } end - for k=1,#t do - g[k] = t[k] -- kind of replace, when not present, make nil - end - g.virtualized = true - g.variants = list + metapost.reset(mpxformat) -- saves memory + lists = containers.write(fonts.mp.cache, hash, lists) + statistics.stoptiming(flusher) end + variants = variants + #lists + statistics.stoptiming(metapost.characters) + return lists +end - fonts.define.methods.install( "punk", { - { "metafont", "mfplain", "punkfont.mp", 10 }, - } ) - - typesetting.cases.actions[99] = function(current) - local used = fontdata[current.font].variants - if used then - local f = math.random(1,#used) - current.font = used[f] - return current, true - else - return current, false - end +function fonts.vf.aux.combine.commands.metafont(g,v) + local size = g.specification.size + local data = metapost.characters.process(v[2],v[3],v[4],size/655360) + local list, t = { }, { } + for d=1,#data do + t = data[d] + t = fonts.tfm.scale(t, -1000) + local id = font.nextid() + t.fonts = { { id = id } } + fontdata[id] = t + fonts.vf.aux.compose_characters(t) + list[d] = font.define(t) end + for k, v in next, t do + g[k] = v -- kind of replace, when not present, make nil + end + g.virtualized = true + g.variants = list +end - metapost.characters.flusher = flusher - - statistics.register("metapost font generation", function() - local time = statistics.elapsedtime(flusher) - if total > 0 then - return string.format("%i glyphs, %.3f seconds runtime, %i glyphs/second", total, time, total/time) - else - return string.format("%i glyphs, %.3f seconds runtime", total, time) - end - end) +fonts.define.methods.install( "punk", { + { "metafont", "mfplain", "punkfont.mp", 10 }, +} ) +fonts.define.methods.install( "punkbold", { + { "metafont", "mfplain", "punkfont-bold.mp", 10 }, +} ) +fonts.define.methods.install( "punkslanted", { + { "metafont", "mfplain", "punkfont-slanted.mp", 10 }, +} ) +fonts.define.methods.install( "punkboldslanted", { + { "metafont", "mfplain", "punkfont-boldslanted.mp", 10 }, +} ) + +typesetting.cases.actions[99] = function(current) + local used = fontdata[current.font].variants + if used then + local f = math.random(1,#used) + current.font = used[f] + return current, true + else + return current, false + end +end - statistics.register("metapost font loading",function() - local time = statistics.elapsedtime(metapost.characters) - if variants > 0 then - return string.format("%.3f seconds, %i instances, %0.3f instances/second", time, variants, variants/time) - else - return string.format("%.3f seconds, %i instances", time, variants) - end - end) +metapost.characters.flusher = flusher -end +statistics.register("metapost font generation", function() + local time = statistics.elapsedtime(flusher) + if total > 0 then + return string.format("%i glyphs, %.3f seconds runtime, %i glyphs/second", total, time, total/time) + else + return string.format("%i glyphs, %.3f seconds runtime", total, time) + end +end) + +statistics.register("metapost font loading",function() + local time = statistics.elapsedtime(metapost.characters) + if variants > 0 then + return string.format("%.3f seconds, %i instances, %0.3f instances/second", time, variants, variants/time) + else + return string.format("%.3f seconds, %i instances", time, variants) + end +end) \stopluacode \unexpanded\def\EnableRandomPunk {\setcharactercasing[99]} @@ -209,25 +214,18 @@ end \unexpanded\def\StopRandomPunk {\endgroup} \starttypescript [serif] [punk] [default] - \setups[font:fallback:serif] % no style variants yet - \definefontsynonym [Serif] [demo@punk] + \definefontsynonym [Serif] [demo@punk] + \definefontsynonym [SerifBold] [demobold@punkbold] + \definefontsynonym [SerifSlanted] [demoslanted@punkslanted] + \definefontsynonym [SerifBoldSlanted] [demoboldslanted@punkboldslanted] + \definefontsynonym [SerifItalic] [SerifSlanted] + \definefontsynonym [SerifBoldItalic] [SerifBoldSlanted] \stoptypescript \starttypescript [punk] \definetypeface [punk] [rm] [serif] [punk] [default] \stoptypescript -% \definefontfeature[punknova][mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes] - -% \starttypescript [serif] [punknova] -% \setups[font:fallback:serif] % no style variants yet, actually it's a sans -% \definefontsynonym [Serif] [file:punknova] [features=punknova] -% \stoptypescript - -% \starttypescript [punknova] -% \definetypeface [punknova] [rm] [serif] [punknova] [default] -% \stoptypescript - \endinput \usetypescript[punk] diff --git a/tex/context/base/m-units.tex b/tex/context/base/m-units.tex index d186c542b..36fa45d84 100644 --- a/tex/context/base/m-units.tex +++ b/tex/context/base/m-units.tex @@ -377,6 +377,17 @@ \def\Peta {\dimensionprefix{P}} \def\Exa {\dimensionprefix{E}} +%D and binary prefixes: + +\def\Kibi {\dimensionprefix{Ki}} +\def\Mebi {\dimensionprefix{Mi}} +\def\Gibi {\dimensionprefix{Gi}} +\def\Tebi {\dimensionprefix{Ti}} +\def\Pebi {\dimensionprefix{Pi}} +\def\Exbi {\dimensionprefix{Ei}} +\def\Zebi {\dimensionprefix{Zi}} +\def\Yobi {\dimensionprefix{Yi}} + %D and operators: \def\Times {\dimensionnopfix{\iftextdimensions.\else\cdot\fi}} @@ -384,7 +395,7 @@ \def\Per {\dimensionmidfix{/}} \def\OutOf {\dimensionnopfix{:}} -%D and suffixes: +%D and suffixes: \def\Linear {\dimensionpower{1}} \def\Square {\dimensionpower{2}} @@ -665,10 +676,10 @@ %D Computer memory is specified in Bytes: -\getvalue{\v!unit} [Baud] {Baud} {Baud (Bit/s)} -\getvalue{\v!unit} [Bit] {Bit} {Bit} +\getvalue{\v!unit} [Bit] {bit} {Bit} +\getvalue{\v!unit} [Baud] {Bd} {Baud (Bit/s)} -\getvalue{\v!unit} [Byte] {Byte} {Byte} +\getvalue{\v!unit} [Byte] {B} {Byte} \getvalue{\v!unit} [kByte] {\Kilo \Byte} {kilo Byte} \getvalue{\v!unit} [MByte] {\Mega \Byte} {mega Byte} \getvalue{\v!unit} [GByte] {\Giga \Byte} {giga Byte} diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua index 2b4f9b6fa..19cc94ea7 100644 --- a/tex/context/base/math-noa.lua +++ b/tex/context/base/math-noa.lua @@ -19,6 +19,7 @@ local has_attribute = node.has_attribute local mlist_to_hlist = node.mlist_to_hlist local font_of_family = node.family_font local fontdata = fonts.identifiers +local nodecodes = nodes.nodecodes local format, rep = string.format, string.rep local utfchar, utfbyte = utf.char, utf.byte @@ -31,6 +32,8 @@ local trace_analyzing = false trackers.register("math.analyzing", function(v) local report_noads = logs.new("mathematics") +-- todo: nodes.noadcodes + local noad_ord = 0 local noad_op_displaylimits = 1 local noad_op_limits = 2 @@ -47,34 +50,34 @@ local noad_vcenter = 12 -- obsolete: -- --- math_ord = node.id("ord") -- attr nucleus sub sup --- math_op = node.id("op") -- attr nucleus sub sup subtype --- math_bin = node.id("bin") -- attr nucleus sub sup --- math_rel = node.id("rel") -- attr nucleus sub sup --- math_punct = node.id("punct") -- attr nucleus sub sup --- --- math_open = node.id("open") -- attr nucleus sub sup --- math_close = node.id("close") -- attr nucleus sub sup --- --- math_inner = node.id("inner") -- attr nucleus sub sup --- math_vcenter = node.id("vcenter") -- attr nucleus sub sup --- math_under = node.id("under") -- attr nucleus sub sup --- math_over = node.id("over") -- attr nucleus sub sup - -local math_noad = node.id("noad") -- attr nucleus sub sup - -local math_accent = node.id("accent") -- attr nucleus sub sup accent -local math_radical = node.id("radical") -- attr nucleus sub sup left degree -local math_fraction = node.id("fraction") -- attr nucleus sub sup left right - -local math_box = node.id("sub_box") -- attr list -local math_sub = node.id("sub_mlist") -- attr list -local math_char = node.id("math_char") -- attr fam char -local math_text_char = node.id("math_text_char") -- attr fam char -local math_delim = node.id("delim") -- attr small_fam small_char large_fam large_char -local math_style = node.id("style") -- attr style -local math_choice = node.id("choice") -- attr display text script scriptscript -local math_fence = node.id("fence") -- attr subtype +-- math_ord = nodecodes.ord") -- attr nucleus sub sup +-- math_op = nodecodes.op") -- attr nucleus sub sup subtype +-- math_bin = nodecodes.bin") -- attr nucleus sub sup +-- math_rel = nodecodes.rel") -- attr nucleus sub sup +-- math_punct = nodecodes.punct") -- attr nucleus sub sup +--_ +-- math_open = nodecodes.open") -- attr nucleus sub sup +-- math_close = nodecodes.close") -- attr nucleus sub sup +--_ +-- math_inner = nodecodes.inner") -- attr nucleus sub sup +-- math_vcenter = nodecodes.vcenter") -- attr nucleus sub sup +-- math_under = nodecodes.under") -- attr nucleus sub sup +-- math_over = nodecodes.over") -- attr nucleus sub sup + +local math_noad = nodecodes.noad -- attr nucleus sub sup + +local math_accent = nodecodes.accent -- attr nucleus sub sup accent +local math_radical = nodecodes.radical -- attr nucleus sub sup left degree +local math_fraction = nodecodes.fraction -- attr nucleus sub sup left right + +local math_box = nodecodes.sub_box -- attr list +local math_sub = nodecodes.sub_mlist -- attr list +local math_char = nodecodes.math_char -- attr fam char +local math_text_char = nodecodes.math_text_char -- attr fam char +local math_delim = nodecodes.delim -- attr small_fam small_char large_fam large_char +local math_style = nodecodes.style -- attr style +local math_choice = nodecodes.choice -- attr display text script scriptscript +local math_fence = nodecodes.fence -- attr subtype local simple_noads = table.tohash { math_noad, @@ -366,7 +369,7 @@ end fonts.otf.tables.features['mathalternates'] = 'Additional math alternative shapes' -fonts.otf.features.register('mathalternates',true) +fonts.otf.features.register('mathalternates') -- true table.insert(fonts.triggers,"mathalternates") fonts.initializers.base.otf.mathalternates = fonts.initializers.common.mathalternates diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua index 7180435f5..7960c014f 100644 --- a/tex/context/base/math-tag.lua +++ b/tex/context/base/math-tag.lua @@ -9,26 +9,27 @@ if not modules then modules = { } end modules ['math-tag'] = { local has_attribute = nodes.has_attribute local set_attribute = nodes.set_attribute local set_attributes = nodes.set_attributes - local traverse_nodes = node.traverse -local math_noad = node.id("noad") -- attr nucleus sub sup -local math_noad = node.id("noad") -- attr nucleus sub sup -local math_accent = node.id("accent") -- attr nucleus sub sup accent -local math_radical = node.id("radical") -- attr nucleus sub sup left degree -local math_fraction = node.id("fraction") -- attr nucleus sub sup left right -local math_box = node.id("sub_box") -- attr list -local math_sub = node.id("sub_mlist") -- attr list -local math_char = node.id("math_char") -- attr fam char -local math_text_char = node.id("math_text_char") -- attr fam char -local math_delim = node.id("delim") -- attr small_fam small_char large_fam large_char -local math_style = node.id("style") -- attr style -local math_choice = node.id("choice") -- attr display text script scriptscript -local math_fence = node.id("fence") -- attr subtype +local nodecodes = nodes.nodecodes + +local math_noad = nodecodes.noad -- attr nucleus sub sup +local math_noad = nodecodes.noad -- attr nucleus sub sup +local math_accent = nodecodes.accent -- attr nucleus sub sup accent +local math_radical = nodecodes.radical -- attr nucleus sub sup left degree +local math_fraction = nodecodes.fraction -- attr nucleus sub sup left right +local math_box = nodecodes.sub_box -- attr list +local math_sub = nodecodes.sub_mlist -- attr list +local math_char = nodecodes.math_char -- attr fam char +local math_text_char = nodecodes.math_text_char -- attr fam char +local math_delim = nodecodes.delim -- attr small_fam small_char large_fam large_char +local math_style = nodecodes.style -- attr style +local math_choice = nodecodes.choice -- attr display text script scriptscript +local math_fence = nodecodes.fence -- attr subtype -local hlist = node.id("hlist") -local vlist = node.id("vlist") -local glyph = node.id("glyph") +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local glyph = nodecodes.glyph local a_tagged = attributes.private('tagged') diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv index 1072cb8f2..c44be4282 100644 --- a/tex/context/base/meta-ini.mkiv +++ b/tex/context/base/meta-ini.mkiv @@ -199,36 +199,10 @@ {\let\handleuseMPgraphic \thirdofthreearguments \let\handlereusableMPgraphic\thirdofthreearguments} -\let\MPdrawingdata\empty - \newif\ifMPdrawingdone \MPdrawingdonefalse -\def\resetMPdrawing - {\globallet\MPdrawingdata\empty - \global\MPdrawingdonefalse} - -\def\pushMPdrawing - {\globalpushmacro\MPdrawingdata - \globallet\MPdrawingdata\empty} - -\def\popMPdrawing - {\globalpopmacro\MPdrawingdata} - -\def\getMPdrawing{\dosinglegroupempty\dogetMPdrawing} - -\def\startMPdrawing - {\dosingleempty\dostartMPdrawing} - -\long\def\dostartMPdrawing[#1]#2\stopMPdrawing - {\relax - \bgroup - \enableincludeMPgraphics - \presetMPdefinitions % in case #2 has measures - \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}% - \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}% - \egroup} - -\let\stopMPdrawing\relax +\def\finalizeMPdrawing + {\MPdrawingdonetrue} \let\MPdrawingdata\empty @@ -264,6 +238,14 @@ \let\stopMPdrawing\relax +\long\def\MPdrawing#1% + {\relax + \bgroup + \enableincludeMPgraphics + \presetMPdefinitions + \long\xdef\MPdrawingdata{\MPdrawingdata#1}% + \egroup} + \let\stopMPclip\relax \long\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less @@ -771,6 +753,23 @@ \let\stopMPcode\relax +\def\MPcode{\dosinglegroupempty\doMPcode} + +\def\doMPcode + {\iffirstargument + \expandafter\dodoMPcode + \else + \expandafter\nodoMPcode + \fi} + +\def\dodoMPcode#1#2% + {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter + \processMPgraphic{#2}% + \endMPgraphicgroup} + +\def\nodoMPcode#1#2% + {\processMPgraphic{#2}} + % a bit nasty (also needed for compatibility: % \startMPrun input mp-www.mp ; \stopMPrun diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index f00c99cdb..9d6b4eb7a 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -278,23 +278,12 @@ end -- -- normalize(ca,cb) fails for spotcolors -function metapost.specials.cs(specification,object,result,flusher) -- spot colors? - -- a mess, not dynamic anyway - nofshades = nofshades + 1 - flusher.flushfigure(result) - result = { } - local t = lpegmatch(specificationsplitter,specification) - -- we need a way to move/scale - local ca = lpegmatch(colorsplitter,t[4]) - local cb = lpegmatch(colorsplitter,t[8]) +local function checkandconvert(ca,cb) + local name = format("MpSh%s",nofshades) if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end - local name = format("MplSh%s",nofshades) - local domain = { tonumber(t[1]), tonumber(t[2]) } - local coordinates = { tonumber(t[5]), tonumber(t[6]), tonumber(t[7]), tonumber(t[9]), tonumber(t[10]), tonumber(t[11]) } if type(ca) == "string" then - -- backend specific (will be renamed) - lpdf.circularshade(name,domain,{ 0 },{ 1 },1,"DeviceGray",coordinates) + return { 0 }, { 1 }, "DeviceGray", name else if #ca > #cb then normalize(ca,cb) @@ -307,38 +296,43 @@ function metapost.specials.cs(specification,object,result,flusher) -- spot color end if model == "rgb" then if #ca == 4 then - ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4]) - cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4]) - ca[4], cb[4] = nil, nil + ca = { cmyktorgb(ca[1],ca[2],ca[3],ca[4]) } + cb = { cmyktorgb(cb[1],cb[2],cb[3],cb[4]) } elseif #ca == 1 then local a, b = 1-ca[1], 1-cb[1] - ca[1], ca[2], ca[3] = a, a, a - cb[1], cb[2], cb[3] = b, b, b + ca = { a, a, a } + cb = { b, b, b } end - -- backend specific (will be renamed) - lpdf.circularshade(name,domain,ca,cb,1,"DeviceRGB",coordinates) + return ca, cb, "DeviceRGB", name elseif model == "cmyk" then if #ca == 3 then - ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3]) - cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3]) + ca = { rgbtocmyk(ca[1],ca[2],ca[3]) } + cb = { rgbtocmyk(cb[1],cb[2],cb[3]) } elseif #ca == 1 then - ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1] - cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1] + ca = { 0, 0, 0, ca[1] } + cb = { 0, 0, 0, ca[1] } end - -- backend specific (will be renamed) - lpdf.circularshade(name,domain,ca,cb,1,"DeviceCMYK",coordinates) + return ca, cb, "DeviceCMYK", name else if #ca == 4 then - ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4]) - cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4]) + ca = { cmyktogray(ca[1],ca[2],ca[3],ca[4]) } + cb = { cmyktogray(cb[1],cb[2],cb[3],cb[4]) } elseif #ca == 3 then - ca[1] = rgbtogray(ca[1],ca[2],ca[3]) - cb[1] = rgbtogray(cb[1],cb[2],cb[3]) + ca = { rgbtogray(ca[1],ca[2],ca[3]) } + cb = { rgbtogray(cb[1],cb[2],cb[3]) } end -- backend specific (will be renamed) - lpdf.circularshade(name,domain,ca,cb,1,"DeviceGRAY",coordinates) + return ca, cb, "DeviceGray", name end end +end + +local function resources(object,name,flusher,result) + -- There is no real need for flushing in between, so: + -- + -- flusher.flushfigure(result) + -- local result = { } + -- local before = function() result[#result+1] = "q /Pattern cs" return object, result @@ -351,75 +345,30 @@ function metapost.specials.cs(specification,object,result,flusher) -- spot color return object, before, nil, after end +-- todo: we need a way to move/scale + +function metapost.specials.cs(specification,object,result,flusher) -- spot colors? + nofshades = nofshades + 1 + local t = lpegmatch(specificationsplitter,specification) + local ca = lpegmatch(colorsplitter,t[4]) + local cb = lpegmatch(colorsplitter,t[8]) + local domain = { tonumber(t[1]), tonumber(t[2]) } + local coordinates = { tonumber(t[5]), tonumber(t[6]), tonumber(t[7]), tonumber(t[9]), tonumber(t[10]), tonumber(t[11]) } + local ca, cb, colorspace, name = checkandconvert(ca,cb) + lpdf.circularshade(name,domain,ca,cb,1,colorspace,coordinates) -- backend specific (will be renamed) + return resources(object,name,flusher,result) -- object, before, nil, after +end + function metapost.specials.ls(specification,object,result,flusher) nofshades = nofshades + 1 - flusher.flushfigure(result) - result = { } local t = lpegmatch(specificationsplitter,specification) - -- we need a way to move/scale local ca = lpegmatch(colorsplitter,t[4]) local cb = lpegmatch(colorsplitter,t[7]) - if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end - if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end - local name = format("MpSh%s",nofshades) local domain = { tonumber(t[1]), tonumber(t[2]) } local coordinates = { tonumber(t[5]), tonumber(t[6]), tonumber(t[8]), tonumber(t[9]) } - if type(ca) == "string" then - -- backend specific (will be renamed) - lpdf.linearshade(name,domain,{ 0 },{ 1 },1,"DeviceGray",coordinates) - else - if #ca > #cb then - normalize(ca,cb) - elseif #ca < #cb then - normalize(cb,ca) - end - local model = colors.model - if model == "all" then - model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray" - end - if model == "rgb" then - if #ca == 4 then - ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4]) - cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4]) - elseif #ca == 1 then - local a, b = 1-ca[1], 1-cb[1] - ca[1], ca[2], ca[3] = a, a, a - cb[1], cb[2], cb[3] = b, b, b - end - -- backend specific (will be renamed) - lpdf.linearshade(name,domain,ca,cb,1,"DeviceRGB",coordinates) - elseif model == "cmyk" then - if #ca == 3 then - ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3]) - cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3]) - elseif #ca == 1 then - ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1] - cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1] - end - -- backend specific (will be renamed) - lpdf.linearshade(name,domain,ca,cb,1,"DeviceCMYK",coordinates) - else - if #ca == 4 then - ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4]) - cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4]) - elseif #ca == 3 then - ca[1] = rgbtogray(ca[1],ca[2],ca[3]) - cb[1] = rgbtogray(cb[1],cb[2],cb[3]) - end - -- backend specific (will be renamed) - lpdf.linearshade(name,domain,ca,cb,1,"DeviceGRAY",coordinates) - end - end - local before = function() - result[#result+1] = "q /Pattern cs" - return object, result - end - local after = function() - result[#result+1] = format("W n /%s sh Q", name) - return object, result - end - object.color, object.type = nil, nil - return object, before, nil, after + local ca, cb, colorspace, name = checkandconvert(ca,cb) + lpdf.linearshade(name,domain,ca,cb,1,colorspace,coordinates) -- backend specific (will be renamed) + return resources(object,name,flusher,result) -- object, before, nil, after end -- no need for a before here diff --git a/tex/context/base/mult-aux.mkiv b/tex/context/base/mult-aux.mkiv new file mode 100644 index 000000000..c364c3507 --- /dev/null +++ b/tex/context/base/mult-aux.mkiv @@ -0,0 +1,165 @@ +%D \module +%D [ file=mult-aux, +%D version=2010.08.2, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=Definitions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright=PRAGMA] +%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 A generalization of \MKIV-like inheritance. Just something to play +%D with (interface might change). + +\unprotect + +%D \starttyping +%D \unprotect +%D \def\????aa{@@@@aa} +%D +%D \installparameterhandler \????aa {whatever} +%D \installsetuphandler \????aa {whatever} +%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot +%D \installattributehandler \????aa {whatever} +%D +%D % \installcommandhandler \????aa {whatever} \????aa +%D \protect +%D +%D % \whateverparameter \c!test +%D % \whateverparameterhash \c!test +%D % \namedwhateverparameter \mycurrentwhatever \c!test +%D % \dosetwhateverattributes \c!style \c!color +%D % \everydefinewhatever (sets \currentwhatever) +%D % \everypresetwhatever (can be used to reset parameters as we can redefine) +%D % \everysetupwhatever (sets \currentwhatever) +%D +%D \starttext +%D \definewhatever[first] \definewhatever[second][first] +%D test: \def\currentwhatever{first} \whateverparameter{method} \par +%D \setupwhatever [method=unset] test: \def\currentwhatever{first} \whateverparameter{method} \par +%D \setupwhatever[first] [method=first] test: \def\currentwhatever{first} \whateverparameter{method} \par +%D test: \def\currentwhatever{second} \whateverparameter{method} \par +%D \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par +%D \stoptext +%D \stoptyping + +% problem: every* could clash + +% faster but assumes \c!always +% +% \unexpanded\def\doinstallparameterhandler#1#2#3#4#5#6#7#8#9% \??aa {whatever} \current.. +% {\def#3##1{\csname#6{#1#2}##1\endcsname}% +% \def#4##1{#7{#1#2}##1}% +% \def#5##1##2{\csname#6{#1##2}##1\endcsname}% +% \def#6##1##2{\ifcsname##1##2\endcsname##1##2\else\expandafter#8\csname##1\s!parent\endcsname##2\fi}% +% \def#7##1##2{\ifcsname##1##2\endcsname ##1\else\expandafter#9\csname##1\s!parent\endcsname##2\fi}% +% \def#8##1##2{\ifx##1\relax\s!empty\else#6{##1}##2\fi}% +% \def#9##1##2{\ifx##1\relax \else#7{##1}##2\fi}} + +\unexpanded\def\doinstallparameterhandler#1#2#3#4#5#6#7#8#9% \??aa {whatever} \current.. + {\def#3##1{\csname#6{#1#2}{##1}\endcsname}% + \def#4##1{#7{#1#2}{##1}}% + \def#5##1##2{\csname#6{#1##1}{##2}\endcsname}% + \def#6##1##2{\ifcsname##1##2\endcsname##1##2\else\expandafter#8\csname##1\s!parent\endcsname{##2}\fi}% + \def#7##1##2{\ifcsname##1##2\endcsname ##1\else\expandafter#9\csname##1\s!parent\endcsname{##2}\fi}% + \def#8##1##2{\ifx##1\relax\s!empty\else#6{##1}{##2}\fi}% + \def#9##1##2{\ifx##1\relax \else#7{##1}{##2}\fi}} + +% todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root + +\def\installparameterhandler#1#2% + {\normalexpanded + {\doinstallparameterhandler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname #2parameter\endcsname % can move + \expandafter\noexpand\csname #2parameterhash\endcsname % can move + \expandafter\noexpand\csname named#2parameter\endcsname % can move + \expandafter\noexpand\csname do#2parameter\endcsname + \expandafter\noexpand\csname do#2parameterhash\endcsname + \expandafter\noexpand\csname do#2parentparameter\endcsname + \expandafter\noexpand\csname do#2parentparameterhash\endcsname}} + +% faster but assumes \c!always +% +% \unexpanded\def\doinstallattributehandler#1#2#3% #1 not used here +% {\expandafter\def\csname doset#2attributes\endcsname##1##2% style color +% {\edef\fontattributehash {#3##1}% +% \edef\colorattributehash{#3##2}% +% \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash ##1\fi +% \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash##2\fi}} + +\unexpanded\def\doinstallattributehandler#1#2#3% #1 not used here + {\expandafter\def\csname doset#2attributes\endcsname##1##2% style color + {\edef\fontattributehash {#3{##1}}% + \edef\colorattributehash{#3{##2}}% + \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash {##1}\fi + \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash{##2}\fi}} + +\def\installattributehandler#1#2% + {\normalexpanded + {\doinstallattributehandler + {\noexpand#1}% \??aa + {\noexpand#2}% whatever + \expandafter\noexpand\csname #2parameterhash\endcsname}} + +\unexpanded\def\doinstalldefinehandler#1#2#3#4#5#6#7% + {\unexpanded\expandafter\def\csname define#2\endcsname{\dodoubleempty#5}% + \expandafter\newtoks\csname everydefine#2\endcsname + \def#5[##1][##2]% + {\edef#4{##1}% + \the#6% predefine + \ifsecondargument + \getparameters[#1#4][\s!parent=#1,##2]% + \else + \getparameters[#1#4][\s!parent=#3]% + \fi + \the#7}} + +\def\installdefinehandler#1#2#3% + {\normalexpanded + {\doinstalldefinehandler + {\noexpand#1}% \??aa + {#2}% whatever + {#3}% root + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname dodefine#2\endcsname + \expandafter\noexpand\csname everypreset#2\endcsname + \expandafter\noexpand\csname everydefine#2\endcsname}} + +\unexpanded\def\doinstallsetuphandler#1#2#3#4#5% + {\unexpanded\expandafter\def\csname setup#2\endcsname{\dodoubleempty#4}% + \expandafter\newtoks\csname everysetup#2\endcsname + \def#4[##1][##2]% + {\ifsecondargument + \def\docommand####1% we will have a simple one as well + {\edef#3{##1#1}% + \getparameters[#1#3][##2]% + \the#5}% + \processcommalist[##1]\docommand + \else + \let#3\empty + \getparameters[#1][##1]% + \the#5% + \fi}} + +\def\installsetuphandler#1#2% + {\normalexpanded + {\doinstallsetuphandler + {\noexpand#1}% \??aa + {#2}% whatever + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname dosetup#2\endcsname + \expandafter\noexpand\csname everysetup#2\endcsname}} + +\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) + {\installparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}#3% + \installsetuphandler {#1}{#2}% + \installattributehandler{#1}{#2}} + +\protect + diff --git a/tex/context/base/mult-cld.lua b/tex/context/base/mult-cld.lua index a9fb1ff1c..9e7f94287 100644 --- a/tex/context/base/mult-cld.lua +++ b/tex/context/base/mult-cld.lua @@ -19,10 +19,10 @@ if not modules then modules = { } end modules ['mult-cld'] = { context = context or { } local format, concat = string.format, table.concat -local next, type = next, type +local next, type, tostring = next, type, tostring local texsprint, texiowrite, ctxcatcodes = tex.sprint, texio.write, tex.ctxcatcodes -local flush = texsprint or function(cct,...) print(table.concat{...}) end +local flush = texsprint or function(cct,...) print(concat{...}) end local _stack_, _n_ = { }, 0 @@ -64,7 +64,7 @@ trackers.register("context.intercept", function(v) if v then context.trace(true) local trace_context = logs.new("context") -local function writer(k,...) +local function writer(k,...) -- we can optimize for 1 argument if k then flush(ctxcatcodes,k) local t = { ... } @@ -75,8 +75,6 @@ local function writer(k,...) local typ = type(ti) if ti == nil then -- next - elseif typ == "function" then - flush(ctxcatcodes,"{\\mkivflush{" .. _store_(ti) .. "}}") elseif typ == "string" or typ == "number" then flush(ctxcatcodes,"{",ti,"}") elseif typ == "table" then @@ -102,6 +100,8 @@ local function writer(k,...) end flush(ctxcatcodes,"]") end + elseif typ == "function" then + flush(ctxcatcodes,"{\\mkivflush{" .. _store_(ti) .. "}}") -- elseif typ == "boolean" then -- flush(ctxcatcodes,"\n") elseif ti == true then @@ -120,6 +120,77 @@ local function writer(k,...) end end +local function newwriter(command,first,...) -- 5% faster than just ... and separate flush of command + if not command then + -- error + elseif not first then + flush(ctxcatcodes,command) + else + local t = { first, ... } + for i=1,#t do + if i == 2 then + command = "" + end + local ti = t[i] + local typ = type(ti) + if ti == nil then + flush(ctxcatcodes,command) + elseif typ == "string" or typ == "number" then + flush(ctxcatcodes,command,"{",ti,"}") + elseif typ == "table" then + local tn = #ti + if tn == 0 then + local done = false + for k, v in next, ti do + if done then + flush(ctxcatcodes,",",k,'=',v) + else + flush(ctxcatcodes,command,"[",k,'=',v) + done = true + end + end + flush(ctxcatcodes,"]") + elseif tn == 1 then -- some 20% faster than the next loop + local tj = ti[1] + if type(tj) == "function" then + flush(ctxcatcodes,command,"[\\mkivflush{",_store_(tj),"}]") + else + flush(ctxcatcodes,command,"[",tj,"]") + end + else -- is concat really faster than flushes here? + for j=1,tn do + local tj = ti[j] + if type(tj) == "function" then + ti[j] = "\\mkivflush{" .. _store_(tj) .. "}" + end + end + flush(ctxcatcodes,command,"[",concat(ti,","),"]") + end + elseif typ == "function" then + flush(ctxcatcodes,command,"{\\mkivflush{",_store_(ti),"}}") + -- elseif typ == "boolean" then + -- flush(ctxcatcodes,"\n") + elseif ti == true then + flush(ctxcatcodes,command,"\n") + elseif typ == false then + -- if force == "direct" then + flush(ctxcatcodes,command,tostring(ti)) + -- end + elseif typ == "thread" then + flush(ctxcatcodes,command) + trace_context("coroutines not supported as we cannot yeild across boundaries") + else + flush(ctxcatcodes,command) + trace_context("error: %s gets a weird argument %s",command,tostring(ti)) + end + end + end +end + +experiments.register("context.writer",function() + writer = newwriter +end) + -- -- -- local function indexer(t,k) diff --git a/tex/context/base/mult-de.tex b/tex/context/base/mult-de.tex index 608fdb1f8..a924c0bec 100644 --- a/tex/context/base/mult-de.tex +++ b/tex/context/base/mult-de.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{fusszeile} \setinterfaceconstant{footerdistance}{fusszeilenabstand} \setinterfaceconstant{footerstate}{fusszeilenstatus} +\setinterfaceconstant{force}{zwinge} \setinterfaceconstant{foregroundcolor}{foregroundcolor} \setinterfaceconstant{foregroundstyle}{foregroundstyle} \setinterfaceconstant{format}{formatieren} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{vorige} \setinterfaceconstant{previousnumber}{vorigenummer} \setinterfaceconstant{process}{process} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{radius} \setinterfaceconstant{random}{zufaellig} diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua index d877ad0f2..1614301ac 100644 --- a/tex/context/base/mult-def.lua +++ b/tex/context/base/mult-def.lua @@ -7783,6 +7783,16 @@ return { ["pe"]="رنگ‌پیش‌زمینه", ["ro"]="foregroundcolor", }, + ["force"]={ + ["cs"]="sila", + ["de"]="zwinge", + ["en"]="force", + ["fr"]="force", + ["it"]="forza", + ["nl"]="forceer", + ["pe"]="اجبار", + ["ro"]="fortat", + }, ["foregroundstyle"]={ ["cs"]="foregroundstyle", ["de"]="foregroundstyle", @@ -9412,6 +9422,9 @@ return { ["pe"]="پردازش", ["ro"]="process", }, + ["profile"]={ + ["en"]="profile", + }, ["radius"]={ ["cs"]="polomer", ["de"]="radius", diff --git a/tex/context/base/mult-en.tex b/tex/context/base/mult-en.tex index cbaeb50d6..094678d1e 100644 --- a/tex/context/base/mult-en.tex +++ b/tex/context/base/mult-en.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{footer} \setinterfaceconstant{footerdistance}{footerdistance} \setinterfaceconstant{footerstate}{footerstate} +\setinterfaceconstant{force}{force} \setinterfaceconstant{foregroundcolor}{foregroundcolor} \setinterfaceconstant{foregroundstyle}{foregroundstyle} \setinterfaceconstant{format}{format} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{previous} \setinterfaceconstant{previousnumber}{previousnumber} \setinterfaceconstant{process}{process} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{radius} \setinterfaceconstant{random}{random} diff --git a/tex/context/base/mult-fr.tex b/tex/context/base/mult-fr.tex index 05b4ed1db..52dfab7e4 100644 --- a/tex/context/base/mult-fr.tex +++ b/tex/context/base/mult-fr.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{pdp} \setinterfaceconstant{footerdistance}{dsitancepdp} \setinterfaceconstant{footerstate}{etatpdp} +\setinterfaceconstant{force}{force} \setinterfaceconstant{foregroundcolor}{couleurpremierplan} \setinterfaceconstant{foregroundstyle}{stylepremierplan} \setinterfaceconstant{format}{formatter} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{precedent} \setinterfaceconstant{previousnumber}{numeroprecedent} \setinterfaceconstant{process}{process} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{rayon} \setinterfaceconstant{random}{aleatoire} diff --git a/tex/context/base/mult-it.tex b/tex/context/base/mult-it.tex index 5bac8d0b0..fe9534c08 100644 --- a/tex/context/base/mult-it.tex +++ b/tex/context/base/mult-it.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{piedipagina} \setinterfaceconstant{footerdistance}{distanzapdp} \setinterfaceconstant{footerstate}{statopdp} +\setinterfaceconstant{force}{forza} \setinterfaceconstant{foregroundcolor}{coloreprimopiano} \setinterfaceconstant{foregroundstyle}{foregroundstyle} \setinterfaceconstant{format}{format} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{precedente} \setinterfaceconstant{previousnumber}{numeroprecedente} \setinterfaceconstant{process}{process} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{raggio} \setinterfaceconstant{random}{casuale} diff --git a/tex/context/base/mult-mcs.tex b/tex/context/base/mult-mcs.tex index 98c392c9f..27fbd37dd 100644 --- a/tex/context/base/mult-mcs.tex +++ b/tex/context/base/mult-mcs.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{neznama reference --} +\setinterfacemessage{references}{30}{neznamy objekt --} \setinterfacemessage{references}{3}{neznamy typ reference --} \setinterfacemessage{references}{2}{duplicitni reference -- na strane --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{nedovolena reference --} -\setinterfacemessage{references}{30}{neznamy objekt --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{reference} diff --git a/tex/context/base/mult-mde.tex b/tex/context/base/mult-mde.tex index 4da89ba33..2819c1ed5 100644 --- a/tex/context/base/mult-mde.tex +++ b/tex/context/base/mult-mde.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{unbekannte Referenz --} +\setinterfacemessage{references}{30}{unbekanntes Object --} \setinterfacemessage{references}{3}{unbekannte Referenz Typ --} \setinterfacemessage{references}{2}{doppelte Referenz -- auf Seite --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{illegale Referenz --} -\setinterfacemessage{references}{30}{unbekanntes Object --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{referenzen} diff --git a/tex/context/base/mult-men.tex b/tex/context/base/mult-men.tex index 4c1bc9942..c9c56bcc5 100644 --- a/tex/context/base/mult-men.tex +++ b/tex/context/base/mult-men.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{unknown reference --} +\setinterfacemessage{references}{30}{unknown object --} \setinterfacemessage{references}{3}{unknown reference type --} \setinterfacemessage{references}{2}{duplicate reference -- on page --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{illegal reference --} -\setinterfacemessage{references}{30}{unknown object --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{references} diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua index 5c8129711..50c764785 100644 --- a/tex/context/base/mult-mes.lua +++ b/tex/context/base/mult-mes.lua @@ -1363,6 +1363,12 @@ return { ["no"]="ulovlig referanse --", ["ro"]="referinta eronata --", }, + ["5"]={ + ["en"]="number of unknown references: --", + }, + ["6"]={ + ["en"]="number of illegal references: --", + }, ["files"]={ "core-obj.tex", "core-ref.tex", "strc-ref.tex" }, ["title"]={ ["cs"]="reference", diff --git a/tex/context/base/mult-mfr.tex b/tex/context/base/mult-mfr.tex index 78e4f9f17..7fee954c0 100644 --- a/tex/context/base/mult-mfr.tex +++ b/tex/context/base/mult-mfr.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{réference -- inconnue} +\setinterfacemessage{references}{30}{objet -- inconnu} \setinterfacemessage{references}{3}{type -- de réference inconnu} \setinterfacemessage{references}{2}{réference -- dupliquée à la page --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{réference -- inconnue} -\setinterfacemessage{references}{30}{objet -- inconnu} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{réferences} diff --git a/tex/context/base/mult-mit.tex b/tex/context/base/mult-mit.tex index 6d2a8f516..9d09e2676 100644 --- a/tex/context/base/mult-mit.tex +++ b/tex/context/base/mult-mit.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{riferimento sconosciuto --} +\setinterfacemessage{references}{30}{oggetto sconosciuto --} \setinterfacemessage{references}{3}{riferimento di tipo sconosciuto --} \setinterfacemessage{references}{2}{riferimento duplicato -- a pagina --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{riferimento illecito --} -\setinterfacemessage{references}{30}{oggetto sconosciuto --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{riferimenti} diff --git a/tex/context/base/mult-mnl.tex b/tex/context/base/mult-mnl.tex index b8204a40b..fb527d4ad 100644 --- a/tex/context/base/mult-mnl.tex +++ b/tex/context/base/mult-mnl.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{onbekende verwijzing --} +\setinterfacemessage{references}{30}{onbekend object --} \setinterfacemessage{references}{3}{type verwijzing -- onbekend} \setinterfacemessage{references}{2}{dubbele verwijzing -- op pagina --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{verboden verwijzing --} -\setinterfacemessage{references}{30}{onbekend object --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{verwijzingen} diff --git a/tex/context/base/mult-mno.tex b/tex/context/base/mult-mno.tex index ee6fd3273..bbbc3a658 100644 --- a/tex/context/base/mult-mno.tex +++ b/tex/context/base/mult-mno.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{ukjent referanse --} +\setinterfacemessage{references}{30}{ukjent objekt --} \setinterfacemessage{references}{3}{ukjent referansetype --} \setinterfacemessage{references}{2}{duplikat referanse -- pø side --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{ulovlig referanse --} -\setinterfacemessage{references}{30}{ukjent objekt --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{referanser} diff --git a/tex/context/base/mult-mpe.tex b/tex/context/base/mult-mpe.tex index 4c1bc9942..c9c56bcc5 100644 --- a/tex/context/base/mult-mpe.tex +++ b/tex/context/base/mult-mpe.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{unknown reference --} +\setinterfacemessage{references}{30}{unknown object --} \setinterfacemessage{references}{3}{unknown reference type --} \setinterfacemessage{references}{2}{duplicate reference -- on page --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{illegal reference --} -\setinterfacemessage{references}{30}{unknown object --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{references} diff --git a/tex/context/base/mult-mro.tex b/tex/context/base/mult-mro.tex index da96a23a4..70673c317 100644 --- a/tex/context/base/mult-mro.tex +++ b/tex/context/base/mult-mro.tex @@ -1,8 +1,10 @@ \setinterfacemessage{references}{1}{referinta necunoscuta --} +\setinterfacemessage{references}{30}{obiect necunoscut --} \setinterfacemessage{references}{3}{tip necunoscut de referinta --} \setinterfacemessage{references}{2}{referinta duplicat -- la pagina --} +\setinterfacemessage{references}{5}{number of unknown references: --} \setinterfacemessage{references}{4}{referinta eronata --} -\setinterfacemessage{references}{30}{obiect necunoscut --} +\setinterfacemessage{references}{6}{number of illegal references: --} \setinterfacemessage{references}{25}{references from document '--' are not imported (export again)} \setinterfacemessage{references}{24}{references from document '--' are not exported} \setinterfacemessage{references}{title}{referinte} diff --git a/tex/context/base/mult-nl.tex b/tex/context/base/mult-nl.tex index 58c106a22..4b08fcdaa 100644 --- a/tex/context/base/mult-nl.tex +++ b/tex/context/base/mult-nl.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{voet} \setinterfaceconstant{footerdistance}{voetafstand} \setinterfaceconstant{footerstate}{voetstatus} +\setinterfaceconstant{force}{forceer} \setinterfaceconstant{foregroundcolor}{voorgrondkleur} \setinterfaceconstant{foregroundstyle}{voorgrondletter} \setinterfaceconstant{format}{formatteer} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{vorige} \setinterfaceconstant{previousnumber}{vorigenummer} \setinterfaceconstant{process}{proces} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{straal} \setinterfaceconstant{random}{willekeur} diff --git a/tex/context/base/mult-ro.tex b/tex/context/base/mult-ro.tex index 48993ae1f..8eae4e4b5 100644 --- a/tex/context/base/mult-ro.tex +++ b/tex/context/base/mult-ro.tex @@ -656,6 +656,7 @@ \setinterfaceconstant{footer}{subsol} \setinterfaceconstant{footerdistance}{distantasubsol} \setinterfaceconstant{footerstate}{staresubsol} +\setinterfaceconstant{force}{fortat} \setinterfaceconstant{foregroundcolor}{foregroundcolor} \setinterfaceconstant{foregroundstyle}{foregroundstyle} \setinterfaceconstant{format}{format} @@ -854,6 +855,7 @@ \setinterfaceconstant{previous}{precendent} \setinterfaceconstant{previousnumber}{numarprecedent} \setinterfaceconstant{process}{process} +\setinterfaceconstant{profile}{profile} \setinterfaceconstant{pubsep}{pubsep} \setinterfaceconstant{radius}{raza} \setinterfaceconstant{random}{aleator} diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex index 8b00b8d73..4f0f6c28b 100644 --- a/tex/context/base/mult-sys.tex +++ b/tex/context/base/mult-sys.tex @@ -450,11 +450,13 @@ \definesystemvariable {as} % AlignmentSwitch \definesystemvariable {at} % ATtachments \definesystemvariable {ba} % synchronisatieBAlk +\definesystemvariable {bc} % BaCkend \definesystemvariable {be} % startstop (BeginEnd) \definesystemvariable {bj} % BlokJe \definesystemvariable {bk} % Blokken (floats) \definesystemvariable {bl} % BLanko \definesystemvariable {bg} % BleedinG +\definesystemvariable {bm} % BookMark \definesystemvariable {bo} % BlankO (definitions) \definesystemvariable {bp} % BreakPoint \definesystemvariable {br} % sideBaR diff --git a/tex/context/base/node-acc.lua b/tex/context/base/node-acc.lua index f5c33a793..fc0c5fb0f 100644 --- a/tex/context/base/node-acc.lua +++ b/tex/context/base/node-acc.lua @@ -10,10 +10,12 @@ local traverse_nodes, traverse_id, has_attribute, copy_node = node.traverse, nod nodes.accessibility = nodes.accessibility or { } -local glue = node.id("glue") -local glyph = node.id("glyph") -local hlist = node.id("hlist") -local vlist = node.id("vlist") +local nodecodes = nodes.nodecodes + +local glue = nodecodes.glue +local glyph = nodecodes.glyph +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist local function injectspaces(head) local p diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index 5ddf31e25..4b57bf225 100644 --- a/tex/context/base/node-aux.lua +++ b/tex/context/base/node-aux.lua @@ -11,8 +11,10 @@ local gsub, format = string.gsub, string.format local free_node, hpack_nodes, node_fields, traverse_nodes = node.free, node.hpack, node.fields, node.traverse local has_attribute, set_attribute, unset_attribute, has_attribute = node.has_attribute, node.set_attribute, node.unset_attribute,node.has_attribute -local hlist = node.id("hlist") -local vlist = node.id("vlist") +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist function nodes.repack_hlist(list,...) local temp, b = hpack_nodes(list,...) diff --git a/tex/context/base/node-bck.lua b/tex/context/base/node-bck.lua index 94fbac85f..593be8492 100644 --- a/tex/context/base/node-bck.lua +++ b/tex/context/base/node-bck.lua @@ -9,8 +9,10 @@ if not modules then modules = { } end modules ['node-bck'] = { -- beware, this one takes quite some runtime, so we need a status flag -- maybe some page related state -local hlist = node.id("hlist") -local vlist = node.id("vlist") +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist local has_attribute = node.has_attribute local set_attribute = node.set_attribute diff --git a/tex/context/base/node-dir.lua b/tex/context/base/node-dir.lua index 05e4835e5..3f65c75b1 100644 --- a/tex/context/base/node-dir.lua +++ b/tex/context/base/node-dir.lua @@ -15,7 +15,6 @@ adapted and now has the mappings as comments. This lua file is based on that file. ]]-- - nodes = nodes or { } nodes.is_mirrored = { diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 74b8daf2a..004d72765 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -10,21 +10,19 @@ if not modules then modules = { } end modules ['node-fin'] = { local next, type, format = next, type, string.format local texsprint = tex.sprint - local ctxcatcodes = tex.ctxcatcodes +local has_attribute, copy_node = node.has_attribute, node.copy +local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming -local glyph = node.id('glyph') -local disc = node.id('disc') -local glue = node.id('glue') -local rule = node.id('rule') -local whatsit = node.id('whatsit') -local hlist = node.id('hlist') -local vlist = node.id('vlist') - -local has_attribute = node.has_attribute -local copy_node = node.copy +local nodecodes = nodes.nodecodes -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming +local glyph = nodecodes.glyph +local disc = nodecodes.disc +local glue = nodecodes.glue +local rule = nodecodes.rule +local whatsit = nodecodes.whatsit +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist states = states or { } shipouts = shipouts or { } diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua index 594cfc1a1..ad7af592f 100644 --- a/tex/context/base/node-fnt.lua +++ b/tex/context/base/node-fnt.lua @@ -12,12 +12,12 @@ local next, type = next, type local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end) -local glyph = node.id('glyph') +local traverse_id, has_attribute = node.traverse_id, node.has_attribute +local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming -local traverse_id = node.traverse_id -local has_attribute = node.has_attribute +local nodecodes = nodes.nodecodes -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming +local glyph = nodecodes.glyph fonts = fonts or { } fonts.tfm = fonts.tfm or { } diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 8f507e9b1..836c43860 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -52,20 +52,71 @@ also ignore the empty nodes. [This is obsolete!]</p> nodes = nodes or { } -local hlist = node.id('hlist') -local vlist = node.id('vlist') -local glyph = node.id('glyph') -local glue = node.id('glue') -local penalty = node.id('penalty') -local kern = node.id('kern') -local whatsit = node.id('whatsit') - -local traverse_id = node.traverse_id -local traverse = node.traverse -local free_node = node.free -local remove_node = node.remove -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after +local traverse, traverse_id = node.traverse, node.traverse_id +local free_node, remove_node = node.free, node.remove +local insert_node_before, insert_node_after = node.insert_before, node.insert_after + +-- there will be more of this: + +local skipcodes = { + [ 0] = "userskip", + [ 1] = "lineskip", + [ 2] = "baselineskip", + [ 3] = "parskip", + [ 4] = "abovedisplayskip", + [ 5] = "belowdisplayskip", + [ 6] = "abovedisplayshortskip", + [ 7] = "belowdisplayshortskip", + [ 8] = "leftskip", + [ 9] = "rightskip", + [10] = "topskip", + [11] = "splittopskip", + [12] = "tabskip", + [13] = "spaceskip", + [14] = "xspaceskip", + [15] = "parfillskip", + [16] = "thinmuskip", + [17] = "medmuskip", + [18] = "thickmuskip", +} + +local noadcodes = { + [ 0] = "ord", + [ 1] = "op_displaylimits", + [ 2] = "op_limits", + [ 3] = "op_nolimits", + [ 4] = "bin", + [ 5] = "rel", + [ 6] = "open", + [ 7] = "close", + [ 8] = "punct", + [ 9] = "inner", + [10] = "under", + [11] = "over", + [12] = "vcenter", +} + +local nodecodes = node.types() +local whatsitcodes = node.whatsits() + +skipcodes = table.swapped(skipcodes,skipcodes) +noadcodes = table.swapped(noadcodes,noadcodes) +nodecodes = table.swapped(nodecodes,nodecodes) +whatsitcodes = table.swapped(whatsitcodes,whatsitcodes) + +nodes.skipcodes = skipcodes +nodes.gluecodes = skipcodes -- more official +nodes.noadcodes = noadcodes +nodes.nodecodes = nodecodes +nodes.whatsitcodes = whatsitcodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local glyph = nodecodes.glyph +local glue = nodecodes.glue +local penalty = nodecodes.penalty +local kern = nodecodes.kern +local whatsit = nodecodes.whatsit function nodes.remove(head, current, free_too) local t = current diff --git a/tex/context/base/node-mig.lua b/tex/context/base/node-mig.lua index c014c8de4..c2d6e8eca 100644 --- a/tex/context/base/node-mig.lua +++ b/tex/context/base/node-mig.lua @@ -8,15 +8,17 @@ if not modules then modules = { } end modules ['node-mig'] = { local format = string.format -local hlist = node.id('hlist') -local vlist = node.id('vlist') -local insert = node.id('ins') -local mark = node.id('mark') - local has_attribute = node.has_attribute local set_attribute = node.set_attribute local remove_nodes = nodes.remove +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local insert = nodecodes.ins +local mark = nodecodes.mark + local migrated = attributes.private("migrated") local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end) diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua index c7c02b414..d10d2ebe4 100644 --- a/tex/context/base/node-pro.lua +++ b/tex/context/base/node-pro.lua @@ -24,10 +24,6 @@ nodes.processors = nodes.processors or { } -- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional -- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional -lists = lists or { } -chars = chars or { } -words = words or { } -- not used yet - local actions = tasks.actions("processors",4) local n = 0 diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index a25cf1f4a..3c0d03f82 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -30,10 +30,12 @@ local trace_destinations = false trackers.register("nodes.destinations", functi local report_backends = logs.new("backends") -local hlist = node.id("hlist") -local vlist = node.id("vlist") -local glue = node.id("glue") -local whatsit = node.id("whatsit") +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local glue = nodecodes.glue +local whatsit = nodecodes.whatsit local new_kern = nodes.kern diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua index 546f56916..bafa5e159 100644 --- a/tex/context/base/node-res.lua +++ b/tex/context/base/node-res.lua @@ -19,14 +19,10 @@ for debugging <l n='luatex'/> node management.</p> nodes = nodes or { } -nodes.whatsits = { } -- table.swapped(node.whatsits()) +local whatsitcodes = nodes.whatsitcodes +local skipcodes = nodes.skipcodes local reserved = { } -local whatsits = nodes.whatsits - -for k, v in next, node.whatsits() do - whatsits[k], whatsits[v] = v, k -- two way -end local function register_node(n) reserved[#reserved+1] = n @@ -72,19 +68,19 @@ local penalty = register_node(new_node("penalty")) local glue = register_node(new_node("glue")) -- glue.spec = nil local glue_spec = register_node(new_node("glue_spec")) local glyph = register_node(new_node("glyph",0)) -local textdir = register_node(new_node("whatsit",whatsits.dir)) -- 7 (6 is local par node) +local textdir = register_node(new_node("whatsit",whatsitcodes.dir)) -- 7 (6 is local par node) local rule = register_node(new_node("rule")) -local latelua = register_node(new_node("whatsit",whatsits.late_lua)) -- 35 -local user_n = register_node(new_node("whatsit",whatsits.user_defined)) user_n.type = 100 -- 44 -local user_l = register_node(new_node("whatsit",whatsits.user_defined)) user_l.type = 110 -- 44 -local user_s = register_node(new_node("whatsit",whatsits.user_defined)) user_s.type = 115 -- 44 -local user_t = register_node(new_node("whatsit",whatsits.user_defined)) user_t.type = 116 -- 44 +local latelua = register_node(new_node("whatsit",whatsitcodes.late_lua)) -- 35 +local user_n = register_node(new_node("whatsit",whatsitcodes.user_defined)) user_n.type = 100 -- 44 +local user_l = register_node(new_node("whatsit",whatsitcodes.user_defined)) user_l.type = 110 -- 44 +local user_s = register_node(new_node("whatsit",whatsitcodes.user_defined)) user_s.type = 115 -- 44 +local user_t = register_node(new_node("whatsit",whatsitcodes.user_defined)) user_t.type = 116 -- 44 local left_margin_kern = register_node(new_node("margin_kern",0)) local right_margin_kern = register_node(new_node("margin_kern",1)) -local lineskip = register_node(new_node("glue",1)) -local baselineskip = register_node(new_node("glue",2)) -local leftskip = register_node(new_node("glue",8)) -local rightskip = register_node(new_node("glue",9)) +local lineskip = register_node(new_node("glue",skipcodes.lineskip)) +local baselineskip = register_node(new_node("glue",skipcodes.baselineskip)) +local leftskip = register_node(new_node("glue",skipcodes.leftskip)) +local rightskip = register_node(new_node("glue",skipcodes.rightskip)) local temp = register_node(new_node("temp",0)) local noad = register_node(new_node("noad")) diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 5e1df2da4..e981b83b4 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -11,9 +11,11 @@ if not modules then modules = { } end modules ['node-rul'] = { -- -- todo: make robust for layers ... order matters -local glyph = node.id("glyph") -local disc = node.id("disc") -local rule = node.id("rule") +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local disc = nodecodes.disc +local rule = nodecodes.rule function nodes.strip_range(first,last) -- todo: dir if first and last then -- just to be sure @@ -62,29 +64,34 @@ local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') -local glyph = node.id("glyph") -local disc = node.id("disc") -local glue = node.id("glue") -local penalty = node.id("penalty") -local kern = node.id("kern") -local hlist = node.id("hlist") -local vlist = node.id("vlist") -local rule = node.id("rule") -local whatsit = node.id("whatsit") - -local new_rule = nodes.rule -local new_kern = nodes.kern -local new_glue = nodes.glue - local insert_before, insert_after, strip_range = node.insert_before, node.insert_after, nodes.strip_range local list_dimensions, has_attribute, set_attribute = node.dimensions, node.has_attribute, node.set_attribute local hpack_nodes = node.hpack +local skipcodes, nodecodes = nodes.skipcodes, nodes.nodecodes local dimenfactor = fonts.dimenfactor local texwrite = tex.write local fontdata = fonts.ids local variables = interfaces.variables +local glyph = nodecodes.glyph +local disc = nodecodes.disc +local glue = nodecodes.glue +local penalty = nodecodes.penalty +local kern = nodecodes.kern +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local rule = nodecodes.rule +local whatsit = nodecodes.whatsit + +local userskip = skipcodes.userskip +local spaceskip = skipcodes.spaceskip +local xspaceskip = skipcodes.xspaceskip + +local new_rule = nodes.rule +local new_kern = nodes.kern +local new_glue = nodes.glue + -- we can use this one elsewhere too -- -- todo: functions: word, sentence @@ -161,7 +168,9 @@ local function process_words(attribute,data,flush,head,parent) -- we have hlistd l = n elseif id == glue then -- catch \underbar{a} \underbar{a} (subtype test is needed) - if continue and has_attribute(n,attribute) and n.subtype == 0 then + local subtype = n.subtype + if continue and has_attribute(n,attribute) and + (subtype == userskip or subtype == spaceskip or subskip == xspaceskip) then l = n else head, done = flush(head,f,l,d,level,parent,strip), true diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua index e632e92da..b6e72f9fb 100644 --- a/tex/context/base/node-ser.lua +++ b/tex/context/base/node-ser.lua @@ -13,13 +13,15 @@ local type, format, concat = type, string.format, table.concat local ctxcatcodes = tex.ctxcatcodes -local hlist = node.id('hlist') -local vlist = node.id('vlist') - local traverse = node.traverse local node_fields = node.fields local node_type = node.type +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist + local expand = table.tohash { "list", -- list_ptr & ins_ptr & adjust_ptr "pre", -- diff --git a/tex/context/base/node-shp.lua b/tex/context/base/node-shp.lua index 50b16efa5..1066ab064 100644 --- a/tex/context/base/node-shp.lua +++ b/tex/context/base/node-shp.lua @@ -6,15 +6,16 @@ if not modules then modules = { } end modules ['node-shp'] = { license = "see context related readme files" } -local hlist = node.id('hlist') -local vlist = node.id('vlist') -local disc = node.id('disc') -local mark = node.id('mark') -local kern = node.id('kern') -local glue = node.id('glue') - -local free_node = node.free -local remove_node = node.remove +local free_node, remove_node = node.free, node.remove + +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local disc = nodecodes.disc +local mark = nodecodes.mark +local kern = nodecodes.kern +local glue = nodecodes.glue local function cleanup_page(head) -- rough local start = head diff --git a/tex/context/base/node-spl.lua b/tex/context/base/node-spl.lua index d6ecdfa13..de1935a03 100644 --- a/tex/context/base/node-spl.lua +++ b/tex/context/base/node-spl.lua @@ -33,13 +33,6 @@ local report_fonts = logs.new("fonts") local report_splitter = logs.new("splitter") local report_optimizer = logs.new("optimizer") -local glyph = node.id("glyph") -local glue = node.id("glue") -local kern = node.id("kern") -local disc = node.id("disc") -local hlist = node.id("hlist") -local whatsit = node.id("whatsit") - local find_node_tail = node.tail or node.slide local free_node = node.free local free_nodelist = node.flush_list @@ -56,6 +49,15 @@ local insert_node_before = node.insert_before local insert_node_after = node.insert_after local repack_hlist = nodes.repack_hlist +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local glue = nodecodes.glue +local kern = nodecodes.kern +local disc = nodecodes.disc +local hlist = nodecodes.hlist +local whatsit = nodecodes.whatsit + local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index d2d02c8df..5134611c4 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['node-tra'] = { might become a runtime module instead. This module will be cleaned up!</p> --ldx]]-- -local utf = unicode.utf8 -local format, match, concat, rep, utfchar = string.format, string.match, table.concat, string.rep, utf.char +local utfchar = utf.char +local concat = table.concat +local format, match, gmatch, concat, rep = string.format, string.match, string.gmatch, table.concat, string.rep local ctxcatcodes = tex.ctxcatcodes @@ -21,20 +22,14 @@ local report_nodes = logs.new("nodes") fonts = fonts or { } fonts.tfm = fonts.tfm or { } fonts.ids = fonts.ids or { } +fonts.chr = fonts.chr or { } nodes = nodes or { } nodes.tracers = nodes.tracers or { } nodes.tracers.characters = nodes.tracers.characters or { } nodes.tracers.steppers = nodes.tracers.steppers or { } -local glyph = node.id('glyph') -local hlist = node.id('hlist') -local vlist = node.id('vlist') -local disc = node.id('disc') -local glue = node.id('glue') -local kern = node.id('kern') -local rule = node.id('rule') -local whatsit = node.id('whatsit') +local tracers = nodes.tracers local copy_node_list = node.copy_list local hpack_node_list = node.hpack @@ -45,8 +40,19 @@ local traverse_nodes = node.traverse local texsprint = tex.sprint local fontdata = fonts.ids - -function nodes.tracers.characters.collect(head,list,tag,n) +local fontchar = fonts.chr +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local disc = nodecodes.disc +local glue = nodecodes.glue +local kern = nodecodes.kern +local rule = nodecodes.rule +local whatsit = nodecodes.whatsit + +function tracers.characters.collect(head,list,tag,n) n = n or 0 local ok, fn = false, nil while head do @@ -75,7 +81,7 @@ function nodes.tracers.characters.collect(head,list,tag,n) end end -function nodes.tracers.characters.equal(ta, tb) +function tracers.characters.equal(ta, tb) if #ta ~= #tb then return false else @@ -89,7 +95,7 @@ function nodes.tracers.characters.equal(ta, tb) return true end -function nodes.tracers.characters.string(t) +function tracers.characters.string(t) local tt = { } for i=1,#t do tt[i] = utfchar(t[i][1]) @@ -97,7 +103,7 @@ function nodes.tracers.characters.string(t) return concat(tt,"") end -function nodes.tracers.characters.unicodes(t,decimal) +function tracers.characters.unicodes(t,decimal) local tt = { } for i=1,#t do local n = t[i][1] @@ -112,7 +118,7 @@ function nodes.tracers.characters.unicodes(t,decimal) return concat(tt," ") end -function nodes.tracers.characters.indices(t,decimal) +function tracers.characters.indices(t,decimal) local tt = { } for i=1,#t do local n = t[i][3] @@ -127,20 +133,20 @@ function nodes.tracers.characters.indices(t,decimal) return concat(tt," ") end -function nodes.tracers.characters.start() +function tracers.characters.start() local npc = nodes.process_characters local list = { } function nodes.process_characters(head) local n = #list - nodes.tracers.characters.collect(head,list,'before',n) + tracers.characters.collect(head,list,'before',n) local h, d = npc(head) - nodes.tracers.characters.collect(head,list,'after',n) + tracers.characters.collect(head,list,'after',n) if #list > n then list[#list+1] = { } end return h, d end - function nodes.tracers.characters.stop() + function tracers.characters.stop() tracers.list['characters'] = list local variables = { ['title'] = 'ConTeXt Character Processing Information', @@ -156,14 +162,14 @@ end local stack = { } -function nodes.tracers.start(tag) +function tracers.start(tag) stack[#stack+1] = tag - local tracer = nodes.tracers[tag] + local tracer = tracers[tag] if tracer and tracer.start then tracer.start() end end -function nodes.tracers.stop() +function tracers.stop() local tracer = stack[#stack] if tracer and tracer.stop then tracer.stop() @@ -175,15 +181,15 @@ end local collection, collecting, messages = { }, false, { } -function nodes.tracers.steppers.start() +function tracers.steppers.start() collecting = true end -function nodes.tracers.steppers.stop() +function tracers.steppers.stop() collecting = false end -function nodes.tracers.steppers.reset() +function tracers.steppers.reset() for i=1,#collection do local c = collection[i] if c then @@ -193,18 +199,18 @@ function nodes.tracers.steppers.reset() collection, messages = { }, { } end -function nodes.tracers.steppers.nofsteps() +function tracers.steppers.nofsteps() return tex.write(#collection) end -function nodes.tracers.steppers.glyphs(n,i) +function tracers.steppers.glyphs(n,i) local c = collection[i] if c then tex.box[n] = hpack_node_list(copy_node_list(c)) end end -function nodes.tracers.steppers.features() +function tracers.steppers.features() -- local f = first_character(collection[1]) -- if f then -- something fishy with first_character local f = collection[1] @@ -235,13 +241,13 @@ function nodes.tracers.steppers.features() end end -function nodes.tracers.fontchar(font,char) +function tracers.fontchar(font,char) local n = nodes.glyph() n.font, n.char, n.subtype = font, char, 256 node.write(n) end -function nodes.tracers.steppers.codes(i,command) +function tracers.steppers.codes(i,command) local c = collection[i] while c do local id = c.id @@ -260,7 +266,7 @@ function nodes.tracers.steppers.codes(i,command) end end -function nodes.tracers.steppers.messages(i,command,split) +function tracers.steppers.messages(i,command,split) local list = messages[i] -- or { "no messages" } if list then for i=1,#list do @@ -277,9 +283,9 @@ end -- hooks into the node list processor (see otf) -function nodes.tracers.steppers.check(head) +function tracers.steppers.check(head) if collecting then - nodes.tracers.steppers.reset() + tracers.steppers.reset() local n = copy_node_list(head) nodes.inject_kerns(n,nil,"trace",true) nodes.protect_glyphs(n) -- can be option @@ -287,7 +293,7 @@ function nodes.tracers.steppers.check(head) end end -function nodes.tracers.steppers.register(head) +function tracers.steppers.register(head) if collecting then local nc = #collection+1 if messages[nc] then @@ -299,7 +305,7 @@ function nodes.tracers.steppers.register(head) end end -function nodes.tracers.steppers.message(str,...) +function tracers.steppers.message(str,...) str = format(str,...) if collecting then local n = #collection + 1 @@ -332,7 +338,7 @@ function nodes.check_glyphs(head,message) return false end -function nodes.tosequence(start,stop,compact) +local function tosequence(start,stop,compact) if start then local t = { } while start do @@ -341,7 +347,7 @@ function nodes.tosequence(start,stop,compact) local c = start.char if compact then if start.components then - t[#t+1] = nodes.tosequence(start.components,nil,compact) + t[#t+1] = tosequence(start.components,nil,compact) else t[#t+1] = utfchar(c) end @@ -379,6 +385,8 @@ function nodes.tosequence(start,stop,compact) end end +nodes.tosequence = tosequence + function nodes.report(t,done) if done then if status.output_active then @@ -474,3 +482,56 @@ function nodes.list_to_utf(h,joiner) end return concat(w) end + +local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" } + +local function show_boxes(n,symbol,depth) + depth, symbol = depth or 0, symbol or "." + for n in traverse_nodes(n) do + local id = n.id + if id == hlist or id == vlist then + local s = n.subtype + logs.simple(rep(symbol,depth) .. what[s] or s) + show_boxes(n.list,symbol,depth+1) + end + end +end + +nodes.show_boxes = show_boxes + +local threshold = 65536 + +function toutf(list,result) + for n in traverse_nodes(list) do + local id = n.id + if id == glyph then + local c = n.char + local fc = fontchar[n.font] + if fc then + local u = fc[c].tounicode + if u then + for s in gmatch(u,"..") do + result[#result+1] = utfchar(tonumber(s,16)) + end + else + result[#result+1] = utfchar(c) + end + else + result[#result+1] = utfchar(c) + end + elseif id == disc then + toutf(n.replace,result) + elseif id == hlist or id == vlist then + toutf(n.list,result) + elseif id == glue and n.subtype == 0 and n.spec.width > threshold then + result[#result+1] = " " + elseif id == kern and n.kern > threshold then + result[#result+1] = " " + end + end + return result +end + +function nodes.toutf(list) + return concat(toutf(list,{})) +end diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua index 66f691ec8..b47bceef1 100644 --- a/tex/context/base/node-tsk.lua +++ b/tex/context/base/node-tsk.lua @@ -115,8 +115,8 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if data then if n == 0 then return function(head) - local runner = data.runner total = total + 1 -- will go away + local runner = data.runner if not runner then created = created + 1 if trace_tasks then diff --git a/tex/context/base/node-tst.lua b/tex/context/base/node-tst.lua index d7ea96f26..c7e79c48f 100644 --- a/tex/context/base/node-tst.lua +++ b/tex/context/base/node-tst.lua @@ -6,16 +6,17 @@ if not modules then modules = { } end modules ['node-tst'] = { license = "see context related readme files" } -local glue = node.id("glue") -local penalty = node.id("penalty") -local kern = node.id("kern") -local glyph = node.id("glyph") -local whatsit = node.id("whatsit") -local hlist = node.id("hlist") - local find_node_tail = node.tail or node.slide -local chardata = characters.data +local chardata = characters.data +local nodecodes = nodes.nodecodes + +local glue = nodecodes.glue +local penalty = nodecodes.penalty +local kern = nodecodes.kern +local glyph = nodecodes.glyph +local whatsit = nodecodes.whatsit +local hlist = nodecodes.hlist function nodes.the_left_margin(n) -- todo: three values while n do diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua index 5ab6b6975..b807e6aae 100644 --- a/tex/context/base/node-typ.lua +++ b/tex/context/base/node-typ.lua @@ -10,9 +10,7 @@ if not modules then modules = { } end modules ['node-typ'] = { local utfvalues = string.utfvalues -local newglyph = nodes.glyph -local newglue = nodes.glue - +local newglyph, newglue = nodes.glyph, nodes.glue local hpack, vpack = node.hpack, node.vpack typesetting = typesetting or { } @@ -21,7 +19,7 @@ local function tonodes(str,fontid,spacing) -- don't use this local head, prev = nil, nil for s in utfvalues(str) do local next - if spacing and s == 32 then + if spacing and s == 32 then next = newglue(spacing or 64*1024*10) else next = newglyph(fontid or 1,s) diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv index 272ef0544..b0e9f858d 100644 --- a/tex/context/base/pack-rul.mkiv +++ b/tex/context/base/pack-rul.mkiv @@ -612,8 +612,6 @@ \def\inheritlocalframed[#1]#2[#3]{\letvalue{#1\s!parent}#3} \def\copylocalframed [#1]#2[#3]{\setvalue{#1\s!parent}{#3}} -\let\setuplocalframed\getparameters % obsolete - \presetlocalframed[\??ol] \newcount\framednesting @@ -627,23 +625,33 @@ \unexpanded\def\setupframed {\dodoubleempty\dosetupframed} -\def\dosetupframed +% \def\dosetupframed +% {\ifsecondargument +% \@EA\dodoublesetupframed +% \else +% \@EA\dosinglesetupframed +% \fi} + +% we can consider setting the parent of the regular framed to +% something else in the otr so that we isolate it there + +\def\dosetupframed[#1][#2]% {\ifsecondargument - \@EA\dodoublesetupframed + \getparameters[\??ol#1][#2]% \else - \@EA\dosinglesetupframed + \getparameters[\??ol][#1]% \fi} -\def\dosinglesetupframed[#1][#2]% - {\getparameters[\??ol][#1]} +% \def\dosinglesetupframed[#1][#2]% +% {\getparameters[\??ol][#1]} -\def\dodoublesetupframed[#1][#2]% - {\bgroup - \let\dodoubleempty\empty - \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}% - \getvalue{#1}% - \egroup - \letvalue{#1}\globalredefinedframed} +% \def\dodoublesetupframed[#1][#2]% +% {\bgroup +% \let\dodoubleempty\empty +% \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}% +% \getvalue{#1}% +% \egroup +% \letvalue{#1}\globalredefinedframed} %D \startbuffer %D \setupframed [framecolor=yellow] \framed{A} @@ -655,7 +663,6 @@ %D %D \startbuffer %D \presetlocalframed[myframed] -%D \setuplocalframed[myframed][width=4cm,height=2cm] %D \localframed[myframed][framecolor=green]{oeps} %D \stopbuffer %D @@ -884,7 +891,7 @@ % todo: protect local \framednames -\unexpanded\def\startlocalframed[#1][#2]% +\unexpanded\def\startlocalframed[#1][#2]% it should be possible to set \@@framed before calling this which saves a [] scan {\bgroup \inframedtrue \edef\@@framed{#1}% @@ -2829,17 +2836,49 @@ %D One can also define simple framed texts, using: %D %D \showsetup{defineframed} +%D +%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance +%D model instead of passing a combination of arguments. This also +%D also simplified the \type {\setupframed} command. There are +%D certainly more places where such improvements can be made. + +% \unexpanded\def\defineframed +% {\dodoubleempty\dodefineframed} +% +% \def\dodefineframed[#1][#2]% +% {\iffirstargument +% \setuvalue{#1}{\dodoubleempty\doframed[#2]}% +% \fi} +% +% \def\doframed[#1][#2]% +% {\framed[#1,#2]} -\unexpanded\def\defineframed +\def\defineframed {\dodoubleempty\dodefineframed} \def\dodefineframed[#1][#2]% - {\iffirstargument - \setuvalue{#1}{\dodoubleempty\doframed[#2]}% - \fi} + {\ifcsname\??ol:#1\endcsname + % already defined, keeps settings + \else + \expandafter\newcount\csname\??ol:#1\endcsname % \the\everypresetframed + \fi + \getparameters[\??ol#1][\s!parent=\??ol,#2]% + \setuvalue{#1}{\doframed[#1]}}% % \the\everydefineframed + +\def\doframed[#1]% we can speed up startlocalframed by using \currentlocalframed + {\bgroup + \expandafter\let\expandafter\tempframedcount\csname\??ol:#1\endcsname + \advance\tempframedcount\plusone + \expandafter\def\csname\??ol#1:\the\tempframedcount\s!parent\endcsname{\??ol#1}% \copylocalframed + \dodoubleempty\startlocalframed[\??ol#1:\the\tempframedcount]} -\def\doframed[#1][#2]% - {\framed[#1,#2]} +%D We can do: +%D +%D \starttyping +%D \defineframed[\v!framed] +%D \stoptyping +%D +%D but the existing one is ok as well (less csname messy too). %D \macros %D {textrule, starttextrule, setuptextrules} @@ -3521,6 +3560,9 @@ \setuplinewidth [\v!medium] +% We could omit the empty setings but that is some 10% slower due to +% extra testing in the chain. + \setupframed [\c!width=\v!fit, \c!height=\v!broad, @@ -3554,12 +3596,12 @@ \c!align=, \c!bottom=\vss, \c!top=, - \c!strut=\v!yes, \c!autostrut=\v!yes, \c!location=\v!normal, \c!orientation=, \c!autowidth=\v!yes, - \c!setups=] + \c!setups=, + \c!strut=\v!yes] \setupscreens [%\c!factor=1.0, % obsolete diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index e11730eae..f8daa84f4 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -27,11 +27,16 @@ storage.register("lines/data", nodes.lines.data, "nodes.lines.data") -- if there is demand for it, we can support multiple numbering streams -- and use more than one attibute -local hlist, vlist, whatsit = node.id('hlist'), node.id('vlist'), node.id('whatsit') +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local whatsit = nodecodes.whatsit local display_math = attributes.private('display-math') local line_number = attributes.private('line-number') local line_reference = attributes.private('line-reference') +local verbatim_line = attributes.private('verbatim-line') local current_list = { } local cross_references = { } @@ -45,8 +50,6 @@ local hpack_node = node.hpack local insert_node_after = node.insert_after local insert_node_before = node.insert_before -local whatsit = node.id("whatsit") - local data = nodes.lines.data local last = #data @@ -147,21 +150,28 @@ end local the_left_margin = nodes.the_left_margin -local function check_number(n,a,skip) -- move inline +local function check_number(n,a,skip,sameline) local d = data[a] if d then - local s = d.start or 1 + local tag, skipflag, s = d.tag or "", 0, d.start or 1 current_list[#current_list+1] = { n, s } - if not skip and s % d.step == 0 then - local tag = d.tag or "" - texsprint(ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}{%s}\\endgraf",tag,s,n.shift,n.width,the_left_margin(n.list),n.dir)) + if sameline then + skipflag = 0 + if trace_numbers then + report_lines("skipping broken line number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") + end + elseif not skip and s % d.step == 0 then + skipflag, d.start = 1, s + 1 -- (d.step or 1) if trace_numbers then report_lines("making number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") end else - texsprint(ctxcatcodes, "\\skipnumber\\endgraf") + skipflag, d.start = 0, s + 1 -- (d.step or 1) + if trace_numbers then + report_lines("skipping line number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") + end end - d.start = s + 1 -- (d.step or 1) + context.makelinenumber(tag,skipflag,s,n.shift,n.width,the_left_margin(n.list),n.dir) end end @@ -170,12 +180,13 @@ function nodes.lines.boxed.stage_one(n) local head = texbox[n] if head then local list = head.list - local last_a, skip = nil, false + local last_a, last_v, skip = nil, -1, false for n in traverse_id(hlist,list) do -- attr test here and quit as soon as zero found if n.height == 0 and n.depth == 0 then -- skip funny hlists else - local a = has_attribute(n.list,line_number) + local list = n.list + local a = has_attribute(list,line_number) if a and a > 0 then if last_a ~= a then if data[a].method == variables.next then @@ -188,10 +199,13 @@ function nodes.lines.boxed.stage_one(n) check_number(n,a,skip) end else - -- the following test fails somehow (change in luatex?) - -- if node.first_character(n.list) then + local v = has_attribute(list,verbatim_line) + if not v or v ~= last_v then + last_v = v check_number(n,a,skip) - -- end + else + check_number(n,a,skip,true) + end end skip = false end diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv index 51f027639..e9df56aa6 100644 --- a/tex/context/base/page-lin.mkiv +++ b/tex/context/base/page-lin.mkiv @@ -42,11 +42,7 @@ % id nr shift width leftskip dir -% \def\mkskiplinenumber #1#2#3#4#6#5{} -% \def\mkleftlinenumber #1#2#3#4#5#6{\hbox{\llap{#2\quad\hskip#3\scaledpoint}}} -% \def\mkrightlinenumber#1#2#3#4#5#6{\hbox{\rlap{\hskip#4\scaledpoint\hskip#3\scaledpoint\quad#2}}} - -\let\makenumber\gobblesixarguments +\let\makelinenumber\gobblesevenarguments \newconditional\boxcontentneedsprocessing @@ -235,8 +231,6 @@ % number placement -\let\mkskiplinenumber \gobblesixarguments - \def\mkdoinnerlinenumber{\doifoddpageelse\mkdoleftlinenumber\mkdorightlinenumber} \def\mkdoouterlinenumber{\doifoddpageelse\mkdorightlinenumber\mkdoleftlinenumber} @@ -278,47 +272,53 @@ \expandafter\mkdobeginlinenumber \fi} +\newconditional\faketextlinenumber + \def\mkaddtextlinenumbers#1#2#3% box col max {\bgroup \chardef\linenumberbox #1\relax \chardef\linenumbercolumn #2\relax \chardef\linenumberlastcolumn#3\relax \fullrestoreglobalbodyfont - \def\skipnumber{\hbox{}}% - \let\makenumber\maketextlinenumber + \let\makelinenumber\maketextlinenumber \mkprocesstextlinenumbers\linenumberbox \egroup} -\def\maketextlinenumber#1% +\def\maketextlinenumber#1#2% {\edef\currentlinenumbering{#1}% + \ifcase#2\relax + \settrue \faketextlinenumber + \else + \setfalse\faketextlinenumber + \fi \chardef\linenumberlocation \executeifdefined{\??rn:l:\linenumberparameter\c!location}\plusone % left \chardef\linenumberalignment\executeifdefined{\??rn:a:\linenumberparameter\c!align }\plusfive % auto \ifcase\linenumberlastcolumn\relax - \let\domakenumber\mkskiplinenumber + \settrue \faketextlinenumber \or % one column \ifcase\linenumberlocation - \let\domakenumber\mkskiplinenumber + \settrue \faketextlinenumber % hm \or - \let\domakenumber\mkleftlinenumber + \let\domakelinenumber\mkleftlinenumber \or - \let\domakenumber\mkrightlinenumber + \let\domakelinenumber\mkrightlinenumber \or % inner - \let\domakenumber\mkdoinnerlinenumber + \let\domakelinenumber\mkdoinnerlinenumber \or % outer - \let\domakenumber\mkdoouterlinenumber + \let\domakelinenumber\mkdoouterlinenumber \or % text - \let\domakenumber\mkdotextlinenumber + \let\domakelinenumber\mkdotextlinenumber \or - \let\domakenumber\mkdobeginlinenumber + \let\domakelinenumber\mkdobeginlinenumber \or - \let\domakenumber\mkdoendlinenumber + \let\domakelinenumber\mkdoendlinenumber \fi \else\ifcase\linenumbercolumn\relax - \let\domakenumber\mkskiplinenumber + \settrue \faketextlinenumber \or - \let\domakenumber\mkleftlinenumber + \let\domakelinenumber\mkleftlinenumber \ifcase\linenumberlocation\or \chardef\linenumberlocation\plusone \or @@ -335,7 +335,7 @@ \chardef\linenumberlocation\plusone % todo \fi \else - \let\domakenumber\mkrightlinenumber + \let\domakelinenumber\mkrightlinenumber \ifcase\linenumberlocation\or \chardef\linenumberlocation\plustwo \or @@ -350,7 +350,7 @@ \chardef\linenumberlocation\plustwo % todo \fi \fi\fi - \domakenumber{#1}} + \domakelinenumber{#1}} \def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width ! {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}} @@ -420,11 +420,15 @@ \or \doifoddpageelse\hss\relax % outer \fi - \linenumberattributes\c!style\c!color - {\linenumberparameter\c!command - {\linenumberparameter\c!left - \convertnumber{\linenumberparameter\c!conversion}{#3}% - \linenumberparameter\c!right}}% + \ifconditional\faketextlinenumber + % we need to reserve space + \else + \linenumberattributes\c!style\c!color + {\linenumberparameter\c!command + {\linenumberparameter\c!left + \convertnumber{\linenumberparameter\c!conversion}{#3}% + \linenumberparameter\c!right}}% + \fi \ifcase\linenumberlocation \hss % middle \or diff --git a/tex/context/base/page-mul.mkii b/tex/context/base/page-mul.mkii index c78af074a..801ae5d65 100644 --- a/tex/context/base/page-mul.mkii +++ b/tex/context/base/page-mul.mkii @@ -1179,11 +1179,11 @@ \egroup} \def\multicolumnseject - {\ifdim\pagetotal>\textheight - \eject % new - \else + {%\ifdim\pagetotal>\textheight + % \eject % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point) + %\else \allowbreak - \fi} + }%\fi} %D The multicolumn mechanism is incorporated in a \CONTEXT\ %D interface, which acts like: diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv index 791f328c5..ff0c9e502 100644 --- a/tex/context/base/page-mul.mkiv +++ b/tex/context/base/page-mul.mkiv @@ -1028,30 +1028,27 @@ \dontshowcomposition \widowpenalty\zerocount \setbox0\vbox{\unvbox\normalpagebox}% -\ifdim\ht0>\openlineheight % at least one line - \ifnum\minbalancetoplines<2 % balance anyway - \donetrue - \else % check criterium to available lines - \getnoflines{\ht0}% - \divide\noflines \nofcolumns \relax - \ifnum\noflines<\minbalancetoplines \relax - \dimen0\ht0 - \advance\dimen0 \ht\firsttopcolumnbox - \advance\dimen0 \openlineheight \relax % let's play safe - \ifdim\dimen0>\columntextheight % column exceeding text height - \donetrue - \else % it seems to fit - \donefalse - \fi - \else % balance indeed - \donetrue - \fi + \ifdim\ht0>\openlineheight % at least one line + \ifnum\minbalancetoplines<2 % balance anyway + \donetrue + \else % check criterium to available lines + \getnoflines{\ht0}% + \divide\noflines \nofcolumns \relax + \ifnum\noflines<\minbalancetoplines \relax + % let's play safe + \ifdim\dimexpr\ht0+\ht\firsttopcolumnbox+\openlineheight\relax>\columntextheight + \donetrue % column exceeding text height + \else + \donefalse % it seems to fit + \fi + \else % balance indeed + \donetrue + \fi + \fi + \else % balancing does not make sense + \donefalse \fi -\else % balancing does not make sense - \donefalse -\fi -\ifdone % start balancing - %\ifdim\ht0>\openlineheight + \ifdone % start balancing, was: \ifdim\ht0>\openlineheight \dimen0\ht0 \advance\dimen0 \topskip \advance\dimen0 -\baselineskip @@ -1174,11 +1171,11 @@ \egroup} \def\multicolumnseject - {\ifdim\pagetotal>\textheight - \eject % new - \else + {%\ifdim\pagetotal>\textheight + % \eject % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point) + %\else \allowbreak - \fi} + }%\fi} %D The multicolumn mechanism is incorporated in a \CONTEXT\ %D interface, which acts like: diff --git a/tex/context/base/scrn-nav.mkiv b/tex/context/base/scrn-nav.mkiv index 264e3ded2..04b404a78 100644 --- a/tex/context/base/scrn-nav.mkiv +++ b/tex/context/base/scrn-nav.mkiv @@ -217,7 +217,6 @@ [\c!state=\v!stop, \c!page=\v!no, \c!click=\v!yes, - \c!display=, \c!openaction=, \c!closeaction=, \c!openpageaction=, diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index e06cb0ded..571e9f3ca 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -72,13 +72,15 @@ local hpack_node = node.hpack local vpack_node = node.vpack local writable_spec = nodes.writable_spec -local glyph = node.id("glyph") -local penalty = node.id("penalty") -local kern = node.id("kern") -local glue = node.id('glue') -local hlist = node.id('hlist') -local vlist = node.id('vlist') -local adjust = node.id('adjust') +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local penalty = nodecodes.penalty +local kern = nodecodes.kern +local glue = nodecodes.glue +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist +local adjust = nodecodes.adjust vspacing = vspacing or { } vspacing.data = vspacing.data or { } @@ -157,8 +159,8 @@ function vspacing.define_snap_method(name,method) tex.write(n) end ---~ local rule_id = node.id("rule") ---~ local vlist_id = node.id("vlist") +--~ local rule_id = nodecodes.rule +--~ local vlist_id = nodecodes.vlist --~ function nodes.makevtop(n) --~ if n.id == vlist_id then --~ local list = n.list @@ -530,47 +532,18 @@ end -- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display -local user_skip = 0 -local line_skip = 1 -local baseline_skip = 2 -local par_skip = 3 -local above_display_skip = 4 -local below_display_skip = 5 -local above_display_short_skip = 6 -local below_display_short_skip = 7 -local left_skip_code = 8 -local right_skip_code = 9 -local top_skip_code = 10 -local split_top_skip_code = 11 -local tab_skip_code = 12 -local space_skip_code = 13 -local xspace_skip_code = 14 -local par_fill_skip_code = 15 -local thin_mu_skip_code = 16 -local med_mu_skip_code = 17 -local thick_mu_skip_code = 18 - -local skips = { - [ 0] = "user_skip", - [ 1] = "line_skip", - [ 2] = "baseline_skip", - [ 3] = "par_skip", - [ 4] = "above_display_skip", - [ 5] = "below_display_skip", - [ 6] = "above_display_short_skip", - [ 7] = "below_display_short_skip", - [ 8] = "left_skip_code", - [ 9] = "right_skip_code", - [10] = "top_skip_code", - [11] = "split_top_skip_code", - [12] = "tab_skip_code", - [13] = "space_skip_code", - [14] = "xspace_skip_code", - [15] = "par_fill_skip_code", - [16] = "thin_mu_skip_code", - [17] = "med_mu_skip_code", - [18] = "thick_mu_skip_code", -} +local skipcodes = nodes.skipcodes + +local userskip_code = skipcodes.userskip +local lineskip_code = skipcodes.lineskip +local baselineskip_code = skipcodes.baselineskip +local parskip_code = skipcodes.parskip +local abovedisplayskip_code = skipcodes.abovedisplayskip +local belowdisplayskip_code = skipcodes.belowdisplayskip +local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip +local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip +local topskip_code = skipcodes.topskip +local splittopskip_code = skipcodes.splittopskip local free_glue_node = free_node local discard, largest, force, penalty, add, disable, nowhite, goback, together = 0, 1, 2, 3, 4, 5, 6, 7, 8 @@ -706,7 +679,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail elseif id ~= glue then flush("something else") current = current.next - elseif subtype == user_skip then -- todo, other subtypes, like math + elseif subtype == userskip_code then -- todo, other subtypes, like math local sc = has_attribute(current,skip_category) -- has no default, no unset (yet) local so = has_attribute(current,skip_order ) or 1 -- has 1 default, no unset (yet) local sp = has_attribute(current,skip_penalty ) -- has no default, no unset (yet) @@ -832,7 +805,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail if sc == force then force_glue = true end - elseif subtype == line_skip then + elseif subtype == lineskip_code then if snap then local s = has_attribute(current,snap_method) if s and s ~= 0 then @@ -853,7 +826,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail flush("lineskip") end current = current.next - elseif subtype == baseline_skip then + elseif subtype == baselineskip_code then if snap then local s = has_attribute(current,snap_method) if s and s ~= 0 then @@ -874,7 +847,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail flush("baselineskip") end current = current.next - elseif subtype == par_skip then + elseif subtype == parskip_code then -- parskip always comes later if ignore_whitespace then if trace then trace_natural("ignored parskip",current) end @@ -892,7 +865,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail if trace then trace_natural("honored parskip",current) end head, current, glue_data = remove_node(head, current) end - elseif subtype == top_skip_code or subtype == split_top_skip_code then + elseif subtype == topskip_code or subtype == splittopskip_code then if snap then local s = has_attribute(current,snap_method) if s and s ~= 0 then @@ -911,25 +884,25 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail flush("topskip") end current = current.next - elseif subtype == above_display_skip then + elseif subtype == abovedisplayskip_code then -- if trace then trace_skip("above display skip (normal)",sc,so,sp,current) end flush("above display skip (normal)") current = current.next -- - elseif subtype == below_display_skip then + elseif subtype == belowdisplayskip_code then -- if trace then trace_skip("below display skip (normal)",sc,so,sp,current) end flush("below display skip (normal)") current = current.next -- - elseif subtype == above_display_short_skip then + elseif subtype == abovedisplayshortskip_code then -- if trace then trace_skip("above display skip (short)",sc,so,sp,current) end flush("above display skip (short)") current = current.next -- - elseif subtype == below_display_short_skip then + elseif subtype == belowdisplayshortskip_code then -- if trace then trace_skip("below display skip (short)",sc,so,sp,current) end flush("below display skip (short)") @@ -937,7 +910,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail -- else -- other glue if snap and trace_vsnapping and current.spec.writable and current.spec.width ~= 0 then - report_snapper("%s of %s (kept)",skips[subtype],current.spec.width) + report_snapper("%s of %s (kept)",skipcodes[subtype],current.spec.width) --~ current.spec.width = 0 end if trace then trace_skip(format("some glue (%s)",subtype),sc,so,sp,current) end @@ -1083,8 +1056,10 @@ end local attribute = attributes.private('graphicvadjust') -local hlist = node.id('hlist') -local vlist = node.id('vlist') +local nodecodes = nodes.nodecodes + +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist local remove_node = nodes.remove local hpack_node = node.hpack diff --git a/tex/context/base/strc-bkm.lua b/tex/context/base/strc-bkm.lua index 79ed867de..5fe9325a6 100644 --- a/tex/context/base/strc-bkm.lua +++ b/tex/context/base/strc-bkm.lua @@ -16,8 +16,9 @@ local texsprint, utfvalues = tex.sprint, string.utfvalues local ctxcatcodes = tex.ctxcatcodes -local lists = structure.lists -local levelmap = structure.sections.levelmap +local lists = structure.lists +local levelmap = structure.sections.levelmap +local variables = interfaces.variables structure.bookmarks = structure.bookmarks or { } @@ -25,11 +26,29 @@ local bookmarks = structure.bookmarks bookmarks.method = "internal" -- or "page" -local names, opened = "", "" - -function bookmarks.register(n,o) - if names == "" then names = n else names = names .. "," .. n end - if opened == "" then opened = o else opened = opened .. "," .. o end +local names, opened, forced, numbered = { }, { }, { }, { } + +function bookmarks.register(settings) + local force = settings.force == variables.yes + local number = settings.number == variables.yes + local allopen = settings.opened == variables.all + for k, v in next, aux.settings_to_hash(settings.names or "") do + names[k] = true + if force then + forced[k] = true + if allopen then + opened[k] = true + end + end + if number then + numbered[k] = true + end + end + if not allopen then + for k, v in next, aux.settings_to_hash(settings.opened or "") do + opened[k] = true + end + end end function bookmarks.overload(name,text) @@ -63,23 +82,32 @@ end -- todo: collect specs and collect later i.e. multiple places +local numberspec = { } + +function structure.bookmarks.setup(spec) + -- table.merge(numberspec,spec) + for k, v in next, spec do + numberspec[k] = v + end +end + function bookmarks.place() - if names ~= "" then - local list = lists.filter(names,"all",nil,lists.collected) - local lastlevel = 1 + if next(names) then + local list = lists.filter_collected(names,"all",nil,lists.collected,forced) if #list > 0 then - local opened, levels = aux.settings_to_set(opened), { } + local levels, lastlevel = { }, 1 for i=1,#list do local li = list[i] local metadata = li.metadata local name = metadata.name - if not metadata.nolist then -- and levelmap[name] then + if not metadata.nolist or forced[name] then -- and levelmap[name] then local titledata = li.titledata if titledata then local structural = levelmap[name] lastlevel = structural or lastlevel local title = titledata.bookmark if not title or title == "" then + -- We could typeset the title and then convert it. if not structural then -- placeholder, todo: bookmarklabel title = name .. ": " .. (titledata.title or "?") @@ -87,47 +115,34 @@ function bookmarks.place() title = titledata.title or "?" end end + if numbered[name] then + local sectiondata = jobsections.collected[li.references.section] + local numberdata = li.numberdata + if sectiondata and numberdata and not numberdata.hidenumber then + -- we could typeset the number and convert it + title = concat(structure.sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata)) .. " " .. title + end + end levels[#levels+1] = { lastlevel, - stripped(title), + stripped(title), -- can be replaced by converter li.references, -- has internal and realpage allopen or opened[name] } end end end - backends.codeinjections.addbookmarks(levels,bookmarks.method) + bookmarks.finalize(levels) end function bookmarks.place() end -- prevent second run end end -lpdf.registerdocumentfinalizer(function() structure.bookmarks.place() end,1,"bookmarks") +function bookmarks.finalize(levels) + -- This function can be overloaded by an optional converter + -- that uses nodes.toutf on a typeset stream. This is something + -- that we will support when the main loop has become a coroutine. + backends.codeinjections.addbookmarks(levels,bookmarks.method) +end --- bkm ---~ function nodes.toutf(list) ---~ local t= { } ---~ for n in node.traverse(list) do ---~ local id = n.id ---~ if id == node.id("glyph") then ---~ local c = n.char ---~ local f = fonts.ids[n.font] ---~ if f then ---~ local u = f.characters[c].tounicode ---~ if u then ---~ for s in string.gmatch(u,"..") do ---~ t[#t+1] = utf.char(tonumber(s,16)) ---~ end ---~ else ---~ t[#t+1] = utf.char(c) ---~ end ---~ else ---~ t[#t+1] = utf.char(c) ---~ end ---~ elseif id == node.id("glue") then ---~ t[#t+1] = " " ---~ end ---~ end ---~ return table.concat(t,"") ---~ end ---~ print(nodes.toutf(tex.box[999].list)) +lpdf.registerdocumentfinalizer(function() structure.bookmarks.place() end,1,"bookmarks") diff --git a/tex/context/base/strc-bkm.mkiv b/tex/context/base/strc-bkm.mkiv index 77854738d..f0cfa2a2f 100644 --- a/tex/context/base/strc-bkm.mkiv +++ b/tex/context/base/strc-bkm.mkiv @@ -55,18 +55,56 @@ %D Placement \unknown\ look how simple compared to \MKII: +\newtoks \everysetupbookmarks + +\def\bookmarkparameter#1{\ifcsname\??bm#1\endcsname\csname\??bm#1\endcsname\fi} + +\unexpanded\def\setupbookmarks[#1]% + {\getparameters[\??bm][#1]% + \the\everysetupbookmarks} + \unexpanded\def\placebookmarks - {\dodoubleempty\doplacebookmarks} + {\dotripleempty\doplacebookmarks} -\def\doplacebookmarks[#1][#2]% +\def\doplacebookmarks[#1][#2][#3]% {\iflocation - \iffirstargument - \ctxlua{structure.bookmarks.register("#1","#2")}% - \else - \normalexpanded{\noexpand\placebookmarks[\getvalue{\??ih\v!content\c!list}]}% + \begingroup + \edef\askednames{#1}% + \edef\askedopened{#2}% + \ifx\askednames\empty + \edef\askednames{\getvalue{\??ih\v!content\c!list}}% \fi + \ifx\askednames\empty + \let\askednames\v!all + \fi + \ifthirdargument + \getparameters[\??bm][#3]% + \else\ifsecondargument + \doifassignmentelse{#2}{\let\askedopened\empty\getparameters[\??bm][#2]}\donothing + \fi\fi + \ctxlua{structure.bookmarks.register { + names = "\askednames", + opened = "\askedopened", + force = "\bookmarkparameter\c!force", + number = "\bookmarkparameter\c!number", + }}% + \endgroup \fi} +\setupbookmarks + [\c!force=\v!no, % it's easier to force that to inhibit + \c!number=\v!yes] % might become v!no + +\appendtoks + \ctxlua{structure.bookmarks.setup { + separatorset = "\bookmarkparameter\c!numberseparatorset", + conversionset = "\bookmarkparameter\c!numberconversionset", + starter = \!!bs\bookmarkparameter\c!numberstarter\!!es, + stopper = \!!bs\bookmarkparameter\c!numberstopper\!!es, + segments = "\bookmarkparameter\c!numbersegments", + }}% +\to \everysetupbookmarks + % \prependtoks\ctxlua{structure.bookmarks.place()}\to\everystoptext % too late % \prependtoks\ctxlua{structure.bookmarks.place()}\to\everylastbackendshipout % okay but not nice diff --git a/tex/context/base/strc-blk.lua b/tex/context/base/strc-blk.lua index 2589190eb..25c4f2cae 100644 --- a/tex/context/base/strc-blk.lua +++ b/tex/context/base/strc-blk.lua @@ -73,8 +73,6 @@ function blocks.setstate(state,name,tag) end end ---~ filter_collected(names, criterium, number, collected) - function blocks.select(state,name,tag,criterium) criterium = criterium or "text" if find(tag,"=") then tag = "" end @@ -83,7 +81,7 @@ function blocks.select(state,name,tag,criterium) local tags = not all and aux.settings_to_set(tag) local hide = state == "process" local n = structure.sections.number_at_depth(criterium) - local result = structure.lists.filter_collected("all", criterium, n, collected) + local result = structure.lists.filter_collected("all", criterium, n, collected, { }) for i=1,#result do local ri = result[i] local metadata = ri.metadata diff --git a/tex/context/base/strc-des.mkiv b/tex/context/base/strc-des.mkiv index 42ea701f0..d528ffae9 100644 --- a/tex/context/base/strc-des.mkiv +++ b/tex/context/base/strc-des.mkiv @@ -374,13 +374,14 @@ \def\@@stopdescription {\@@placedescriptionclosesymbol - \par % else we loose -\dostoptagged -\dostoptagged + \doifnot{\descriptionparameter\c!display}\v!no\par + \dostoptagged + \dostoptagged \endgroup \descriptionparameter\c!after % which currentdescription is taken here? - \egroup % temporary hack - \checknextindentation[\descriptionparameter\c!indentnext] + \normalexpanded + {\egroup % temporary hack + \noexpand\checknextindentation[\descriptionparameter\c!indentnext]}% \dorechecknextindentation} \def\@@dodescription @@ -422,12 +423,12 @@ \ifcsname @@description\currentdescriptionlocation\endcsname \else \let\currentdescriptionlocation\v!left \fi -\dostarttagged\t!description\currentdescription -\dostarttagged\t!descriptiontag\empty + \dostarttagged\t!description\currentdescription + \dostarttagged\t!descriptiontag\empty \@@dostartdescription \csname @@description\currentdescriptionlocation\endcsname -\dostoptagged -\dostarttagged\t!descriptioncontent\empty} % args not needed + \dostoptagged + \dostarttagged\t!descriptioncontent\empty} % args not needed \def\@@makedescription[#1]#2% {\postponenotes % new, assumes grouping @@ -1048,6 +1049,7 @@ \c!titleright=), \c!closesymbol=, \c!closecommand=\wordright, + \c!display=\v!yes, \c!command=, \c!titlecommand=] diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 0c5cea64f..3b696fbb0 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -39,6 +39,9 @@ local sections = structure.sections local sets = structure.sets local processors = structure.processors +local sprintprocessor = processors.sprint +local ignoreprocessor = processors.ignore + -- -- -- document -- -- -- local data @@ -471,6 +474,51 @@ end -- sign=positive => also zero -- sign=hang => llap sign +--~ todo: test this +--~ +--~ local function process(index,numbers,ownnumbers,criterium,separatorset,conversion,conversionset,index,entry,preceding,done) -- todo: result +--~ -- todo: too much (100 steps) +--~ local number = numbers and (numbers[index] or 0) +--~ local ownnumber = ownnumbers and ownnumbers[index] or "" +--~ if number > criterium or (ownnumber ~= "") then +--~ local block = (entry.block ~= "" and entry.block) or sections.currentblock() -- added +--~ if preceding then +--~ local separator = sets.get("structure:separators",block,separatorset,preceding,".") +--~ if result then +--~ result[#result+1] = ignoreprocessor(separator) +--~ else +--~ sprintprocessor(ctxcatcodes,separator) +--~ end +--~ preceding = false +--~ end +--~ if result then +--~ if ownnumber ~= "" then +--~ result[#result+1] = ownnumber +--~ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups) +--~ result[#result+1] = converters.convert(conversion,number,true) +--~ else +--~ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") +--~ result[#result+1] = converters.convert(theconversion,number,true) +--~ end +--~ else +--~ if ownnumber ~= "" then +--~ sprintprocessor(ctxcatcodes,ownnumber) +--~ elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups) +--~ texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",conversion,number)) +--~ -- context.convertnumber(conversion,number) +--~ else +--~ local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") +--~ sprintprocessor(ctxcatcodes,theconversion,function(str) +--~ return format("\\convertnumber{%s}{%s}",str or "numbers",number) +--~ end) +--~ end +--~ end +--~ return index, true -- preceding, done +--~ else +--~ return preceding or false, done +--~ end +--~ end + function sections.typesetnumber(entry,kind,...) -- kind='section','number','prefix' if entry and entry.hidenumber ~= true then -- can be nil local separatorset = "" @@ -535,7 +583,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref local numbers, ownnumbers = entry.numbers, entry.ownnumbers if numbers then local done, preceding = false, false - local function process(index) -- move to outer + local function process(index,result) -- move to outer -- todo: too much (100 steps) local number = numbers and (numbers[index] or 0) local ownnumber = ownnumbers and ownnumbers[index] or "" @@ -544,22 +592,35 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref if preceding then local separator = sets.get("structure:separators",block,separatorset,preceding,".") if separator then - processors.sprint(ctxcatcodes,separator) + if result then + result[#result+1] = ignoreprocessor(separator) + else + sprintprocessor(ctxcatcodes,separator) + end end preceding = false end - if ownnumber ~= "" then - processors.sprint(ctxcatcodes,ownnumber) - -- elseif conversion and conversion ~= "" then - -- texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",conversion,number)) - elseif conversion and conversion ~= "" then - -- traditional (e.g. used in itemgroups) - texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",conversion,number)) + if result then + if ownnumber ~= "" then + result[#result+1] = ownnumber + elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups) + result[#result+1] = converters.convert(conversion,number,true) + else + local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") + result[#result+1] = converters.convert(theconversion,number,true) + end else - local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") - processors.sprint(ctxcatcodes,theconversion,function(str) - return format("\\convertnumber{%s}{%s}",str or "numbers",number) - end) + if ownnumber ~= "" then + sprintprocessor(ctxcatcodes,ownnumber) + elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups) + texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",conversion,number)) + --~ context.convertnumber(conversion,number) + else + local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") + sprintprocessor(ctxcatcodes,theconversion,function(str) + return format("\\convertnumber{%s}{%s}",str or "numbers",number) + end) + end end preceding, done = index, true else @@ -567,11 +628,20 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref end end -- + local result = kind == "direct" and { } + if result then + connector = false + end + -- local prefixlist = set and sets.getall("structure:prefixes","",set) -- "" == block if starter then - processors.sprint(ctxcatcodes,starter) + if result then + result[#result+1] = ignoreprocessor(starter) + else + sprintprocessor(ctxcatcodes,starter) + end end - if prefixlist and (kind == 'section' or kind == 'prefix') then + if prefixlist and (kind == 'section' or kind == 'prefix' or kind == 'direct') then -- find valid set (problem: for sectionnumber we should pass the level) -- if kind == "section" then -- no holes @@ -616,7 +686,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref local prefix = prefixlist[k] local index = sections.getlevel(prefix) or k if index >= firstprefix and index <= lastprefix then - process(index) + process(index,result) end end -- else @@ -631,15 +701,24 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref else -- also holes check for prefix=firstprefix,lastprefix do - process(prefix) + process(prefix,result) end end -- if done and connector and kind == 'prefix' then - processors.sprint(ctxcatcodes,connector) + if result then + -- can't happen as we're in 'direct' + else + sprintprocessor(ctxcatcodes,connector) + end elseif done and stopper then - processors.sprint(ctxcatcodes,stopper) + if result then + result[#result+1] = ignoreprocessor(stopper) + else + sprintprocessor(ctxcatcodes,stopper) + end end + return result -- a table ! else -- report_structure("error: no numbers") end @@ -686,13 +765,18 @@ function sections.findnumber(depth,what) end end -function sections.fullnumber(depth,what,raw) +function sections.fullnumber(depth,what) local sectiondata = sections.findnumber(depth,what) if sectiondata then sections.typesetnumber(sectiondata,'section',sectiondata) end end +--~ function sections.directnumber(depth,what) +--~ local sectiondata = sections.findnumber(depth,what) +--~ return sectiondata and sections.typesetnumber(sectiondata,'direct',sectiondata) or "" +--~ end + function sections.getnumber(depth,what) -- redefined here local sectiondata = sections.findnumber(depth,what) texwrite((sectiondata and sectiondata.numbers[depth]) or 0) diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua index 36650cd54..f36f79672 100644 --- a/tex/context/base/strc-ini.lua +++ b/tex/context/base/strc-ini.lua @@ -232,6 +232,11 @@ function processors.apply(str) end end +function processors.ignore(str) + local p, s = lpegmatch(splitter,str) + return s or str +end + -- -- -- sets -- -- -- structure.sets = structure.sets or { } diff --git a/tex/context/base/strc-itm.mkiv b/tex/context/base/strc-itm.mkiv index e012ce447..40a515a34 100644 --- a/tex/context/base/strc-itm.mkiv +++ b/tex/context/base/strc-itm.mkiv @@ -104,7 +104,7 @@ }) }% \xdef\currentitemattribute{\number\lastdestinationattribute}% - \begingroup\attribute\destinationattribute\currentitemattribute\kern\zeropoint\endgroup % todo + \begingroup\attribute\destinationattribute\currentitemattribute\kern\zeropoint\endgroup % todo, apply attribute to symbol \fi} @@ -1258,19 +1258,23 @@ % \item {test} is this okay? % \stopitemize -\def\complexitem[#1]#2\par % todo: no two pass data - {\startitemgroup[#1]% - \complexdoitemgroupitem[]\begstrut#2\endstrut\par +% \def\complexitem[#1]#2\par % todo: no two pass data +% {\startitemgroup[#1]% +% \complexdoitemgroupitem[]\begstrut#2\endstrut\par +% \stopitemgroup} + +\def\complexitem[#1]#2\par + {\doifsomethingelse{#1}{\startitemgroup[#1]}{\startitemgroup[\v!itemize]}% + \startitem#2\stopitem \stopitemgroup} +\setvalue{\e!start\v!item}% + {\startitemgroup[\v!itemize]\startitem + \setvalue{\e!stop \v!item}{\endgraf\stopitemgroup}} % inside, else overloaded + \definecomplexorsimpleempty\item \definecomplexorsimpleempty\doitemgroupitem -\def\complexhead[#1]#2\par#3\par - {\startitemgroup[#1]% - \complexdoitemgrouphead[]\begstrut#2\endstrut\par\begstrut#3\endstrut\par - \stopitemgroup} - % the next solution accepts \head test \type{x{x}x} test ... \let\doenditemhead\relax diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua index 6af062134..c2c3c41b8 100644 --- a/tex/context/base/strc-lst.lua +++ b/tex/context/base/strc-lst.lua @@ -124,25 +124,25 @@ function lists.enhance(n) end end -function lists.enforce(n) - -- todo: symbolic names for counters - local l = cached[n] - if l then - -- - l.directives = nil -- might change - -- save in the right order (happens at shipout) - lists.tobesaved[#lists.tobesaved+1] = l - -- default enhancer (cross referencing) - l.references.realpage = texcount.realpageno - -- specific enhancer (kind of obsolete) - local kind = l.metadata.kind - local enhancer = kind and lists.enhancers[kind] - if enhancer then - enhancer(l) - end - return l - end -end +--~ function lists.enforce(n) +--~ -- todo: symbolic names for counters +--~ local l = cached[n] +--~ if l then +--~ -- +--~ l.directives = nil -- might change +--~ -- save in the right order (happens at shipout) +--~ lists.tobesaved[#lists.tobesaved+1] = l +--~ -- default enhancer (cross referencing) +--~ l.references.realpage = texcount.realpageno +--~ -- specific enhancer (kind of obsolete) +--~ local kind = l.metadata.kind +--~ local enhancer = kind and lists.enhancers[kind] +--~ if enhancer then +--~ enhancer(l) +--~ end +--~ return l +--~ end +--~ end -- we can use level instead but we can also decide to remove level from the metadata @@ -163,17 +163,17 @@ end -- will be split -local function filter_collected(names, criterium, number, collected, nested) +local function filter_collected(names, criterium, number, collected, forced, nested) -- names is hash or string local numbers, depth = documents.data.numbers, documents.data.depth - local hash, result, all, detail = { }, { }, not names or names == "" or names == variables.all, nil - names, criterium = gsub(names," ",""), gsub(criterium," ","") - if trace_lists then - report_lists("filtering names: %s, criterium: %s, number: %s",names,criterium,number or "-") + local result, detail = { }, nil + criterium = gsub(criterium," ","") -- not needed + forced = forced or { } -- todo: also on other branched, for the moment only needed for bookmarks + if type(names) == "string" then + names = aux.settings_to_hash(names) end - if not all then - for s in gmatch(names,"[^, ]+") do -- sort of settings to hash - hash[s] = true - end + local all = not next(names) or names[variables.all] or false + if trace_lists then + report_lists("filtering names: %s, criterium: %s, number: %s",aux.simple_hash_to_string(names),criterium,number or "-") end if criterium == variables.intro then -- special case, no structure yet @@ -184,15 +184,16 @@ local function filter_collected(names, criterium, number, collected, nested) result[#result+1] = v end end - elseif criterium == variables.all or criterium == variables.text then + elseif all or criterium == variables.all or criterium == variables.text then for i=1,#collected do local v = collected[i] local r = v.references if r then - local sectionnumber = (r.section == 0) or jobsections.collected[r.section] - if sectionnumber then -- and not sectionnumber.hidenumber then - local metadata = v.metadata - if metadata and not metadata.nolist and (all or hash[metadata.name or false]) then + local metadata = v.metadata + if metadata then + local name = metadata.name or false + local sectionnumber = (r.section == 0) or jobsections.collected[r.section] + if forced[name] or (sectionnumber and not metadata.nolist and (all or names[name])) then -- and not sectionnumber.hidenumber then result[#result+1] = v end end @@ -200,7 +201,7 @@ local function filter_collected(names, criterium, number, collected, nested) end elseif criterium == variables.current then if depth == 0 then - return filter_collected(names,variables.intro,number,collected) + return filter_collected(names,variables.intro,number,collected,forced) else for i=1,#collected do local v = collected[i] @@ -211,7 +212,7 @@ local function filter_collected(names, criterium, number, collected, nested) local cnumbers = sectionnumber.numbers local metadata = v.metadata if cnumbers then - if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers > depth then + if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers > depth then local ok = true for d=1,depth do local cnd = cnumbers[d] @@ -232,7 +233,7 @@ local function filter_collected(names, criterium, number, collected, nested) elseif criterium == variables.here then -- this is quite dirty ... as cnumbers is not sparse we can misuse #cnumbers if depth == 0 then - return filter_collected(names,variables.intro,number,collected) + return filter_collected(names,variables.intro,number,collected,forced) else for i=1,#collected do local v = collected[i] @@ -244,7 +245,7 @@ local function filter_collected(names, criterium, number, collected, nested) local metadata = v.metadata if cnumbers then --~ print(#cnumbers, depth, table.concat(cnumbers)) - if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers >= depth then + if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then local ok = true for d=1,depth do local cnd = cnumbers[d] @@ -264,7 +265,7 @@ local function filter_collected(names, criterium, number, collected, nested) end elseif criterium == variables.previous then if depth == 0 then - return filter_collected(names,variables.intro,number,collected) + return filter_collected(names,variables.intro,number,collected,forced) else for i=1,#collected do local v = collected[i] @@ -275,7 +276,7 @@ local function filter_collected(names, criterium, number, collected, nested) local cnumbers = sectionnumber.numbers local metadata = v.metadata if cnumbers then - if metadata and not metadata.nolist and (all or hash[metadata.name or false]) and #cnumbers >= depth then + if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then local ok = true for d=1,depth-1 do local cnd = cnumbers[d] @@ -296,11 +297,11 @@ local function filter_collected(names, criterium, number, collected, nested) elseif criterium == variables["local"] then -- not yet ok local nested = nesting[#nesting] if nested then - return filter_collected(names,nested.name,nested.number,collected,nested) + return filter_collected(names,nested.name,nested.number,collected,forced,nested) elseif sections.autodepth(documents.data.numbers) == 0 then - return filter_collected(names,variables.all,number,collected) + return filter_collected(names,variables.all,number,collected,forced) else - return filter_collected(names,variables.current,number,collected) + return filter_collected(names,variables.current,number,collected,forced) end else -- sectionname, number -- not the same as register @@ -321,7 +322,7 @@ local function filter_collected(names, criterium, number, collected, nested) local metadata = v.metadata local cnumbers = sectionnumber.numbers if cnumbers then - if (all or hash[metadata.name or false]) and #cnumbers >= depth and matching_till_depth(depth,cnumbers,parent) then + if (all or names[metadata.name or false]) and #cnumbers >= depth and matching_till_depth(depth,cnumbers,parent) then result[#result+1] = v end end @@ -342,8 +343,8 @@ end lists.filter_collected = filter_collected -function lists.filter(names, criterium, number) - return filter_collected(names, criterium, number, lists.collected) +function lists.filter(names, criterium, number, forced) + return filter_collected(names, criterium, number, lists.collected, forced) end lists.result = { } diff --git a/tex/context/base/strc-lst.mkiv b/tex/context/base/strc-lst.mkiv index 83faf75a7..5db22d1d7 100644 --- a/tex/context/base/strc-lst.mkiv +++ b/tex/context/base/strc-lst.mkiv @@ -577,13 +577,18 @@ \def\domakelistelement#1#2#3#4% ref internal command data {\dontleavehmode - \iflocation % we cannot tewak \iflocation as we nest + \iflocation % we cannot tweak \iflocation as we nest \doifelse{\listparameter\c!interaction}{#1} - {\directgoto{\setlocationcolor\??ia#4}[internal(#2)]}% was \directgotobox - {#3{#4}}% - \else + {\begingroup + \doif{\namedstructureheadparameter\currentlist\c!interaction}\v!list + {\dosetsimplepagereference{bck:#2}% + \attribute\destinationattribute\currentdestinationattribute}% + \directgoto{\setlocationcolor\??ia#4}[internal(#2)]% we can get the attribute instead so then we don't need a goto + \endgroup}% was \directgotobox + {#3{#4}}% + \else #3{#4}% - \fi} + \fi} \def\dodofreelistelement#1#2#3#4#5#6#7#8% {\listparameter\c!before% can be \hskip diff --git a/tex/context/base/strc-not.lua b/tex/context/base/strc-not.lua index 466bc7a03..f0bf6cab3 100644 --- a/tex/context/base/strc-not.lua +++ b/tex/context/base/strc-not.lua @@ -304,7 +304,11 @@ function notes.flush(tag,whatkind) -- store and postpone if trace_notes then report_notes("flushing state %s of %s from %s to %s",whatkind,tag,ns,#nd) end + -- todo: as registers: start, stop, inbetween for i=ns,#nd do + if i > ns then + texsprint(ctxcatcodes,format("\\betweennoteitself{%s}",tag)) + end texsprint(ctxcatcodes,format("\\handlenoteitself{%s}{%s}",tag,i)) end end diff --git a/tex/context/base/strc-not.mkii b/tex/context/base/strc-not.mkii index f6fae3378..a47d796e0 100644 --- a/tex/context/base/strc-not.mkii +++ b/tex/context/base/strc-not.mkii @@ -285,8 +285,6 @@ % todo: make sure less calls, is quite some code -% BEWARE, OVERLOADED IN cont-new.mkiv - \def\dochecknote % only to be called locally, some bools will become class-ones {% for the moment no mixed text/endnotes modes, so we use % \footnoteparameter and not \noteparameter (**) diff --git a/tex/context/base/strc-not.mkiv b/tex/context/base/strc-not.mkiv index 58229a54f..0a631ce0c 100644 --- a/tex/context/base/strc-not.mkiv +++ b/tex/context/base/strc-not.mkiv @@ -195,6 +195,8 @@ %\c!next=\autoinsertnextspace \c!prefix=\v!no, %\c!continue=\v!no, + \c!paragraph=\v!no, + \c!inbetween=\hskip1em, \c!n=1] \setupnotes @@ -338,8 +340,8 @@ % compatibility (will go away) -\newif\ifendnotes -\newif\ifbottomnotes +\newif\ifbottomnotes % still used in page-one.mkiv +%newif\endnotes % no longer used % locations: @@ -371,18 +373,21 @@ \def\dochecknote {% node states - \setnotelocation\plusone - \setnoteposition\plustwo + \setnotelocation\plusone % page + \setnoteposition\plustwo % high \normalexpanded{\noexpand\rawprocesscommalist[\noteparameter\c!location]}\dosetcheckednote % compatibility hack - \ifnum\noteparameter\s!noteloc=\plusfive \endnotestrue \else \endnotesfalse \fi + %ifnum\noteparameter\s!noteloc=\plusfive \endnotestrue \else \endnotesfalse \fi \ifnum\noteparameter\s!notepos=\plustwo \bottomnotestrue \else \bottomnotesfalse \fi % set column multiplier \edef\currentnotenofcolumns{\noteparameter\c!n}% \ifx\currentnotenofcolumns\empty \let\currentnotenofcolumns\!!plusone \fi - \ifcase\noteparameter\s!noteloc\or + \ifcase\noteparameter\s!noteloc + % can't happen + \scratchcounter\plusone + \or % page \scratchcounter \currentnotenofcolumns \or @@ -399,6 +404,9 @@ \scratchcounter\currentnotenofcolumns \fi % column factor + \ifcase\scratchcounter + \scratchcounter\plusone + \fi \global\count\currentnoteins\plusthousand \global\count\currentnoteins\numexpr\plusthousand/\scratchcounter\relax % maximize height @@ -704,18 +712,28 @@ \normalexpanded{\noexpand\ctxlatelua{structure.notes.setsymbolpage("#1",#2,#3)}}% \fi} -\def\handlenoteinsert#1#2% +\def\handlenoteinsert#1#2% tg, id {\begingroup \edef\currentnote{#1}% \the\everybeforenoteinsert \insert\currentnoteins\bgroup \the\everyinsidenoteinsert \doprocesslocalsetups{\noteparameter\c!setups}% experimental - \handlenoteitself{#1}{#2}% + \doifelse{\noteparameter\c!paragraph}\v!yes + {\nointerlineskip + \startvboxtohbox + \handlenoteitself{#1}{#2}% + % add some slack + \stopvboxtohbox} + {\handlenoteitself{#1}{#2}}% \egroup \the\everyafternoteinsert \endgroup} +\def\betweennoteitself#1% tg + {\edef\currentnote{#1}% + \doif{\noteparameter\c!paragraph}\v!yes\dobetweenparagraphnotes} + \def\handlenoteitself#1#2% tg, id {\edef\currentdescription{#1}% \edef\currentnote{#1}% @@ -750,10 +768,8 @@ %D mainly because endnotes had to be supported.} that is, %D automatically (vise versa) and by user supplied reference. -\newcount\internalnotereference - -\let\startpushnote=\relax -\let\stoppushnote =\relax +\let\startpushnote\relax +\let\stoppushnote \relax \newsignal\notesignal \newcount \notepenalty @@ -783,9 +799,9 @@ \splitmaxdepth\strutdp % not actually needed here \leftmargindistance\noteparameter\c!margindistance \rightmargindistance\leftmargindistance - \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? - \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? - \fi +% \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? +% \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? +% \fi \to \everyinsidenoteinsert % not: \appendtoks \setnotehsize \to \everyinsidenoteinsert (spoils columns) @@ -836,6 +852,47 @@ \unexpanded\def\unvboxed {\ifvmode\unvbox \else\box \fi} \unexpanded\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} +% idea: tag with attr and then just flush them again + +\def\dobetweenparagraphnotes % should not be too much + {\noteparameter\c!inbetween} + +\def\doflushgobalnotes + {\doifelse{\noteparameter\c!paragraph}\v!yes + {\vbox + {\beginofshapebox + \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins + \endofshapebox + %\doreshapebox{\box\shapebox}{}{}{}% get rid of penalties etc + \gdef\dodobetweenparagraphnotes{\glet\dodobetweenparagraphnotes\dobetweenparagraphnotes}% shape works reverse + \doreshapebox{\hbox{\unhbox\shapebox\dodobetweenparagraphnotes}}{}{}{}% get rid of penalties etc + \innerflushshapebox + \convertvboxtohbox}} + {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}} + +\def\dodoplacenoteinserts + {\ifcase\noteparameter\c!n\relax + % should not happen + \or + \doglobalflushnotesnormal + \else + \doglobalflushnotescolums + \fi} + +\def\doglobalflushnotesnormal + {%\iftrialtypesetting\copy\else\box\fi\currentnoteins + \doflushgobalnotes + \obeydepth} % (a) added , since split footnotes will not align properly + +\def\doglobalflushnotescolums + {\edef\currentnotewidth{\noteparameter\c!width}% + \doifdimensionelse\currentnotewidth\donothing + {\edef\currentnotewidth{\the\hsize}}% + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]% + %\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % compare with local + \doflushgobalnotes + \stopsimplecolumns} + \def\doplacenoteinserts {\relax\ifdim\ht\currentnoteins>\zeropoint\relax \ifnum\noteparameter\s!noteloc=\plusfive @@ -845,24 +902,15 @@ \whitespace \noteparameter\c!before \fi -% \bgroup -% \setupalign[\noteparameter\c!align]% + % \bgroup + % \setupalign[\noteparameter\c!align]% \placenoterule % alleen in ..mode -% \par -% \egroup + % \par + % \egroup \bgroup \setnotebodyfont \setbox\scratchbox\hbox - {% this should be checked, smells like a mix-up - % does not split: \ifcase\noteparameter\c!n\unvbox\else\box\fi\currentnoteins - \ifcase\noteparameter\c!n\relax - \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % is this needed? - \or - \iftrialtypesetting\copy\else\box\fi\currentnoteins - \obeydepth % (a) added , since split footnotes will not align properly - \else - \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins - \fi}% + {\dodoplacenoteinserts}% \setbox\scratchbox\hbox {\localframed [\??vn\currentnote] @@ -995,7 +1043,7 @@ \the\everyplacelocalnotes % beware, we cannot trust setting \currentnote here \getparameters[\??vn#2][\c!width=\v!fit,\c!height=\v!fit,\c!strut=\v!no,\c!offset=\v!overlay,#1]% we only need a selective one - \donotealternative{#2}% + \dolocalnotealternative{#2}% \endgroup \dochecknote} % we need to restore the old state @@ -1065,7 +1113,7 @@ \def\doifnotescollected#1% {\ctxlua{structure.notes.doifcontent("#1")}} -\def\donotealternative#1% +\def\dolocalnotealternative#1% {\edef\currentnote{#1}% \doifnotescollected\currentnote {\endgraf diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index 8fab48697..03c755f57 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -922,7 +922,7 @@ function jobreferences.doifelse(prefix,reference,highlight,newwindow,layer) end function jobreferences.setinternalreference(prefix,tag,internal,view) - local t = { } + local t = { } -- maybe add to current if tag then if prefix and prefix ~= "" then prefix = prefix .. ":" @@ -943,12 +943,11 @@ function jobreferences.setinternalreference(prefix,tag,internal,view) return destination end -function jobreferences.getinternalreference(n) -- n points into list +function jobreferences.getinternalreference(n) -- n points into list (todo: registers) local l = structure.lists.collected[n] texsprint(ctxcatcodes,(l and l.references.internal) or n) end - -- function jobreferences.get_current_metadata(tag) diff --git a/tex/context/base/strc-ref.mkiv b/tex/context/base/strc-ref.mkiv index 91e975ea9..408673f83 100644 --- a/tex/context/base/strc-ref.mkiv +++ b/tex/context/base/strc-ref.mkiv @@ -127,8 +127,11 @@ \def\dododosetreference#1#2#3#4% kind labels userdata text -> todo: userdata {\ifreferencing + % we could have a more efficient one for page references but for the moment + % we don't care too much \edef\currentreferencekind{#1}% \edef\currentreferencelabels{#2}% + \edef\currentreferenceuserdata{#3}% \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion} \ifx\currentreferencelabels\empty \else \ifx\currentreferenceexpansion\s!xml @@ -153,19 +156,24 @@ block = "\currentstructureblock", section = structure.sections.currentid(), }, - metadata = { - kind = "#1", - catcodes = \the\catcodetable, - xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text + metadata = { % we could assume page to have no metadata + kind = "#1", + \ifx\currentreferencekind\s!page\else + catcodes = \the\catcodetable, + xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text + \fi }, \ifx\currentreferencedata\empty\else entries = { text = \!!bs\currentreferencedata\!!es }, \fi - userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es) + \ifx\currentreferenceuserdata\empty\else + userdata = structure.helpers.touserdata(\!!bs\detokenize{#3}\!!es) + \fi },"\@@iafocus") }% + % todo: optional \xdef\currentdestinationattribute{\number\lastdestinationattribute}% \begingroup\attribute\destinationattribute\currentdestinationattribute\hbox{}\endgroup % todo \fi @@ -174,6 +182,34 @@ \def\defaultreferencepage#1{[[[#1]]]} \def\defaultreferencetext#1{[[[#1]]]} +%D For internal usage: + +\def\dosetsimplepagereference#1% label + {\iflocation + \ctxlua{jobreferences.setandgetattribute("\s!page", "\referenceprefix","#1", + { + references = { + % block = "\currentstructureblock", + % section = structure.sections.currentid(), + }, + metadata = { % we could assume page to have no metadata + kind = "\s!page", + }, + },"\@@iafocus") + }% + \xdef\currentdestinationattribute{\number\lastdestinationattribute}% + \else + \xdef\currentdestinationattribute{\number\attributeunsetvalue}% + \fi} + +\def\dogetsimplepagereference#1% + {\iflocation + \ctxlua{jobreferences.inject("\referenceprefix","#1",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% + \xdef\currentreferenceattribute{\number\lastreferenceattribute}% + \else + \xdef\currentreferenceattribute{\number\attributeunsetvalue}% + \fi} + %D These macros depend on three other ones, %D \type {\makesectionformat}, that generated \type %D {\sectionformat}, \type {\pagenumber}. The not yet used @@ -453,14 +489,26 @@ %D An unknown reference is reported on the screen, in the log %D file and, when enabled, in the left margin of the text. -\def\reportreferenceerror#1#2% only once (keep track in lua) +\def\reportreferenceerror#1#2#3% only once (keep track in lua) {\ifinpagebody \else - \doifconcepttracing{\doifsomething{#2}{\inleft{\infofont\doboundtext{#2}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% + \doifconcepttracing{\doifsomething{#3}{\inleft{\infofont\doboundtext{#3}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}% \fi - \showmessage\m!references{#1}{[\referenceprefix][#2]}} + \global\advance#1\plusone + \showmessage\m!references{#2}{[\referenceprefix][#3]}} -\def\unknownreference{\reportreferenceerror1} -\def\illegalreference{\reportreferenceerror4} +\newcount\nofunknownreferences +\newcount\nofillegalreferences + +\def\unknownreference{\reportreferenceerror\nofunknownreferences1} +\def\illegalreference{\reportreferenceerror\nofillegalreferences4} + +\def\reportreferenceproblems + {\ifcase\nofunknownreferences\else\showmessage\m!references5{\number\nofunknownreferences}\fi + \ifcase\nofillegalreferences\else\showmessage\m!references6{\number\nofillegalreferences}\fi} + +\appendtoks + \reportreferenceproblems +\to \everystoptext %D When a reference is not found, we typeset a placeholder %D (two glyphs are often enough to represent the reference @@ -541,7 +589,10 @@ {\ctxlua{jobreferences.currentorder("#1","#2")}} \def\thisissomeinternal#1#2% tag reference (only for old time sake) - {\begingroup\attribute\destinationattribute\ctxlua{jobreferences.mark("#1:#2")}\hbox{}\endgroup} + {\begingroup + \ctxlua{jobreferences.setinternalreference("","#1:#2")}% + \hbox attr \destinationattribute\lastdestinationattribute{}% + \endgroup} \def\gotosomeinternal#1#2#3#4% {\ifinternalnamedreferences @@ -866,8 +917,11 @@ %D The other alternatives just conform their names: only the %D label, only the text, or the label and the text. +% \def\dounknownreference#1#2[#3]% +% {\unknownreference{#3}\dotextprefix{#2}\dummyreference}% + \def\dounknownreference#1#2[#3]% - {\unknownreference{#3}\dotextprefix{#2}\dummyreference}% + {\unknownreference{#3}\dotextprefix{#2}{\leftofreference\dummyreference\rightofreference}} \def\docompletereference#1#2[#3]% {\goto{\dotextprefix{#2}#1}[#3]} @@ -885,114 +939,15 @@ \let\dowantedreference\docompletereference -%D \macros -%D {definereferenceformat} -%D -%D The next few macros were made for for David Arnold and Taco -%D Hoekwater. They can be used for predefining reference -%D texts, and thereby stimulate efficiency. -%D -%D [more documentation will be added] -%D -%D \starttyping -%D \definereferenceformat[informula] [left=(,right=),text=formula] -%D \definereferenceformat[informulas] [left=(,right=),text=formulas] -%D \definereferenceformat[andformula] [left=(,right=),text=and] -%D \definereferenceformat[andformulas][left=(,right=),text=and] -%D -%D \informula [b] and \informula [for:c] -%D the \informula {formulas}[b] \informula {and} [for:c] -%D the \informulas {formulas}[b] \informula {and} [for:c] -%D the \informulas [b] \informula {en} [for:c] -%D the \informulas [b] \andformula [for:c] -%D \stoptyping -%D -%D Instead of a text, one can specify a label, which should -%D be defined with \type {\setuplabeltext}. - -% todo: inherit; probably not yet mkiv okay - -\unexpanded\def\definereferenceformat - {\dodoubleargument\dodefinereferenceformat} - -\def\dodefinereferenceformat[#1][#2]% - {\iffirstargument - \getparameters[\??rf#1] - [\c!left=, % of the number - \c!right=, % of the number - \c!text=, % before the number - \c!label=, % can be {left}{right} - \c!command=\in, - #2]% - \setuvalue{#1}{\dontleavehmode\doexecutereferenceformat{#1}}% - \fi} - -\def\noexecutelabelreferenceformat#1% - {\doifvaluesomething{\??rf#1\c!text}{\gdef\textofreference{\csname\??rf#1\c!text\endcsname}}% - \csname\??rf#1\c!command\endcsname} - -\def\doexecutelabelreferenceformat#1% - {\csname\??rf#1\c!command\endcsname - {\leftlabeltext {\csname\??rf#1\c!label\endcsname}}% - {\rightlabeltext{\csname\??rf#1\c!label\endcsname}}} - -\def\doexecutereferenceformat#1% - {\gdef\leftofreference {\csname\??rf#1\c!left \endcsname}% - \gdef\rightofreference{\csname\??rf#1\c!right\endcsname}% - \glet\textofreference\empty % otherwise ~ added - \doifelsevaluenothing{\??rf#1\c!label}\noexecutelabelreferenceformat\doexecutelabelreferenceformat{#1}} - -\newtoks\everyresetreferenceformat - -\def\resetreferenceformat - {\the\everyresetreferenceformat} - -\appendtoks - \glet\leftofreference \relax - \glet\rightofreference\relax - \glet\textofreference \relax -\to \everyresetreferenceformat +\unexpanded\def\dospecialin{\dontleavehmode\begingroup\doinatreference\currentreferencedefault} % ends in \doinatreference +\unexpanded\def\dospecialat{\dontleavehmode\begingroup\doinatreference\currentreferencepage } % ends in \doinatreference -\resetreferenceformat - -% fails on metafun {\leftofreference#1\ignorespaces#3\removeunwantedspaces\rightofreference}{#2}[#4]% -% -% \def\dodododoinatreference#1#2#3[#4]% no \removeunwantedspaces (fails on metafun) -% {\ifx\next\bgroup -% \dododododoinatreference{\leftofreference#1\ignorespaces#3\rightofreference}{#2}[#4]% -% \else -% \dododododoinatreference{\leftofreference#1\rightofreference}{#2#3}[#4]% -% \fi} -% -% \def\dododododoinatreference#1#2[#3]% -% {\dontleavehmode % replaces \leaveoutervmode -% \begingroup -% \postponenotes -% \doifreferencefoundelse{#3} -% {\doifelsenothing{#1}\dosymbolreference\dowantedreference{#1}{#2}[#3]}% -% {\dounknownreference{#1}{#2}[#3]}% -% \endgroup} - -% \starttext -% \definereferenceformat[inxx] [left=(,right=),text=txt] -% \setupinteraction[state=start] -% \chapter[one]{xx} -% [\goto{state}[file(mk-last-state)]] -% [\goto{state} [file(mk-last-state)]] -% [\at{page} [one]] -% [\at{page}[one]] -% [\at{page}{okay}[one]] -% [\inxx{a}{b}[one]] -% \stoptext +\newtoks\leftreferencetoks \newtoks\defaultleftreferencetoks \glet\leftofreference \relax +\newtoks\rightreferencetoks \newtoks\defaultrightreferencetoks \glet\rightofreference\relax -\unexpanded\def\dospecialin{\let\currentreferencecontent\currentreferencedefault\doinatreference} -\unexpanded\def\dospecialat{\let\currentreferencecontent\currentreferencepage \doinatreference} - -\newtoks\leftreferencetoks % needs a reset too? -\newtoks\rightreferencetoks - -\def\doinatreference - {\futurelet\next\doinatreferenceone} +\def\doinatreference#1% + {\let\currentreferencecontent#1% + \futurelet\next\doinatreferenceone} \def\doinatreferenceone {\ifx\next\bgroup @@ -1017,8 +972,8 @@ \def\dodoinatreferencenone {\dodoinatreferenceindeed - {\leftofreference\currentreferencecontent\rightofreference} - {}} + {\the\defaultleftreferencetoks\leftofreference\currentreferencecontent\rightofreference} + {\the\defaultrightreferencetoks}} \def\dodoinatreferenceleft {\dodoinatreferenceindeed @@ -1026,22 +981,126 @@ {\the\leftreferencetoks}} \def\dodoinatreferenceboth - {\dodoinatreferenceindeed + {\doifnothing{\the\leftreferencetoks} + {\leftreferencetoks\defaultleftreferencetoks}% + \dodoinatreferenceindeed {\leftofreference\currentreferencecontent\the\rightreferencetoks\rightofreference} {\the\leftreferencetoks}} +% lefttext left <ref> right righttext + +\newtoks\everyresetinatreference + \def\dodoinatreferenceindeed#1#2#3[#4]% #3 gobbles space - {\dontleavehmode % replaces \leaveoutervmode - \begingroup + {%\dontleavehmode\begingroup % already done \postponenotes \doifreferencefoundelse{#4} {\doifelsenothing{#1}\dosymbolreference\dowantedreference{#1}{#2}[#4]}% {\dounknownreference{#1}{#2}[#4]}% - \resetreferenceformat + \the\everyresetinatreference \endgroup} \let\dosymbolreference\dowantedreference +\appendtoks + \glet\leftofreference \relax + \glet\rightofreference\relax +\to \everyresetinatreference + +%D \macros +%D {definereferenceformat} +%D +%D The next few macros were made for for David Arnold and Taco +%D Hoekwater. They can be used for predefining reference +%D texts, and thereby stimulate efficiency. +%D +%D \starttyping +%D \definereferenceformat[informula] [left=(,right=),text=formula] +%D \definereferenceformat[informulas] [left=(,right=),text=formulas] +%D \definereferenceformat[andformula] [left=(,right=),text=and] +%D \definereferenceformat[andformulas][left=(,right=),text=and] +%D +%D \informula [b] and \informula [for:c] +%D the \informula {formulas}[b] \informula {and} [for:c] +%D the \informulas {formulas}[b] \informula {and} [for:c] +%D the \informulas [b] \informula {en} [for:c] +%D the \informulas [b] \andformula [for:c] +%D \stoptyping +%D +%D Instead of a text, one can specify a label, which should +%D be defined with \type {\setuplabeltext}. +%D +%D +%D Watch out: the second argument is somewhat special and mostly +%D meant for a suffix to a number: +%D +%D \startbuffer +%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~] +%D \definereferenceformat [intestb] [left=(,right=),label=figure] +%D +%D \placeformula[x]\startformula a \stopformula +%D +%D \starttabulate[|||||] +%D \NC \in [x] \NC \in {left}[x] \NC \in {}{right}[x] \NC \in {left}{right}[x] \NC \NR +%D \NC \intesta[x] \NC \intesta{left}[x] \NC \intesta{}{right}[x] \NC \intesta{left}{right}[x] \NC \NR +%D \NC \intestb[x] \NC \intestb{left}[x] \NC \intestb{}{right}[x] \NC \intestb{left}{right}[x] \NC \NR +%D \stoptabulate +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +% todo: inherit + +\let\currentreferenceformat\empty + +\def\referenceformatparameter#1% some day we will add inheritance + {\ifcsname\??rf\currentreferenceformat#1\endcsname\csname\??rf\currentreferenceformat#1\expandafter\endcsname\fi} + +\unexpanded\def\definereferenceformat + {\dodoubleargument\dodefinereferenceformat} + +% left right text label + +\def\dodefinereferenceformat[#1][#2]% + {\iffirstargument + \getparameters[\??rf#1][\c!left=,\c!right=,\c!text=,\c!label=,#2]% + \setuvalue{#1}{\doexecutereferenceformat{#1}}% + \fi} + +\def\doexecutereferenceformat#1% + {\dontleavehmode\begingroup % ends in \doinatreference + \edef\currentreferenceformat{#1}% + \gdef\leftofreference {\referenceformatparameter\c!left }% + \gdef\rightofreference{\referenceformatparameter\c!right}% + % we can make a helper for this .. we will use the new parameter handler anyway + % but at least aditya can play with it now + \doifsomething{\referenceformatparameter\c!style} + {\dosetfontattribute{\??rf\currentreferenceformat}\c!style + \let\@@iastyle\empty}% + \doifsomething{\referenceformatparameter\c!color} + {\dosetcolorattribute{\??rf\currentreferenceformat}\c!color + \let\@@iacontrastcolor\empty + \let\@@iacolor \empty}% + % + \doifsomethingelse{\referenceformatparameter\c!label} + {\defaultleftreferencetoks {\leftlabeltext {\referenceformatparameter\c!label}}% + \defaultrightreferencetoks{\rightlabeltext{\referenceformatparameter\c!label}}}% + {\defaultleftreferencetoks {\referenceformatparameter\c!text}% + \defaultrightreferencetoks\emptytoks}% + \doinatreference\currentreferencedefault} % we can make \currentreferencedefault configurable + +% \starttext +% \definereferenceformat[inxx] [left=(,right=),text=txt] +% \setupinteraction[state=start] +% \chapter[one]{xx} +% [\goto{state}[file(mk-last-state)]] +% [\goto{state} [file(mk-last-state)]] +% [\at{page} [one]] +% [\at{page}[one]] +% [\at{page}{okay}[one]] +% [\inxx{a}{b}[one]] +% \stoptext + %D In interactive documents going to a specific location is not %D bound to cross references. The \type{\goto} commands can be %D used to let users access another part of the document. In @@ -1081,14 +1140,16 @@ \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty % not here \ctxlua{jobreferences.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}% -\dostoptagged \setlocationattributes\??ia \setstrut % can be option \attribute\referenceattribute\lastreferenceattribute + #1% + \dostoptagged + \else + #1% \fi - #1% \endgroup} \def\dodirectgotohtdp#1[#2]% no test for valid references @@ -1096,9 +1157,9 @@ \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.inject("\referenceprefix","#2",\number\dimexpr\@@iaheight\relax,\number\dimexpr\@@iadepth\relax,\extrareferencearguments)}% -\dostoptagged + \dostoptagged \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute \fi @@ -1113,9 +1174,9 @@ \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}% -\dostoptagged + \dostoptagged \setlocationattributes\??ia \setstrut % can be option \attribute\referenceattribute\lastreferenceattribute}% @@ -1132,9 +1193,9 @@ \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#3",\extrareferencearguments)}% {\expandtexincurrentreference -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.injectcurrentset(\number\dimexpr\@@iaheight\relax,\number\dimexpr\@@iadepth\relax)}% -\dostoptagged + \dostoptagged \setlocationattributes\??ia \attribute\referenceattribute\lastreferenceattribute}% {\unknownreference{#3}}% @@ -1147,9 +1208,9 @@ \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% -\dostoptagged + \dostoptagged \setlocationattributes\??ia \hbox attr \referenceattribute \lastreferenceattribute {#1}% \else @@ -1162,9 +1223,9 @@ \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}% -\dostoptagged + \dostoptagged \setlocationcolorspec{#1}% no consequence for strut \hbox attr \referenceattribute \lastreferenceattribute {#2}% \else @@ -1177,9 +1238,9 @@ \begingroup \attribute\referenceattribute\attributeunsetvalue \iflocation -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}% -\dostoptagged + \dostoptagged \hbox attr \referenceattribute \lastreferenceattribute {#1}% \else #1% @@ -1193,9 +1254,9 @@ \iflocation \ctxlua{jobreferences.doifelse("\referenceprefix","#2",\extrareferencearguments)}% {\expandtexincurrentreference -\dostarttagged\t!link\empty + \dostarttagged\t!link\empty \ctxlua{jobreferences.injectcurrentset(nil,nil)}% -\dostoptagged + \dostoptagged \setlocationattributes\??ia \hbox attr \referenceattribute \lastreferenceattribute {#1}}% {\unknownreference{#2}}% @@ -1215,7 +1276,6 @@ {\unknownreference{#3}}% \endgroup} - %D An reference to another document can be specified as a file %D or as an \URL. Both are handled by the same mechanism and %D can be issued by saying something like: diff --git a/tex/context/base/strc-reg.mkiv b/tex/context/base/strc-reg.mkiv index 413ccb81a..dc37423de 100644 --- a/tex/context/base/strc-reg.mkiv +++ b/tex/context/base/strc-reg.mkiv @@ -268,6 +268,8 @@ \xdef\currentregistersynchronize{\ctxlatelua{jobregisters.enhance("\currentregister",\currentregisternumber)}}% \fi \currentregistersynchronize % here? + % needs thinking ... bla\index{bla}. will break before the . but adding a + % penalty is also no solution \attribute\destinationattribute\lastdestinationattribute \forcecolorhack % no \strut as it will be removed during cleanup \endgroup} diff --git a/tex/context/base/strc-ren.mkiv b/tex/context/base/strc-ren.mkiv index 3a60a34a3..ad972d9e6 100644 --- a/tex/context/base/strc-ren.mkiv +++ b/tex/context/base/strc-ren.mkiv @@ -123,7 +123,13 @@ % \newif\ifemptyhead % \newif\ifdisplaysectionhead -\def\structureheadattribute{\iflocation attr \destinationattribute \currentstructureattribute\fi} +\let\currentstructurereferenceattribute\attributeunsetvalue + +\def\structureheadattribute + {\iflocation + attr \destinationattribute \currentstructureattribute + attr \referenceattribute \currentstructurereferenceattribute + \fi} \def\doplacestructureheadtext#1#2#3% nodes, text, endstuff {\beginheadplacement @@ -132,6 +138,9 @@ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadattribute to \zeropoint {#1}% \makestrutofbox\sectionheadbox \else + \doif{\namedstructureheadparameter\currentstructurehead\c!interaction}\v!list + {\dogetsimplepagereference{bck:\nextinternalreference}% + \let\currentstructurereferenceattribute\currentreferenceattribute}% \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadattribute {\doresettructureheadnumbercontent \ifcase\headtimingmode\or#1\fi % outerside font determines distance @@ -147,6 +156,9 @@ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadattribute to \zeropoint{#1}% \makestrutofbox\sectionheadbox \else % = needed + \doif{\namedstructureheadparameter\currentstructurehead\c!interaction}\v!list + {\dogetsimplepagereference{bck:\nextinternalreference}% + \let\currentstructurereferenceattribute\currentreferenceattribute}% \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadattribute {\ifcase\headtimingmode\or#1\fi \dosetfontattribute{\??nh\currentstructurehead}\c!style @@ -154,6 +166,7 @@ \fi \endheadplacement{#4}} + \unexpanded\def\placestructureheadnumbertext {\doplacestructureheadnumbertext\empty\getstructureheadnumber\getstructureheadtitle\getstructureheadsyncs} diff --git a/tex/context/base/strc-sec.mkiv b/tex/context/base/strc-sec.mkiv index 2dd602448..fe2a0fddc 100644 --- a/tex/context/base/strc-sec.mkiv +++ b/tex/context/base/strc-sec.mkiv @@ -52,8 +52,9 @@ % interface -\def\structureheadparameter #1{\csname\dostructureheadparameter{\??nh\currentstructurehead}#1\endcsname} -\def\structureheadparameterhash#1{\dostructureheadparameterhash {\??nh\currentstructurehead}#1} +\def\structureheadparameter #1{\csname\dostructureheadparameter{\??nh\currentstructurehead}#1\endcsname} +\def\structureheadparameterhash #1{\dostructureheadparameterhash {\??nh\currentstructurehead}#1} +\def\namedstructureheadparameter#1#2{\csname\dostructureheadparameter{\??nh#1}#2\endcsname} \def\dostructureheadparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dostructureheadparentparameter \csname#1\s!parent\endcsname#2\fi} \def\dostructureheadparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dostructureheadparentparameterhash\csname#1\s!parent\endcsname#2\fi} @@ -377,6 +378,8 @@ \let\currentstructureheadlevel \!!zerocount \let\currentstructureheadcounter \!!zerocount +% here we could inherit as well but it's a bit complex + \def\doregisterstructurehead#1#2#3% name data userdata {\structurecomponent [\c!label={\structureheadparameter\c!label}, diff --git a/tex/context/base/strc-syn.mkiv b/tex/context/base/strc-syn.mkiv index 65f517437..0866ea209 100644 --- a/tex/context/base/strc-syn.mkiv +++ b/tex/context/base/strc-syn.mkiv @@ -114,7 +114,7 @@ \fi \setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name \fi - \getparameters[\??sm#1][\s!parent=\??sm,\s!multi={#2}]% + \getparameters[\??sm#1][\s!parent=\??sm,\s!single={#1},\s!multi={#2}]% \presetheadtext[#2=\Word{#2}]% changes the \if...argument %\ctxlua{joblists.define('#1')}% \setvalue{\e!setup #2\e!endsetup}{\dodoubleargument\getparameters[\??sm#1]}% to be obsolete @@ -207,8 +207,9 @@ \def\completelistofsynonyms {\dodoubleempty\docompletelistofsynonyms} -\def\docompletelistofsynonyms[#1][#2]% expansion needed to avoid v! (due to french active !) - {\normalexpanded{\systemsuppliedchapter[#1]{\noexpand\headtext{\synonymparameter\s!single}}}% +\def\docompletelistofsynonyms[#1][#2]% + {\edef\currentsynonym{#1}% + \normalexpanded{\systemsuppliedchapter[#1]{\noexpand\headtext{\synonymparameter\s!multi}}}% \doplacelistofsynonyms[#1][#2]% \page[\v!yes]} diff --git a/tex/context/base/strc-tag.lua b/tex/context/base/strc-tag.lua index 4381fc529..d69525bc9 100644 --- a/tex/context/base/strc-tag.lua +++ b/tex/context/base/strc-tag.lua @@ -28,7 +28,8 @@ local tags, labels, stack, chain, ids, enabled = { }, { }, { }, { }, { }, false structure.tags.taglist = tags -- can best be hidden function structure.tags.start(tag,label,detail) - labels[label or tag] = tag +--~ labels[label or tag] = tag + labels[tag] = label ~= "" and label or tag if detail and detail ~= "" then tag = tag .. ":" .. detail end diff --git a/tex/context/base/syst-ext.mkii b/tex/context/base/syst-ext.mkii index 73fb98b72..745478526 100644 --- a/tex/context/base/syst-ext.mkii +++ b/tex/context/base/syst-ext.mkii @@ -4991,9 +4991,9 @@ \def\comparedimensioneps#1#2% {\chardef\compresult - \ifdim\dimexpr(#1-#2)<\roudingeps + \ifdim\dimexpr#1-#2\relax<\roudingeps \zerocount - \else\ifdim\dimexpr(#2-#1)<\roudingeps + \else\ifdim\dimexpr#2-#1\relax<\roudingeps \zerocount \else\ifdim#1<#2% \plusone diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv index 67d20a615..e183e5552 100644 --- a/tex/context/base/tabl-ntb.mkiv +++ b/tex/context/base/tabl-ntb.mkiv @@ -721,10 +721,10 @@ % permits \expanded{\bTD ... \eTD} -\unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows -\unexpanded\def\eTD{\ignorespaces} -\unexpanded\def\eTH{\ignorespaces} -\unexpanded\def\eTN{\ignorespaces} +\let\bTR\relax \unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows +\let\bTD\relax \unexpanded\def\eTD{\ignorespaces} +\let\bTH\relax \unexpanded\def\eTH{\ignorespaces} +\let\bTN\relax \unexpanded\def\eTN{\ignorespaces} \unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode {% tricky and dirty order -) diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv index 007338146..196a21850 100644 --- a/tex/context/base/tabl-tbl.mkiv +++ b/tex/context/base/tabl-tbl.mkiv @@ -696,8 +696,8 @@ [\c!unit,\c!distance,\c!before,\c!bodyfont,\c!after, \c!inner,\c!indenting,\c!frame,\c!split,\c!header,\c!title, \c!margin,\c!align,\c!rulecolor,\c!rulethickness,EQ]% - \setvalue{\e!start#1::#2}{\dofinalstarttabulate[#1][#2][#3]}% - \setvalue{\e!start#1}{\bgroup\dosubstarttabulate[#1]}% + \setuvalue{\e!start#1::#2}{\dofinalstarttabulate[#1][#2][#3]}% + \setuvalue{\e!start#1}{\bgroup\dosubstarttabulate[#1]}% \letvalue{\??tt#1-\v!header}\empty \letvalue{\??tt#1-\v!footer }\empty \else\ifsecondargument @@ -752,14 +752,14 @@ \TABLEnoalign{\kern-\lineheight}% \fi} -\setvalue{\e!start\v!tabulatehead}% +\setuvalue{\e!start\v!tabulatehead}% {\dosingleempty\dostartstarttabulatehead} \def\dostartstarttabulatehead[#1]% {\processcontent{\e!stop\v!tabulatehead}\next {\letvalue{\??tt\iffirstargument#1\else\v!tabulate\fi::-\v!header}\next}} -\setvalue{\e!start\v!tabulatetail}% +\setuvalue{\e!start\v!tabulatetail}% {\dosingleempty\dostartstarttabulatetail} \def\dostartstarttabulatetail[#1]% @@ -772,9 +772,13 @@ \def\dodosubstarttabulate[#1][#2]% {\csname\e!start#1::\ifcsname\e!start#1::#2\endcsname#2\fi\endcsname} -\setvalue{\e!start\v!tabulate}% +\setuvalue{\e!start\v!tabulate}% {\bgroup\dodoubleempty\donormalstarttabulate} +\setuvalue{\e!stop\v!tabulate }{} +\setuvalue{\e!stop\v!tabulatehead}{} +\setuvalue{\e!stop\v!tabulatetail}{} + \bgroup \gdef\donormalstarttabulate[#1][#2]% diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua index 4c5ac401d..a04736487 100644 --- a/tex/context/base/task-ini.lua +++ b/tex/context/base/task-ini.lua @@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['task-ini'] = { tasks.appendaction("processors", "normalizers", "fonts.collections.process") -- todo tasks.appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled -tasks.appendaction("processors", "characters", "chars.handle_mirroring") -- disabled +tasks.appendaction("processors", "characters", "mirroring.handler") -- disabled tasks.appendaction("processors", "characters", "typesetting.cases.handler") -- disabled tasks.appendaction("processors", "characters", "typesetting.breakpoints.handler") -- disabled tasks.appendaction("processors", "characters", "scripts.preprocess") @@ -76,7 +76,7 @@ tasks.disableaction("processors", "chars.handle_breakpoints") tasks.disableaction("processors", "typesetting.cases.handler") tasks.disableaction("processors", "typesetting.digits.handler") tasks.disableaction("processors", "typesetting.breakpoints.handler") -tasks.disableaction("processors", "chars.handle_mirroring") +tasks.disableaction("processors", "mirroring.handler") tasks.disableaction("processors", "languages.words.check") tasks.disableaction("processors", "typesetting.spacings.handler") tasks.disableaction("processors", "typesetting.kerns.handler") diff --git a/tex/context/base/trac-set.lua b/tex/context/base/trac-set.lua index a9c55f954..e7498ea85 100644 --- a/tex/context/base/trac-set.lua +++ b/tex/context/base/trac-set.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['trac-set'] = { local type, next, tostring = type, next, tostring local concat = table.concat -local format, find, lower, gsub = string.format, string.find, string.lower, string.gsub +local format, find, lower, gsub, simpleesc = string.format, string.find, string.lower, string.gsub, string.simpleesc local is_boolean = string.is_boolean setters = { } @@ -80,7 +80,7 @@ local function set(t,what,newvalue) for name, functions in next, data do if done[name] then -- prevent recursion due to wildcards - elseif find(name,w) then + elseif find(name,simpleesc(w)) then done[name] = true for i=1,#functions do functions[i](value) @@ -144,14 +144,14 @@ end function setters.enable(t,what) local e = t.enable t.enable, t.done = enable, { } - enable(t,string.simpleesc(tostring(what))) + enable(t,what) t.enable, t.done = e, { } end function setters.disable(t,what) local e = t.disable t.disable, t.done = disable, { } - disable(t,string.simpleesc(tostring(what))) + disable(t,what) t.disable, t.done = e, { } end @@ -215,36 +215,50 @@ trackers = setters.new("trackers") directives = setters.new("directives") experiments = setters.new("experiments") +-- experiment + +if trackers and environment and environment.engineflags.trackers then + trackers.enable(environment.engineflags.trackers) +end +if directives and environment and environment.engineflags.directives then + directives.enable(environment.engineflags.directives) +end + -- nice trick: we overload two of the directives related functions with variants that -- do tracing (itself using a tracker) .. proof of concept +local function report(...) -- messy .. chicken or egg + local p = (commands and commands.writestatus) or (logs and logs.report) + if p then p(...) end +end + local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end) local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end) -local e = directives.enable -local d = directives.disable +local enable = directives.enable +local disable = directives.disable function directives.enable(...) - (commands.writestatus or logs.report)("directives","enabling: %s",concat({...}," ")) - e(...) + report("directives","enabling: %s",concat({...}," ")) + enable(...) end function directives.disable(...) - (commands.writestatus or logs.report)("directives","disabling: %s",concat({...}," ")) - d(...) + report("directives","disabling: %s",concat({...}," ")) + disable(...) end -local e = experiments.enable -local d = experiments.disable +local enable = experiments.enable +local disable = experiments.disable function experiments.enable(...) - (commands.writestatus or logs.report)("experiments","enabling: %s",concat({...}," ")) - e(...) + report("experiments","enabling: %s",concat({...}," ")) + enable(...) end function experiments.disable(...) - (commands.writestatus or logs.report)("experiments","disabling: %s",concat({...}," ")) - d(...) + report("experiments","disabling: %s",concat({...}," ")) + disable(...) end -- a useful example @@ -252,3 +266,12 @@ end directives.register("system.nostatistics", function(v) statistics.enable = not v end) + +-- experiment + +if trackers and environment and environment.engineflags.trackers then + trackers.enable(environment.engineflags.trackers) +end +if directives and environment and environment.engineflags.directives then + directives.enable(environment.engineflags.directives) +end diff --git a/tex/context/base/type-dejavu.mkiv b/tex/context/base/type-dejavu.mkiv index 116d3ca4c..ac83123db 100644 --- a/tex/context/base/type-dejavu.mkiv +++ b/tex/context/base/type-dejavu.mkiv @@ -16,25 +16,25 @@ \starttypescript [serif] [dejavu] [name] \setups[font:fallback:serif] \definefontsynonym [Serif] [name:dejavuserif] [features=default] - \definefontsynonym [SerifBold] [name:dejavuserifitalic] [features=default] - \definefontsynonym [SerifItalic] [name:dejavuserifbold] [features=default] + \definefontsynonym [SerifBold] [name:dejavuserifbold] [features=default] + \definefontsynonym [SerifItalic] [name:dejavuserifitalic] [features=default] \definefontsynonym [SerifBoldItalic] [name:dejavuserifbolditalic] [features=default] \stoptypescript \starttypescript [sans] [dejavu] [name] \setups[font:fallback:sans] \definefontsynonym [Sans] [name:dejavusans] [features=default] - \definefontsynonym [SansBold] [name:dejavusansoblique] [features=default] - \definefontsynonym [SansItalic] [name:dejavusansbold] [features=default] + \definefontsynonym [SansBold] [name:dejavusansbold] [features=default] + \definefontsynonym [SansItalic] [name:dejavusansoblique] [features=default] \definefontsynonym [SansBoldItalic] [name:dejavusansboldoblique] [features=default] \stoptypescript \starttypescript [mono] [dejavu] [name] \setups[font:fallback:mono] - \definefontsynonym [Mono] [name:dejavusansmono] [features=default] - \definefontsynonym [MonoBold] [name:dejavusansmonooblique] [features=default] - \definefontsynonym [MonoItalic] [name:dejavusansmonobold] [features=default] - \definefontsynonym [MonoBoldItalic] [name:dejavusansmonoboldoblique] [features=default] + \definefontsynonym [Mono] [name:dejavusansmono] [features=none] + \definefontsynonym [MonoBold] [name:dejavusansmonobold] [features=none] + \definefontsynonym [MonoItalic] [name:dejavusansmonooblique] [features=none] + \definefontsynonym [MonoBoldItalic] [name:dejavusansmonoboldoblique] [features=none] \stoptypescript \starttypescript[dejavu] diff --git a/tex/context/base/type-otf.mkii b/tex/context/base/type-otf.mkii index cfda29fd7..05a6d3987 100644 --- a/tex/context/base/type-otf.mkii +++ b/tex/context/base/type-otf.mkii @@ -839,6 +839,23 @@ \usemathcollection[default] \stoptypescript + \starttypescript [math] [times] [name] + \definefontsynonym [MathRoman] [Times-Roman-Upright] + \definefontsynonym [MathExtension] [Times-Math-Extension] + \definefontsynonym [MathItalic] [Times-Math-Italic] + \definefontsynonym [MathSymbol] [Times-Math-Symbols] + \definefontsynonym [MathAlpha] [Times-Math-SymbolsA] + \definefontsynonym [MathBeta] [Times-Math-SymbolsB] + \stoptypescript + + \starttypescript [math] [times] [name] + \definefontsynonym [OldStyle] [MathItalic] + \definefontsynonym [Fraktur] [eufm10] + \definefontsynonym [Blackboard] [MathBeta] + \definefontsynonym [Gothic] [eufm10] + \definefontsynonym [Calligraphic] [eusm10] + \stoptypescript + \starttypescript [math] [palatino] [all] \definefontsynonym [Palatino-Roman-Upright] [pxr] \definefontsynonym [Palatino-Roman-Italic] [pxi] @@ -860,6 +877,23 @@ \usemathcollection[default] \stoptypescript + \starttypescript [math] [palatino] [name] + \definefontsynonym [MathRoman] [Palatino-Roman-Upright] + \definefontsynonym [MathExtension] [Palatino-Math-Extension] + \definefontsynonym [MathItalic] [Palatino-Math-Italic] + \definefontsynonym [MathSymbol] [Palatino-Math-Symbols] + \definefontsynonym [MathAlpha] [Palatino-Math-SymbolsA] + \definefontsynonym [MathBeta] [Palatino-Math-SymbolsB] + \stoptypescript + + \starttypescript [math] [palatino] [name] + \definefontsynonym [OldStyle] [MathItalic] + \definefontsynonym [Fraktur] [eufm10] + \definefontsynonym [Blackboard] [MathBeta] + \definefontsynonym [Gothic] [eufm10] + \definefontsynonym [Calligraphic] [eusm10] + \stoptypescript + \stoptypescriptcollection \starttypescriptcollection[antykwa] diff --git a/tex/context/base/type-otf.mkiv b/tex/context/base/type-otf.mkiv index b889e1ad2..24b9f4f6e 100644 --- a/tex/context/base/type-otf.mkiv +++ b/tex/context/base/type-otf.mkiv @@ -450,7 +450,7 @@ \definetypescriptprefix [f:cursor] [cursor] \definetypescriptprefix [f:courier] [cursor] \definetypescriptprefix [f:chorus] [chorus] \definetypescriptprefix [f:chancery] [chorus] % not the full set - \starttypescript [serif,sans,mono] [adventor,bonum,bookman,cursor,courier,heros,helvetica,pagella,palatino,schola,schoolbook,termes,times] + \starttypescript [serif,sans] [adventor,bonum,bookman,heros,helvetica,pagella,palatino,schola,schoolbook,termes,times] \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!default] \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!default] \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!default] @@ -461,6 +461,13 @@ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!smallcaps] \stoptypescript + \starttypescript [mono] [cursor,courier] + \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!none] + \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!none] + \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!none] + \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!none] + \stoptypescript + \starttypescript [serif,calligraphy] [chorus,chancery] \definefontsynonym [TeXGyreChorus-MediumItalic] [\s!file:texgyrechorus-mediumitalic] [\s!features=\s!default] \stoptypescript @@ -1458,7 +1465,7 @@ \starttypescript [lucida] \definetypeface [lucida] [rm] [\s!serif] [lucida] [\s!default] [\s!features=\s!default] \definetypeface [lucida] [ss] [\s!sans] [lucida] [\s!default] [\s!features=\s!default] - \definetypeface [lucida] [tt] [\s!mono] [lucida] [\s!default] [\s!features=\s!default] + \definetypeface [lucida] [tt] [\s!mono] [lucida] [\s!default] [\s!features=\s!none] \definetypeface [lucida] [hw] [\s!handwriting] [lucida] [\s!default] [\s!features=\s!default] \definetypeface [lucida] [cg] [\s!calligraphy] [lucida] [\s!default] [\s!features=\s!default] \definetypeface [lucida] [mm] [\s!math] [lucida] [\s!default] @@ -1497,8 +1504,8 @@ \starttypescript[asana] \definetypeface [\typescriptone] [rm] [\s!serif] [palatino] [\s!default] - \definetypeface [\typescriptone] [ss] [\s!sans] [modern] [\s!default] [rscale=1.075] - \definetypeface [\typescriptone] [tt] [\s!mono] [modern] [\s!default] [rscale=1.075] + \definetypeface [\typescriptone] [ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.075] + \definetypeface [\typescriptone] [tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.075] \definetypeface [\typescriptone] [mm] [\s!math] [\typescriptone] [\s!default] \quittypescriptscanning \stoptypescript @@ -1613,18 +1620,18 @@ \starttypescript [sans] [mscorearial] [name] \setups[\s!font:\s!fallback:\s!sans] - \definefontsynonym [\s!Sans] [\s!file:arial.ttf] [\s!features=default] - \definefontsynonym [\s!SansBold] [\s!file:arialbd.ttf] [\s!features=default] - \definefontsynonym [\s!SansItalic] [\s!file:ariali.ttf] [\s!features=default] - \definefontsynonym [\s!SansBoldItalic] [\s!file:arialbi.ttf] [\s!features=default] + \definefontsynonym [\s!Sans] [\s!file:arial.ttf] [\s!features=\s!default] + \definefontsynonym [\s!SansBold] [\s!file:arialbd.ttf] [\s!features=\s!default] + \definefontsynonym [\s!SansItalic] [\s!file:ariali.ttf] [\s!features=\s!default] + \definefontsynonym [\s!SansBoldItalic] [\s!file:arialbi.ttf] [\s!features=\s!default] \stoptypescript \starttypescript [mono] [mscorecourier] [name] \setups[\s!font:\s!fallback:\s!mono] - \definefontsynonym [\s!Mono] [\s!file:cour.ttf] [\s!features=\s!default] - \definefontsynonym [\s!MonoBold] [\s!file:courbd.ttf] [\s!features=\s!default] - \definefontsynonym [\s!MonoItalic] [\s!file:couri.ttf] [\s!features=\s!default] - \definefontsynonym [\s!MonoBoldItalic] [\s!file:courbi.ttf] [\s!features=\s!default] + \definefontsynonym [\s!Mono] [\s!file:cour.ttf] [\s!features=\s!none] + \definefontsynonym [\s!MonoBold] [\s!file:courbd.ttf] [\s!features=\s!none] + \definefontsynonym [\s!MonoItalic] [\s!file:couri.ttf] [\s!features=\s!none] + \definefontsynonym [\s!MonoBoldItalic] [\s!file:courbi.ttf] [\s!features=\s!none] \stoptypescript \starttypescript [sans] [mscoreverdana] [name] @@ -1671,10 +1678,10 @@ \starttypescript [mono] [liberation] [name] \setups[\s!font:\s!fallback:\s!mono] - \definefontsynonym [\s!Mono] [\s!file:liberationmono-regular] [\s!features=\s!default] - \definefontsynonym [\s!MonoBold] [\s!file:liberationmono-bold] [\s!features=\s!default] - \definefontsynonym [\s!MonoItalic] [\s!file:liberationmono-italic] [\s!features=\s!default] - \definefontsynonym [\s!MonoBoldItalic] [\s!file:liberationmono-bolditalic] [\s!features=\s!default] + \definefontsynonym [\s!Mono] [\s!file:liberationmono-regular] [\s!features=\s!none] + \definefontsynonym [\s!MonoBold] [\s!file:liberationmono-bold] [\s!features=\s!none] + \definefontsynonym [\s!MonoItalic] [\s!file:liberationmono-italic] [\s!features=\s!none] + \definefontsynonym [\s!MonoBoldItalic] [\s!file:liberationmono-bolditalic] [\s!features=\s!none] \stoptypescript \starttypescript[liberation] @@ -1862,22 +1869,43 @@ \starttypescriptcollection[punk] - \definefontfeature[punknova][mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes] + \definefontfeature [punknova] [mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes] + \definefontfeature [punknova-slanted] [punknova] [slant=.25] \starttypescript [serif] [punknova] - \setups[font:fallback:serif] % no style variants yet, actually it's a sans - \definefontsynonym [Serif] [file:punknova] [features=punknova] + \definefontsynonym [Serif] [\s!file:punknova-regular] [\s!features=punknova] + \definefontsynonym [SerifSlanted] [\s!file:punknova-regular] [\s!features=punknova-slanted] + \definefontsynonym [SerifBold] [\s!file:punknova-bold] [\s!features=punknova] + \definefontsynonym [SerifBoldSlanted][\s!file:punknova-bold] [\s!features=punknova-slanted] + \definefontsynonym [SerifItalic] [SerifSlanted] + \definefontsynonym [SerifBoldItalic] [SerifBoldSlanted] \stoptypescript + % \definefontfeature [slanted-25] [slant=.25] + % \starttypescript [serif] [punknova] + % \definefontsynonym [SerifSlanted] [\s!file:punknova-regular] [\s!features={punknova,slanted-25}] + % \stoptypescript + \starttypescript [punknova] \definetypeface [punknova] [rm] [serif] [punknova] [default] \stoptypescript \stoptypescriptcollection -% \starttypescript [math] [hvmath] -% \definefontsynonym[MathRoman][hvmath@hvmath-math] -% \loadfontgoodies[hvmath-math] -% \stoptypescript +% \starttypescriptcollection[hvmath] + +% \starttypescript [math] [hvmath] +% \definefontsynonym[MathRoman][hvmath@hvmath-math] +% \loadfontgoodies[hvmath-math] +% \stoptypescript + +% \starttypescript [hvmath] +% \definetypeface [hvmath] [ss] [sans] [heros] [default] [rscale=0.9] +% \definetypeface [hvmath] [rm] [serif] [termes] [default] +% \definetypeface [hvmath] [tt] [mono] [cursor] [default] [rscale=1.05] +% \definetypeface [hvmath] [mm] [math] [hvmath] [default] +% \stoptypescript + +% \stoptypescriptcollection \protect \endinput diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua index ee58cef68..a845599f5 100644 --- a/tex/context/base/typo-brk.lua +++ b/tex/context/base/typo-brk.lua @@ -33,8 +33,10 @@ local make_glyph_node = nodes.glyph local remove_node = nodes.remove -- ! nodes local tonodes = blobs.tonodes -local glyph = node.id("glyph") -local kern = node.id("kern") +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local kern = nodecodes.kern typesetting = typesetting or {} typesetting.breakpoints = typesetting.breakpoints or {} diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua index 0e9068af3..3de2c5ab1 100644 --- a/tex/context/base/typo-cap.lua +++ b/tex/context/base/typo-cap.lua @@ -21,8 +21,10 @@ local traverse_id = node.traverse_id local texattribute = tex.attribute -local glyph = node.id("glyph") -local kern = node.id("kern") +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local kern = nodecodes.kern local fontdata = fonts.ids local fontchar = fonts.chr diff --git a/tex/context/base/typo-dig.lua b/tex/context/base/typo-dig.lua index 9bc738ecf..687090074 100644 --- a/tex/context/base/typo-dig.lua +++ b/tex/context/base/typo-dig.lua @@ -27,8 +27,10 @@ local insert_after = node.insert_after local texattribute = tex.attribute -local glyph = node.id("glyph") -local kern = node.id("kern") +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local kern = nodecodes.kern local new_glue = nodes.glue diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua index b858dbc1a..27bd09e4d 100644 --- a/tex/context/base/typo-krn.lua +++ b/tex/context/base/typo-krn.lua @@ -23,14 +23,16 @@ local insert_node_after = node.insert_after local make_glue_spec = nodes.glue_spec local make_kern_node = nodes.kern -local texattribute = tex.attribute - -local glyph = node.id("glyph") -local kern = node.id("kern") -local disc = node.id('disc') -local glue = node.id('glue') -local hlist = node.id('hlist') -local vlist = node.id('vlist') +local texattribute = tex.attribute + +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local kern = nodecodes.kern +local disc = nodecodes.disc +local glue = nodecodes.glue +local hlist = nodecodes.hlist +local vlist = nodecodes.vlist local fontdata = fonts.identifiers local chardata = fonts.characters diff --git a/tex/context/base/typo-mir.lua b/tex/context/base/typo-mir.lua index 5ab85c7c2..f0ed7fdff 100644 --- a/tex/context/base/typo-mir.lua +++ b/tex/context/base/typo-mir.lua @@ -26,9 +26,11 @@ local insert_node_before = node.insert_before local insert_node_after = node.insert_after local remove_node = nodes.remove -local glyph = node.id("glyph") -local whatsit = node.id("whatsit") -local mthnode = node.id('math') +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph +local whatsit = nodecodes.whatsit +local mthnode = nodecodes.math local fontdata = fonts.ids local fontchar = fonts.chr @@ -412,12 +414,12 @@ end --~ return false --~ end -chars.handle_mirroring = nodes.install_attribute_handler { +mirroring.handler = nodes.install_attribute_handler { name = "mirroring", namespace = mirroring, processor = mirroring.process, } function mirroring.enable() - tasks.enableaction("processors","chars.handle_mirroring") + tasks.enableaction("processors","mirroring.handler") end diff --git a/tex/context/base/typo-rep.lua b/tex/context/base/typo-rep.lua index 56681974e..ac93cde6f 100644 --- a/tex/context/base/typo-rep.lua +++ b/tex/context/base/typo-rep.lua @@ -22,10 +22,13 @@ local has_attribute = node.has_attribute local chardata = characters.data local collected = false -local glyph = node.id("glyph") local attribute = attributes.private("stripping") local fontdata = fonts.ids +local nodecodes = nodes.nodecodes + +local glyph = nodecodes.glyph + -- other namespace nodes.stripping = nodes.stripping or { } local stripping = nodes.stripping diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua index bc964932a..b11d4e386 100644 --- a/tex/context/base/typo-spa.lua +++ b/tex/context/base/typo-spa.lua @@ -24,13 +24,15 @@ local insert_node_after = node.insert_after local remove_node = nodes.remove local make_penalty_node = nodes.penalty local make_glue_node = nodes.glue -local glyph = node.id("glyph") local fontdata = fonts.identifiers local quaddata = fonts.quads +local nodecodes = nodes.nodecodes local texattribute = tex.attribute +local glyph = nodecodes.glyph + typesetting = typesetting or { } typesetting.spacings = typesetting.spacings or { } diff --git a/tex/context/base/unic-003.mkii b/tex/context/base/unic-003.mkii index d37563d26..3f994a662 100644 --- a/tex/context/base/unic-003.mkii +++ b/tex/context/base/unic-003.mkii @@ -136,7 +136,7 @@ \strippedcsname \unknownchar \or \strippedcsname \unknownchar \or % kappa alt \strippedcsname \greekrhoalt \or - \strippedcsname \unknownchar \or + \strippedcsname \greeksigmalunate \or \strippedcsname \unknownchar \or \strippedcsname \unknownchar \or \strippedcsname \greekepsilonalt \else diff --git a/tex/context/base/xetx-utf.mkii b/tex/context/base/xetx-utf.mkii index 79bd00745..a337c9e76 100644 --- a/tex/context/base/xetx-utf.mkii +++ b/tex/context/base/xetx-utf.mkii @@ -1986,4 +1986,9 @@ \setXTXcharcodes "201C "201C "201C \setXTXcharcodes "201D "201D "201D +% patch needed for french + +% \setXTXcharcodes "0027 "0027 "0027 +\setXTXcharcodes "2019 "2019 "2019 + \endinput |