diff options
Diffstat (limited to 'tex')
34 files changed, 1084 insertions, 279 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 8c09daa83..adf3dc2b0 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.10.18 23:11} +\newcontextversion{2021.10.21 19:53} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 1d1d61d0b..9d6b960ad 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.10.18 23:11} +\edef\contextversion{2021.10.21 19:53} %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii index c1ce78f2d..25a2968fc 100644 --- a/tex/context/base/mkii/mult-it.mkii +++ b/tex/context/base/mkii/mult-it.mkii @@ -188,6 +188,7 @@ \setinterfacevariable{enumeration}{enumerazione} \setinterfacevariable{environment}{ambiente} \setinterfacevariable{even}{pari} +\setinterfacevariable{explicit}{explicit} \setinterfacevariable{export}{export} \setinterfacevariable{external}{esterno} \setinterfacevariable{extremestretch}{extremestretch} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 4fd44d874..1095d81f9 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.10.18 23:11} +\newcontextversion{2021.10.21 19:53} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 80678ac75..5bec8a08a 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -49,7 +49,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.10.18 23:11} +\edef\contextversion{2021.10.21 19:53} %D Kind of special: diff --git a/tex/context/base/mkiv/core-con.lua b/tex/context/base/mkiv/core-con.lua index ac185e80b..2d7423669 100644 --- a/tex/context/base/mkiv/core-con.lua +++ b/tex/context/base/mkiv/core-con.lua @@ -1991,7 +1991,7 @@ function converters.totime(s) end local n = tonumber(s) if n and n >= 0 then - return date("*t",n) + return osdate("*t",n) end end diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua index 0f667bcc2..1475fcf67 100644 --- a/tex/context/base/mkiv/font-oto.lua +++ b/tex/context/base/mkiv/font-oto.lua @@ -67,7 +67,7 @@ local function gref(descriptions,n) end local function cref(feature,sequence) - return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name) + return formatters["feature %a, type %a, (chain) lookup %a"](feature,sequence.type,sequence.name) end local function report_substitution(feature,sequence,descriptions,unicode,substitution) @@ -240,12 +240,11 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis local ligatures = { } local alternate = tonumber(value) or true and 1 local defaultalt = otf.defaultbasealternate - local trace_singles = trace_baseinit and trace_singles local trace_alternatives = trace_baseinit and trace_alternatives local trace_ligatures = trace_baseinit and trace_ligatures - -- A chain of changes is handled in font-con which is clesner because + -- A chain of changes is handled in font-con which is cleaner because -- we can have shared changes and such. if not changed then diff --git a/tex/context/base/mkiv/good-mth.lua b/tex/context/base/mkiv/good-mth.lua index efc7cb22a..751ab2438 100644 --- a/tex/context/base/mkiv/good-mth.lua +++ b/tex/context/base/mkiv/good-mth.lua @@ -135,7 +135,7 @@ local function finalize(tfmdata,feature,value) yoffset = nil end if xoffset or yoffset then - local commands = characters.commands + local commands = character.commands if commands then prependcommands(commands,yoffset,xoffset) else diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index e3626b417..ef9a33153 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -76,7 +76,7 @@ return { "loosenessfrozenparcode", "lastlinefrozenparcode", "linepenaltyfrozenparcode", "clubpenaltyfrozenparcode", "widowpenaltyfrozenparcode", "displaypenaltyfrozenparcode", "brokenpenaltyfrozenparcode", "demeritsfrozenparcode", "shapefrozenparcode", "linefrozenparcode", "hyphenationfrozenparcode", - "shapingpenaltiesfrozenparcode", "allfrozenparcode", + "shapingpenaltiesfrozenparcode", "orphanpenaltyfrozenparcode", "allfrozenparcode", -- "activemathcharcode", -- diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 92f85011a..01f14834b 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -472,6 +472,7 @@ return { "numericscale", "numexpression", "orelse", + "orphanpenalties", "orunless", "outputbox", "overloaded", diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 1fc58def7..f713ae6ba 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 7fb96ed2c..6d1a2b9e6 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkxl/attr-col.lmt b/tex/context/base/mkxl/attr-col.lmt index bda57595c..1ac1cf93b 100644 --- a/tex/context/base/mkxl/attr-col.lmt +++ b/tex/context/base/mkxl/attr-col.lmt @@ -47,6 +47,7 @@ local report_transparencies = logs.reporter("transparencies","support") -- nb. too many "0 g"s local states = attributes.states +local registrations = backends.registrations local nodeinjections = backends.nodeinjections local unsetvalue = attributes.unsetvalue @@ -520,13 +521,12 @@ local f_transparency = formatters["%s:%s"] registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered") registerstorage("attributes/transparencies/values", values, "attributes.transparencies.values") -local register_transparency = nodeinjections.registertransparency -local inject_transparency = nodeinjections.injecttransparency +local register_transparency = registrations.transparency +local inject_transparency = nodeinjections.transparency updaters.register("backends.injections.latebindings",function() - local nodeinjections = backends.nodeinjections - register_transparency = nodeinjections.registertransparency - inject_transparency = nodeinjections.injecttransparency + register_transparency = backends.registrations.transparency + inject_transparency = backends.nodeinjections.transparency end) function transparencies.register(name,a,t,force) -- name is irrelevant here (can even be nil) diff --git a/tex/context/base/mkxl/back-exp.lmt b/tex/context/base/mkxl/back-exp.lmt index de1a1830e..766f30169 100644 --- a/tex/context/base/mkxl/back-exp.lmt +++ b/tex/context/base/mkxl/back-exp.lmt @@ -74,8 +74,6 @@ local v_hidden = variables.hidden local implement = interfaces.implement -local included = backends.included - local tasks = nodes.tasks local fontchar = fonts.hashes.characters local fontquads = fonts.hashes.quads @@ -560,9 +558,7 @@ do setattribute(di,"language",languagenames[texgetcount("mainlanguagenumber")]) if not less_state then setattribute(di,"file",tex.jobname) - if included.date then - setattribute(di,"date",os.fulltime()) - end + setattribute(di,"date",os.fulltime()) setattribute(di,"context",environment.version) setattribute(di,"version",exportversion) setattribute(di,"xmlns:m",mathmlns) @@ -1946,7 +1942,7 @@ local xmlpreamble_yes = [[ return replacetemplate(nocomment and xmlpreamble_nop or xmlpreamble_yes, { standalone = standalone and "yes" or "no", filename = tex.jobname, - date = included.date and os.fulltime(), + date = os.fulltime(), contextversion = environment.version, exportversion = exportversion, }) diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index a2edf83a6..b29dfe679 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.10.18 23:11} +\newcontextversion{2021.10.21 19:53} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index c227468ae..d49b81f2b 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.10.18 23:11} +\immutable\edef\contextversion{2021.10.21 19:53} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt index fed58dacf..a917d9501 100644 --- a/tex/context/base/mkxl/driv-shp.lmt +++ b/tex/context/base/mkxl/driv-shp.lmt @@ -519,16 +519,17 @@ local flush_character do flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ? else -- kind of messy that we do orientation here and offsets elsewhere .. this might change - local orientation = data.orientation + local orientation = data.orientation -- 0 (none), 1, 2, 3 or 4 (none) + local x = data.xoffset + local y = data.yoffset + if x then + pos_h = pos_h + x * sx + end + if y then + pos_v = pos_v + y * sy + end if orientation and (orientation == 1 or orientation == 3) then - local x = data.xoffset - local y = data.yoffset - if x then - pos_h = pos_h + x - end - if y then - pos_v = pos_v + y - end + -- we can get weird charactersbox tracing here pushorientation(orientation,pos_h,pos_v) flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) poporientation(orientation,pos_h,pos_v) diff --git a/tex/context/base/mkxl/font-con.lmt b/tex/context/base/mkxl/font-con.lmt index f2b359e57..36e5efbb6 100644 --- a/tex/context/base/mkxl/font-con.lmt +++ b/tex/context/base/mkxl/font-con.lmt @@ -791,6 +791,14 @@ function constructors.scale(tfmdata,specification) if vc then chr.commands = scalecommands(vc,hdelta,vdelta) end + local vx = characters.xoffset + if vx then + chr.vx = vx*hdelta + end + local vy = characters.yoffset + if vy then + chr.vy = vy*hdelta + end targetcharacters[unicode] = chr end -- diff --git a/tex/context/base/mkxl/font-imp-math.lmt b/tex/context/base/mkxl/font-imp-math.lmt index c505d7ddf..bf3c8b56e 100644 --- a/tex/context/base/mkxl/font-imp-math.lmt +++ b/tex/context/base/mkxl/font-imp-math.lmt @@ -89,6 +89,7 @@ function fonts.helpers.mathscriptslots(tfmdata,textcode) if coverage then local okay = coverage[textcode] if okay then + -- can be single or table return okay end end @@ -120,15 +121,26 @@ local function manipulate(tfmdata,value) for textcode, v in next, coverage do local textdata = characters[textcode] if textdata then - local scriptcode = v[1] - local scriptscriptcode = v[2] - local scriptdata = characters[scriptcode] - local scriptscriptdata = characters[scriptscriptcode] - if scriptdata then - textdata.smaller = scriptcode + local scriptcode, scriptscriptcode + local sstykind = type(v) + if sstykind == "table" then + scriptcode = v[1] + scriptscriptcode = v[2] + elseif sstykind == "number" then + scriptcode = v + scriptscriptcode = v + else + -- weird end - if scriptscriptdata then - scriptdata.smaller = scriptscriptcode + if scriptcode then + local scriptdata = characters[scriptcode] + local scriptscriptdata = characters[scriptscriptcode] + if scriptdata and scriptdata ~= textdata then + textdata.smaller = scriptcode + if scriptscriptdata and scriptdata ~= scriptscriptdata then + scriptdata.smaller = scriptscriptcode + end + end end end end @@ -154,16 +166,25 @@ local function initialize(tfmdata,value) end end +-- local specification = { +-- name = "compactmath", +-- description = "use one math font", +-- manipulators = { +-- base = manipulate, +-- node = manipulate, +-- }, +-- initializers = { +-- base = initialize, +-- node = initialize, +-- } +-- } + local specification = { name = "compactmath", description = "use one math font", - manipulators = { - base = manipulate, - node = manipulate, - }, initializers = { - base = initialize, - node = initialize, + base = function(...) manipulate(...) initialize(...) end, + node = function(...) manipulate(...) initialize(...) end, } } diff --git a/tex/context/base/mkxl/good-mth.lmt b/tex/context/base/mkxl/good-mth.lmt index c78fdbf71..033b2cb88 100644 --- a/tex/context/base/mkxl/good-mth.lmt +++ b/tex/context/base/mkxl/good-mth.lmt @@ -57,13 +57,21 @@ local function withscriptcode(tfmdata,unicode,data,action) if slots then if p == "*" then action(u,data) - for i=1,#slots do - action(slots[i],data) + if type(slots) == "number" then + action(slots,data) + else + for i=1,#slots do + action(slots[i],data) + end end else p = tonumber(p) if p then - action(slots[p],data) + if type(slots) == "number" then + action(slots,data) + else + action(slots[p],data) + end end end end @@ -139,12 +147,11 @@ local function finalize(tfmdata,feature,value,...) yoffset = nil end if xoffset or yoffset then - local commands = characters.commands + local commands = character.commands if commands then prependcommands(commands,yoffset,xoffset) else --- character.commands = { { "offset", xoffset, yoffset, unicode } } --- print(unicode,character.width) +-- character.commands = { { "offset", xoffset or 0, yoffset or 0, unicode } } local slot = charcommand[unicode] if xoffset and yoffset then character.commands = { xoffset, yoffset, slot } diff --git a/tex/context/base/mkxl/lpdf-ini.lmt b/tex/context/base/mkxl/lpdf-ini.lmt index 7979b80f8..6bee9e17b 100644 --- a/tex/context/base/mkxl/lpdf-ini.lmt +++ b/tex/context/base/mkxl/lpdf-ini.lmt @@ -56,7 +56,8 @@ if not modules then modules = { } end modules ['lpdf-ini'] = { -- Comment: beware of "too many locals" problem here. local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset -local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch +local concat = table.concat +local char, byte, format, sub = string.char, string.byte, string.format, string.sub local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values local sind, cosd, max, min = math.sind, math.cosd, math.max, math.min local sort, sortedhash = table.sort, table.sortedhash @@ -1088,73 +1089,6 @@ function lpdf.rotationcm(a) return format("%.6F %.6F %.6F %.6F 0 0 cm",c,s,-s,c) end --- ! -> universaltime - -do - - -- It's a bit of a historical mess here. - - local osdate, ostime, ostimezone = os.date, os.time, os.timezone - - local metadata = nil - local timestamp = osdate("%Y-%m-%dT%X") .. ostimezone(true) - - function lpdf.getmetadata() - if not metadata then - local contextversion = environment.version - local luatexversion = format("%1.2f",LUATEXVERSION) - local luatexfunctionality = tostring(LUATEXFUNCTIONALITY) - metadata = { - producer = format("LuaMetaTeX-%s",luatexversion), - creator = format("LuaMetaTeX %s %s + ConTeXt LMTX %s",luatexversion,luatexfunctionality,contextversion), - luatexversion = luatexversion, - contextversion = contextversion, - luatexfunctionality = luatexfunctionality, - luaversion = tostring(LUAVERSION), - platform = os.platform, - time = timestamp, - } - end - return metadata - end - - function lpdf.settime(n) - if n then - n = converters.totime(n) - if n then - converters.settime(n) - timestamp = osdate("%Y-%m-%dT%X") .. ostimezone(true) -- probably not ok - end - end - if metadata then - metadata.time = timestamp - end - return timestamp - end - - lpdf.settime(tonumber(resolvers.variable("start_time")) or tonumber(resolvers.variable("SOURCE_DATE_EPOCH"))) -- bah - - function lpdf.pdftimestamp(str) - local t = type(str) - if t == "string" then - local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$") - return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm) - else - return osdate("D:%Y%m%d%H%M%S",t == "number" and str or ostime()) -- maybe "!D..." : universal time - end - end - - function lpdf.id(date) - local banner = environment.jobname or tex.jobname or "unknown" - if not date then - return banner - else - return format("%s | %s",banner,timestamp) - end - end - -end - -- return nil is nicer in test prints function lpdf.checkedkey(t,key,variant) diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt index fb7b8ac63..f6cf9f072 100644 --- a/tex/context/base/mkxl/lpdf-lmt.lmt +++ b/tex/context/base/mkxl/lpdf-lmt.lmt @@ -163,8 +163,8 @@ local function reset_variables(specification) f_x_scale = 1.0 f_y_scale = 1.0 cur_factor = 0 - cur_f = false - cur_e = false + cur_f = false -- todo: check for nil vs false + cur_e = false -- todo: check for nil vs false tj_delta = 0.0 cw = 0.0 usedfonts = setmetatableindex(usefont) @@ -624,7 +624,12 @@ do pdf_goto_textmode() setup_fontparameters(font,factor,f,e,sx,sy) set_font() - elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then + elseif cur_f ~= f then -- when ok move up + pdf_goto_textmode() + setup_fontparameters(font,factor,f,e,sx,sy) + set_font() +-- elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then + elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_e ~= e then setup_fontparameters(font,factor,f,e,sx,sy) need_tm = true end @@ -1913,7 +1918,6 @@ local catalog = "" local lastdeferred = false local majorversion = 1 local minorversion = 7 -local trailerid = true directives.register("backend.pdf.threshold",function(v) if v then @@ -2466,6 +2470,7 @@ local openfile, closefile do -- local banner <const> = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128) local banner <const> = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128) + -- local removefile = os.remove openfile = function(filename) @@ -2543,13 +2548,7 @@ local openfile, closefile do local noffree = 0 local catalog = lpdf.getcatalog() local info = lpdf.getinfo() - if trailerid == true then - trailerid = md5.HEX(osuuid()) - elseif trailerid and #trailerid > 32 then - trailerid = md5.HEX(trailerid) - else - trailerid = false - end + local trailerid = lpdf.gettrailerid() if objectstream then flushdeferred() flushcache() diff --git a/tex/context/base/mkxl/lpdf-mis.lmt b/tex/context/base/mkxl/lpdf-mis.lmt index 2b82f8adc..6d99b215d 100644 --- a/tex/context/base/mkxl/lpdf-mis.lmt +++ b/tex/context/base/mkxl/lpdf-mis.lmt @@ -48,13 +48,12 @@ local pdfaction = lpdf.action local pdfflushobject = lpdf.flushobject local pdfflushstreamobject = lpdf.flushstreamobject local pdfminorversion = lpdf.minorversion -local formattedtimestamp = lpdf.pdftimestamp + local adddocumentextgstate = lpdf.adddocumentextgstate local addtocatalog = lpdf.addtocatalog local addtoinfo = lpdf.addtoinfo local addtopageattributes = lpdf.addtopageattributes local addtonames = lpdf.addtonames -local pdfgetmetadata = lpdf.getmetadata local texset = tex.set @@ -189,63 +188,7 @@ lpdf.registerdocumentfinalizer(flushdocumentactions,"document actions") -- the code above will move to scrn-ini -local done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register - -local function setupidentity() - if not done then - local metadata = pdfgetmetadata() - local creator = metadata.creator - local version = metadata.contextversion - local time = metadata.time - local jobname = environment.jobname or tex.jobname or "unknown" - -- - local identity = interactions.general.getidentity() - -- - local title = identity.title - addtoinfo("Title", pdfunicode(title), title) - local subtitle = identity.subtitle - if subtitle ~= "" then - addtoinfo("Subject", pdfunicode(subtitle), subtitle) - end - local author = identity.author - if author ~= "" then - addtoinfo("Author", pdfunicode(author), author) -- '/Author' in /Info, 'Creator' in XMP - end - addtoinfo("Creator", pdfunicode(creator), creator) - addtoinfo("CreationDate", pdfstring(formattedtimestamp(time))) - local date = identity.date - local pdfdate = date and formattedtimestamp(date) - if pdfdate then - addtoinfo("ModDate", pdfstring(pdfdate), date) - else - -- users should enter the date in 2010-01-19T23:27:50+01:00 format - -- and if not provided that way we use the creation time instead - addtoinfo("ModDate", pdfstring(formattedtimestamp(time)),time) - end - local keywords = identity.keywords - if keywords ~= "" then - keywords = concat(settings_to_array(keywords), " ") - addtoinfo("Keywords", pdfunicode(keywords), keywords) - end - local id = lpdf.id() - addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x - -- - addtoinfo("ConTeXt.Version",version) - addtoinfo("ConTeXt.Time",os.date("%Y-%m-%d %H:%M")) - addtoinfo("ConTeXt.Jobname",jobname) - addtoinfo("ConTeXt.Url","www.pragma-ade.com") - addtoinfo("ConTeXt.Support","contextgarden.net") - addtoinfo("TeX.Support","tug.org") - -- - done = true - else - -- no need for a message - end -end - -lpdf.registerpagefinalizer(setupidentity,"identity") - --- or when we want to be able to set things after pag e1: +-- or when we want to be able to set things after page 1: -- -- lpdf.registerdocumentfinalizer(setupidentity,1,"identity") diff --git a/tex/context/base/mkxl/lpdf-xmp.lmt b/tex/context/base/mkxl/lpdf-xmp.lmt index a5be8bfe0..ce5d69a48 100644 --- a/tex/context/base/mkxl/lpdf-xmp.lmt +++ b/tex/context/base/mkxl/lpdf-xmp.lmt @@ -8,10 +8,13 @@ if not modules then modules = { } end modules ['lpdf-xmp'] = { } local tostring, type = tostring, type -local format, gsub = string.format, string.gsub +local format, gsub, match = string.format, string.gsub, string.match +local concat = table.concat +local settings_to_array = utilities.parsers.settings_to_array local utfchar = utf.char local xmlfillin = xml.fillin local md5HEX = md5.HEX +local osdate, ostime, ostimezone, osuuid = os.date, os.time, os.timezone, os.uuid local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end) local trace_info = false trackers.register("backend.info", function(v) trace_info = v end) @@ -26,8 +29,9 @@ local codeinjections = pdfbackend.codeinjections local lpdf = lpdf local pdfdictionary = lpdf.dictionary local pdfconstant = lpdf.constant +local pdfunicode = lpdf.unicode +local pdfstring = lpdf.string local pdfreference = lpdf.reference -local pdfgetmetadata = lpdf.getmetadata local pdfflushstreamobject = lpdf.flushstreamobject -- The XMP packet wrapper is kind of fixed, see page 10 of XMPSpecificationsPart1.pdf from @@ -40,7 +44,8 @@ local xpacket = format ( [[ <?xpacket end="w"?>]], utfchar(0xFEFF) ) -local mapping = { +local unknown = { false, false } +local mapping = table.setmetatableindex ( { -- user defined keys (pdfx:) ["ConTeXt.Jobname"] = { "context", "rdf:Description/pdfx:ConTeXt.Jobname" }, ["ConTeXt.Time"] = { "date", "rdf:Description/pdfx:ConTeXt.Time" }, @@ -89,72 +94,113 @@ local mapping = { ["AuthorsPosition"] = { "metadata", "rdf:Description/photoshop:AuthorsPosition" }, ["Copyright"] = { "metadata", "rdf:Description/photoshop:Copyright" }, ["CaptionWriter"] = { "metadata", "rdf:Description/photoshop:CaptionWriter" }, -} +}, function() return unknown end ) -local included = backends.included -local lpdfid = lpdf.id -function lpdf.id() -- overload of ini - return lpdfid(included.date) -end +local metadata = nil +local trailerid = true +local creationdate = false +local modificationdate = false -local trailerid = nil -local dates = nil +local function pdftimestamp(str) + local t = type(str) + if t == "string" then + local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$") + return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm) + else + return osdate("D:%Y%m%d%H%M%S",t == "number" and str or ostime()) -- maybe "!D..." : universal time + end +end -local function update() - if trailer_id then - local b = toboolean(trailer_id) or trailer_id == "" - if b then - trailer_id = "This file is processed by ConTeXt and LuaTeX." - else - trailer_id = tostring(trailer_id) - end - local h = md5HEX(trailer_id) - if b then - report_info("using frozen trailer id") - else - report_info("using hashed trailer id %a (%a)",trailer_id,h) - end - trailerid = format("[<%s> <%s>]",h,h) +local function pdfgetmetadata() + if not metadata then + local contextversion = environment.version + local luatexversion = format("%1.2f",LUATEXVERSION) + local luatexfunctionality = tostring(LUATEXFUNCTIONALITY) + local jobname = environment.jobname or tex.jobname or "unknown" + local documentid = trailerid and ("uuid:" .. osuuid()) or "no unique document id here" + local instanceid = trailerid and ("uuid:" .. osuuid()) or "no unique instance id here" + metadata = creationdate and { + producer = format("LuaMetaTeX-%s",luatexversion), + creator = format("LuaMetaTeX %s %s + ConTeXt LMTX %s",luatexversion,luatexfunctionality,contextversion), + luatexversion = luatexversion, + contextversion = contextversion, + luatexfunctionality = luatexfunctionality, + luaversion = tostring(LUAVERSION), + platform = os.platform, + creationdate = creationdate, + modificationdate = modificationdate, + id = format("%s | %s",jobname,creationdate), + documentid = documentid, + instanceid = instanceid, + jobname = jobname, + } or { + producer = "LuaMetaTeX", + creator = "LuaMetaTeX + ConTeXt LMTX", + id = jobname, + documentid = documentid, + instanceid = instanceid, + jobname = jobname, + } + -- inspect(metadata) end - -- - local t = type(dates) - if t == "number" or t == "string" then - local d = converters.totime(dates) - if d then - included.date = true - included.id = "fake" - report_info("forced date/time information %a will be used",lpdf.settime(d)) - trailerid = false - elseif t == "string" then - dates = toboolean(dates) - included.date = dates - if dates ~= false then - included.id = true - else - report_info("no date/time but fake id information will be added") - trailerid = true - included.id = "fake" + return metadata +end + +local function pdfsetmetadate(n,both) + if n then + n = converters.totime(n) + if n then + creationdate = osdate("%Y-%m-%dT%X",ostime(n)) .. ostimezone(true) + if both then + modificationdate = creationdate end end end + return creationdate end -lpdf.registerdocumentfinalizer(update,"trailer id and dates",1) +lpdf.pdftimestamp = pdftimestamp -directives.register("backend.trailerid", function(v) trailerid = v end) -directives.register("backend.date", function(v) dates = v end) +function lpdf.gettrailerid() + if trailerid == true then + return md5.HEX(osuuid()) + elseif type(trailerid) == "string" then + return md5.HEX(trailerid) + else + return false + end +end + +-- string: use that, true: uuid, false: nothing + +directives.register("backend.trailerid", function(v) + trailerid = type(v) and v or toboolean(v) +end) -local function permitdetail(what) - local m = mapping[what] - if m then - return included[m[1]] and m[2] +-- year-mm-dd : use that for creation and modification + +local function setdates(v) + local t = type(v) + if t == "number" or t == "string" then + local d = converters.totime(v) + if d then + report_info("forced date/time information %a will be used",pdfsetmetadate(d,true)) + return + end + end + if toboolean(v) then + creationdate = osdate("%Y-%m-%dT%X") .. ostimezone(true) + modificationdate = creationdate else - return included[what] and true or false + creationdate = false + modificationdate = false end end -lpdf.permitdetail = permitdetail +setdates(true) + +directives.register("backend.date", setdates) -- maybe some day we will load the xmp file at runtime @@ -195,7 +241,7 @@ local function valid_xmp() end function lpdf.addxmpinfo(tag,value,check) - local pattern = permitdetail(tag) + local pattern = mapping[tag][2] if type(pattern) == "string" then xmlfillin(xmp or valid_xmp(),pattern,value,check) end @@ -207,7 +253,7 @@ local pdfaddtoinfo = lpdf.addtoinfo local pdfaddxmpinfo = lpdf.addxmpinfo function lpdf.addtoinfo(tag,pdfvalue,strvalue) - local pattern = permitdetail(tag) + local pattern = mapping[tag][2] if pattern then pdfaddtoinfo(tag,pdfvalue) end @@ -234,24 +280,91 @@ end -- flushing -local add_xmp_blob = true directives.register("backend.xmp",function(v) add_xmp_blob = v end) +local add_xmp_blob = true +local indentity_done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register + +local function setupidentity() + if not done then + -- + local identity = interactions.general.getidentity() + local title = identity.title + local subtitle = identity.subtitle + local author = identity.author + local date = identity.date + local keywords = identity.keywords + -- + if date and date ~= "" then + pdfsetmetadate(date) + end + if keywords then + keywords = concat(settings_to_array(keywords), " ") + end + -- + local metadata = pdfgetmetadata() + local creator = metadata.creator + local contextversion = metadata.contextversion + local id = metadata.id + local jobname = metadata.jobname + local creator = metadata.creator + local creation = metadata.creationdate + local modification = metadata.modificationdate + -- + if creator then + pdfaddtoinfo("Creator",pdfunicode(creator),creator) + end + if creation then + pdfaddtoinfo("CreationDate",pdfstring(pdftimestamp(creation)),creation) + end + if modification then + pdfaddtoinfo("ModDate",pdfstring(pdftimestamp(modification)),modification) + end + if id then + pdfaddtoinfo("ID",pdfstring(id),id) -- needed for pdf/x + end + -- + if title ~= "" then + pdfaddtoinfo("Title",pdfunicode(title),title) + end + if subtitle ~= "" then + pdfaddtoinfo("Subject",pdfunicode(subtitle),subtitle) + end + if author ~= "" then + pdfaddtoinfo("Author",pdfunicode(author),author) -- '/Author' in /Info, 'Creator' in XMP + end + if keywords and keywords ~= "" then + pdfaddtoinfo("Keywords",pdfunicode(keywords),keywords) + end + -- + if contextversion then + pdfaddtoinfo("ConTeXt.Version",contextversion) + end + if creation then + pdfaddtoinfo("ConTeXt.Time",creation) + end + if jobname then + pdfaddtoinfo("ConTeXt.Jobname",jobname) + end + -- + pdfaddtoinfo("ConTeXt.Url","www.pragma-ade.com") + pdfaddtoinfo("ConTeXt.Support","contextgarden.net") + pdfaddtoinfo("TeX.Support","tug.org") + -- + done = true + else + -- no need for a message + end +end local function flushxmpinfo() commands.pushrandomseed() - commands.setrandomseed(os.time()) - - local documentid = "no unique document id here" - local instanceid = "no unique instance id here" + commands.setrandomseed(ostime()) - local metadata = pdfgetmetadata() - local time = metadata.time - local producer = metadata.producer - local creator = metadata.creator - - if included.id ~= "fake" then - documentid = "uuid:" .. os.uuid() - instanceid = "uuid:" .. os.uuid() - end + local metadata = pdfgetmetadata() + local time = metadata.time + local producer = metadata.producer + local creator = metadata.creator + local documentid = metadata.documentid + local instanceid = metadata.instanceid pdfaddtoinfo("Producer",producer) pdfaddtoinfo("Creator",creator) @@ -293,15 +406,14 @@ local function flushxmpinfo() end local r = pdfflushstreamobject(blob,md,false) -- uncompressed lpdf.addtocatalog("Metadata",pdfreference(r)) + end commands.poprandomseed() -- hack end --- this will be enabled when we can inhibit compression for a stream at the lua end - +lpdf.registerpagefinalizer(setupidentity,"identity") lpdf.registerdocumentfinalizer(flushxmpinfo,1,"metadata") -directives.register("backend.verbosexmp", function(v) - verbose = v -end) +directives.register("backend.xmp", function(v) add_xmp_blob = v end) +directives.register("backend.verbosexmp", function(v) verbose = v end) diff --git a/tex/context/base/mkxl/math-fbk.lmt b/tex/context/base/mkxl/math-fbk.lmt new file mode 100644 index 000000000..4c58a2bb6 --- /dev/null +++ b/tex/context/base/mkxl/math-fbk.lmt @@ -0,0 +1,722 @@ +if not modules then modules = { } end modules ['math-fbk'] = { + version = 1.001, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This will partly be redone and go via definitions in goodies where we can share +-- some across fonts. + +local next, type = next, type + +local trace_fallbacks = false trackers.register("math.fallbacks", function(v) trace_fallbacks = v end) + +local report_fallbacks = logs.reporter("math","fallbacks") + +local formatters = string.formatters +local fastcopy = table.fastcopy +local byte = string.byte +local sortedhash = table.sortedhash +local setmetatableindex = table.setmetatableindex + +local fallbacks = { } +mathematics.fallbacks = fallbacks + +local helpers = fonts.helpers +local prependcommands = helpers.prependcommands +local charcommand = helpers.commands.char +local leftcommand = helpers.commands.left +local rightcommand = helpers.commands.right +local upcommand = helpers.commands.up +local downcommand = helpers.commands.down +local dummycommand = helpers.commands.dummy +local popcommand = helpers.commands.pop +local pushcommand = helpers.commands.push + +local virtualcharacters = { } +local virtualforced = { } + +local hashes = fonts.hashes +local identifiers = hashes.identifiers +local lastmathids = hashes.lastmathids + +-- we need a trick (todo): if we define scriptscript, script and text in +-- that order we could use their id's .. i.e. we could always add a font +-- table with those id's .. in fact, we could also add a whole lot more +-- as it doesn't hurt + +function fallbacks.apply(target,original) + local mathparameters = target.mathparameters + if not mathparameters or not next(mathparameters) then + return + end + -- we also have forcedsize ... at this moment we already passed through + -- constructors.scale so we have this set + local parameters = target.parameters + local properties = target.properties + local mathsize = parameters.mathsize + if mathsize < 1 or mathsize > 3 then + return + end + local characters = target.characters + local size = parameters.size + local usedfonts = target.fonts + local compactmath = properties.compactmath + if not usedfonts then + usedfonts = { { id = 0 } } -- we need at least one entry (automatically done anyway) + target.fonts = usedfonts + end + -- not used + local textid, scriptid, scriptscriptid + local textindex, scriptindex, scriptscriptindex + local textdata, scriptdata, scriptscriptdata + if mathsize == 3 then + -- scriptscriptsize + textid = 0 + scriptid = 0 + scriptscriptid = 0 + elseif mathsize == 2 then + -- scriptsize + textid = 0 + scriptid = lastmathids[3] or 0 + scriptscriptid = lastmathids[3] or 0 + else + -- textsize + textid = 0 + scriptid = lastmathids[2] or 0 + scriptscriptid = lastmathids[3] or 0 + end + if textid and textid ~= 0 then + textindex = #usedfonts + 1 + textdata = target + usedfonts[textindex] = { id = textid } + else + textdata = target + end + if compactmath then + scriptid = textid + scriptscriptid = textid + end + if scriptid and scriptid ~= 0 then + scriptindex = #usedfonts + 1 + scriptdata = identifiers[scriptid] + usedfonts[scriptindex] = { id = scriptid } + else + scriptindex = textindex + scriptdata = textdata + end + if scriptscriptid and scriptscriptid ~= 0 then + scriptscriptindex = #usedfonts + 1 + scriptscriptdata = identifiers[scriptscriptid] + usedfonts[scriptscriptindex] = { id = scriptscriptid } + else + scriptscriptindex = scriptindex + scriptscriptdata = scriptdata + end + -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid) + local data = { + textdata = textdata, + scriptdata = scriptdata, + scriptscriptdata = scriptscriptdata, + textindex = textindex, + scriptindex = scriptindex, + scriptscriptindex = scriptscriptindex, + textid = textid, + scriptid = scriptid, + scriptscriptid = scriptscriptid, + characters = characters, + unicode = k, + target = target, + original = original, + size = size, + mathsize = mathsize, + } + target.mathrelation = data + -- + local fullname = trace_fallbacks and target.properties.fullname + -- + for k, v in sortedhash(virtualcharacters) do + if not characters[k] or virtualforced[k] then + local tv = type(v) + local cd = nil + if tv == "table" then + cd = v + elseif tv == "number" then + cd = characters[v] + elseif tv == "function" then + cd = v(data) -- ,k + end + if cd then + characters[k] = cd + else + -- something else + end + if trace_fallbacks and characters[k] then + report_fallbacks("extending math font %a with %U",fullname,k) + end + end + end + data.unicode = nil +end + +utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply") + +function fallbacks.install(unicode,value) + virtualcharacters[unicode] = value +end + +-- a few examples: + +local function reference(index,char) + if index then + return { "slot", index, char } + else + return charcommand[char] + end +end + +local function raised(data,replacement,down) + local character = data.scriptdata.characters[replacement] + if character then + local size = data.size + return { + width = character.width, + height = character.height, + depth = character.depth, + commands = { + down and downcommand[size/4] or upcommand[size/2], + reference(data.scriptindex,replacement) + } + } + end +end + +-- virtualcharacters[0x207A] = 0x2212 +-- virtualcharacters[0x207B] = 0x002B +-- virtualcharacters[0x208A] = 0x2212 +-- virtualcharacters[0x208B] = 0x002B + +virtualcharacters[0x207A] = function(data) return raised(data,0x002B) end +virtualcharacters[0x207B] = function(data) return raised(data,0x2212) end +virtualcharacters[0x208A] = function(data) return raised(data,0x002B,true) end +virtualcharacters[0x208B] = function(data) return raised(data,0x2212,true) end + +-- local function repeated(data,char,n,fraction) +-- local character = data.characters[char] +-- if character then +-- local width = character.width +-- local delta = width - character.italic -- width * fraction +-- local c = charcommand[char] +-- local r = rightcommand[right] +-- local commands = { } +-- for i=1,n-1 do +-- width = width + delta +-- commands[#commands+1] = c +-- commands[#commands+1] = -delta +-- end +-- commands[#commands+1] = c +-- return { +-- width = width, +-- height = character.height, +-- depth = character.depth, +-- commands = commands, +-- } +-- end +-- end + +-- virtualcharacters[0x222C] = function(data) +-- return repeated(data,0x222B,2,1/8) +-- end + +-- virtualcharacters[0x222D] = function(data) +-- return repeated(data,0x222B,3,1/8) +-- end + +local addextra = mathematics.extras.add + +addextra(0xFE350) -- MATHEMATICAL DOUBLE ARROW LEFT END +addextra(0xFE351) -- MATHEMATICAL DOUBLE ARROW MIDDLE PART +addextra(0xFE352) -- MATHEMATICAL DOUBLE ARROW RIGHT END + +local leftarrow = charcommand[0x2190] +local relbar = charcommand[0x2212] +local rightarrow = charcommand[0x2192] + +virtualcharacters[0xFE350] = function(data) + -- return combined(data,0x2190,0x2212) -- leftarrow relbar + local charone = data.characters[0x2190] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + pushcommand, + downcommand[size/2], + leftarrow, + popcommand, + upcommand[size/2], + relbar, + } + } + end +end + +virtualcharacters[0xFE351] = function(data) + -- return combined(data,0x2212,0x2212) -- relbar, relbar (isn't that just equal) + local char = data.characters[0x2212] + if char then + local size = data.size/2 + return { + width = char.width, + height = size, + depth = size, + commands = { + pushcommand, + downcommand[size/2], + relbar, + popcommand, + upcommand[size/2], + relbar, + } + } + end +end + +virtualcharacters[0xFE352] = function(data) + -- return combined(data,0x2192,0x2212) -- rightarrow relbar + local charone = data.characters[0x2192] + local chartwo = data.characters[0x2212] + if charone and chartwo then + local size = data.size/2 + return { + width = chartwo.width, + height = size, + depth = size, + commands = { + pushcommand, + downcommand[size/2], + relbar, + popcommand, + rightcommand[chartwo.width - charone.width], + upcommand[size/2], + rightarrow, + } + } + end +end + +-- we could move the defs from math-act here + +local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap,offset,unicode) + local characters = target.characters + local olddata = characters[oldchr] + -- brrr ... pagella has only next + if olddata and not olddata.commands then -- not: and olddata.width > 0 + local addprivate = fonts.helpers.addprivate + if swap then + swap = characters[swap] + height = swap.depth or 0 + depth = 0 + else + height = height or 0 + depth = depth or 0 + end + local oldheight = olddata.height or 0 + local correction = swap and + downcommand[oldheight - height] + or downcommand[oldheight + (offset or 0)] + local newdata = { + commands = { correction, charcommand[oldchr] }, + width = olddata.width, + height = height, + depth = depth, + unicode = unicode, + } + local glyphdata = newdata + local nextglyph = olddata.next + while nextglyph do + local oldnextdata = characters[nextglyph] + if oldnextdata then + local newnextdata = { + commands = { correction, charcommand[nextglyph] }, + width = oldnextdata.width, + height = height, + depth = depth, + } + local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata) + newdata.next = newnextglyph + local nextnextglyph = oldnextdata.next + if nextnextglyph == nextglyph then + break + else + olddata = oldnextdata + newdata = newnextdata + nextglyph = nextnextglyph + end + else + report_fallbacks("error in fallback: no valid next, slot %X",nextglyph) + break + end + end + local hv = olddata.horiz_variants + if hv then + hv = fastcopy(hv) + newdata.horiz_variants = hv + for i=1,#hv do + local hvi = hv[i] + local oldglyph = hvi.glyph + local olddata = characters[oldglyph] + if olddata then + local newdata = { + commands = { correction, charcommand[oldglyph] }, + width = olddata.width, + height = height, + depth = depth, + } + hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata) + else + report_fallbacks("error in fallback: no valid horiz_variants, slot %X, index %i",oldglyph,i) + end + end + end + return glyphdata, true + else + return olddata, false + end +end + +virtualcharacters[0x203E] = function(data) + local target = data.target + local height = 0 + local depth = 0 + -- local mathparameters = target.mathparameters + -- if mathparameters then + -- height = mathparameters.OverbarVerticalGap + -- depth = mathparameters.UnderbarVerticalGap + -- else + height = target.parameters.xheight/4 + depth = height + -- end + return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E) +end + +-- virtualcharacters[0xFE33E] = virtualcharacters[0x203E] -- convenient +-- virtualcharacters[0xFE33F] = virtualcharacters[0x203E] -- convenient + +virtualcharacters[0xFE33E] = function(data) + local target = data.target + local height = 0 + local depth = target.parameters.xheight/4 + return accent_to_extensible(target,0xFE33E,data.original,0x0305,height,depth,nil,nil,0x203E) +end + +virtualcharacters[0xFE33F] = function(data) + local target = data.target + local height = target.parameters.xheight/8 + local depth = height + return accent_to_extensible(target,0xFE33F,data.original,0x0305,height,depth,nil,nil,0x203E) +end + +-- spacing (no need for a cache of widths) + +local c_zero = byte('0') +local c_period = byte('.') + +local function spacefraction(data,fraction) + local width = fraction * data.target.parameters.space + return { + width = width, + commands = { rightcommand[width] } + } +end + +local function charfraction(data,char) + local width = data.target.characters[char].width + return { + width = width, + commands = { rightcommand[width] } + } +end + +local function quadfraction(data,fraction) + local width = fraction * data.target.parameters.quad + return { + width = width, + commands = { rightcommand[width] } + } +end + +virtualcharacters[0x00A0] = function(data) return spacefraction(data,1) end -- nbsp +virtualcharacters[0x2000] = function(data) return quadfraction (data,1/2) end -- enquad +virtualcharacters[0x2001] = function(data) return quadfraction (data,1) end -- emquad +virtualcharacters[0x2002] = function(data) return quadfraction (data,1/2) end -- enspace +virtualcharacters[0x2003] = function(data) return quadfraction (data,1) end -- emspace +virtualcharacters[0x2004] = function(data) return quadfraction (data,1/3) end -- threeperemspace +virtualcharacters[0x2005] = function(data) return quadfraction (data,1/4) end -- fourperemspace +virtualcharacters[0x2006] = function(data) return quadfraction (data,1/6) end -- sixperemspace +virtualcharacters[0x2007] = function(data) return charfraction (data,c_zero) end -- figurespace +virtualcharacters[0x2008] = function(data) return charfraction (data,c_period) end -- punctuationspace +virtualcharacters[0x2009] = function(data) return quadfraction (data,1/8) end -- breakablethinspace +virtualcharacters[0x200A] = function(data) return quadfraction (data,1/8) end -- hairspace +virtualcharacters[0x200B] = function(data) return quadfraction (data,0) end -- zerowidthspace +virtualcharacters[0x202F] = function(data) return quadfraction (data,1/8) end -- narrownobreakspace +virtualcharacters[0x205F] = function(data) return spacefraction(data,1/2) end -- math thinspace + +-- + +local function smashed(data,unicode,swap,private) + local target = data.target + local original = data.original + local chardata = target.characters[unicode] + if chardata and chardata.height > target.parameters.xheight then + return accent_to_extensible(target,private,original,unicode,0,0,swap,nil,unicode) + else + return original.characters[unicode] + end +end + +addextra(0xFE3DE) -- EXTENSIBLE OF 0x03DE +addextra(0xFE3DC) -- EXTENSIBLE OF 0x03DC +addextra(0xFE3B4) -- EXTENSIBLE OF 0x03B4 + +virtualcharacters[0xFE3DE] = function(data) return smashed(data,0x23DE,0x23DF,0xFE3DE) end +virtualcharacters[0xFE3DC] = function(data) return smashed(data,0x23DC,0x23DD,0xFE3DC) end +virtualcharacters[0xFE3B4] = function(data) return smashed(data,0x23B4,0x23B5,0xFE3B4) end + +addextra(0xFE3DF) -- EXTENSIBLE OF 0x03DF +addextra(0xFE3DD) -- EXTENSIBLE OF 0x03DD +addextra(0xFE3B5) -- EXTENSIBLE OF 0x03B5 + +virtualcharacters[0xFE3DF] = function(data) local c = data.target.characters[0x23DF] if c then c.unicode = 0x23DF return c end end +virtualcharacters[0xFE3DD] = function(data) local c = data.target.characters[0x23DD] if c then c.unicode = 0x23DD return c end end +virtualcharacters[0xFE3B5] = function(data) local c = data.target.characters[0x23B5] if c then c.unicode = 0x23B5 return c end end + +-- todo: add some more .. numbers might change + +addextra(0xFE302) -- EXTENSIBLE OF 0x0302 +addextra(0xFE303) -- EXTENSIBLE OF 0x0303 + +local function smashed(data,unicode,private) + local target = data.target + local height = target.parameters.xheight / 2 + local c, done = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height,unicode) + if done then + c.top_accent = nil -- or maybe also all the others + end + return c +end + +virtualcharacters[0xFE302] = function(data) return smashed(data,0x0302,0xFE302) end +virtualcharacters[0xFE303] = function(data) return smashed(data,0x0303,0xFE303) end + +-- another crazy hack .. doesn't work as we define scrscr first .. we now have smaller +-- primes so we have smaller primes for the moment, big ones will become an option .. +-- these primes in fonts are a real mess .. kind of a dead end, so don't wonder about +-- the values below + +local function smashed(data,unicode,optional) + local oldchar = data.characters[unicode] + if oldchar then + local height = 0.85 * data.target.mathparameters.AccentBaseHeight + local newchar = table.copy(oldchar) + newchar.yoffset = height - oldchar.height + newchar.height = height + return newchar + elseif not optional then + report_fallbacks("missing %U prime in font %a",unicode,data.target.properties.fullname) + end +end + +addextra(0xFE932) -- SMASHED PRIME 0x02032 +addextra(0xFE933) -- SMASHED PRIME 0x02033 +addextra(0xFE934) -- SMASHED PRIME 0x02034 +addextra(0xFE957) -- SMASHED PRIME 0x02057 + +addextra(0xFE935) -- SMASHED BACKWARD PRIME 0x02035 +addextra(0xFE936) -- SMASHED BACKWARD PRIME 0x02036 +addextra(0xFE937) -- SMASHED BACKWARD PRIME 0x02037 + +virtualcharacters[0xFE932] = function(data) return smashed(data,0x02032) end +virtualcharacters[0xFE933] = function(data) return smashed(data,0x02033) end +virtualcharacters[0xFE934] = function(data) return smashed(data,0x02034) end +virtualcharacters[0xFE957] = function(data) return smashed(data,0x02057) end + +virtualcharacters[0xFE935] = function(data) return smashed(data,0x02035,true) end +virtualcharacters[0xFE936] = function(data) return smashed(data,0x02036,true) end +virtualcharacters[0xFE937] = function(data) return smashed(data,0x02037,true) end + +local hack = nil + +function mathematics.getridofprime(target,original) +-- local mathsize = specification.mathsize +-- if mathsize == 1 or mathsize == 2 or mathsize == 3) then + local mathparameters = original.mathparameters + if mathparameters and next(mathparameters) then + local changed = original.changed + if changed then + hack = changed[0x02032] + changed[0x02032] = nil + changed[0x02033] = nil + changed[0x02034] = nil + changed[0x02057] = nil + changed[0x02035] = nil + changed[0x02036] = nil + changed[0x02037] = nil + end + end +end + +function mathematics.setridofprime(target,original) + local mathparameters = original.mathparameters + if mathparameters and next(mathparameters) and original.changed then + target.characters[0xFE931] = target.characters[hack or 0x2032] + hack = nil + end +end + +utilities.sequencers.appendaction("beforecopyingcharacters","system","mathematics.getridofprime") +utilities.sequencers.appendaction("aftercopyingcharacters", "system","mathematics.setridofprime") + +-- actuarian (beware: xits has an ugly one) + +addextra(0xFE940) -- SMALL ANNUITY SYMBOL + +local function actuarian(data) + local characters = data.target.characters + local parameters = data.target.parameters + local basechar = characters[0x0078] -- x (0x0058 X) or 0x1D431 + local linewidth = parameters.xheight / 10 + local basewidth = basechar.width + local baseheight = basechar.height + return { + -- todo: add alttext + -- compromise: lm has large hooks e.g. \actuarial{a} + width = basewidth + 4 * linewidth, + height = basechar.height, + depth = basechar.depth, + unicode = 0x20E7, + commands = { + rightcommand[2 * linewidth], + downcommand[- baseheight - 3 * linewidth], + { "rule", linewidth, basewidth + 4 * linewidth }, + leftcommand[linewidth], + downcommand[baseheight + 4 * linewidth], + { "rule", baseheight + 5 * linewidth, linewidth }, + }, + } +end + +virtualcharacters[0x020E7] = actuarian -- checked +virtualcharacters[0xFE940] = actuarian -- unchecked + +local function equals(data,unicode,snippet,advance,n) -- mathpair needs them + local characters = data.target.characters + local parameters = data.target.parameters + local basechar = characters[snippet] + local advance = advance * parameters.quad + return { + unicode = unicode, + width = n*basechar.width - (n-1)*advance, + height = basechar.height, + depth = basechar.depth, + commands = { + charcommand[snippet], + leftcommand[advance], + charcommand[snippet], + n > 2 and leftcommand[advance] or nil, + n > 2 and charcommand[snippet] or nil, + }, + } +end + +virtualcharacters[0x2A75] = function(data) return equals(data,0x2A75,0x003D, 1/5,2) end -- == +virtualcharacters[0x2A76] = function(data) return equals(data,0x2A76,0x003D, 1/5,3) end -- === +virtualcharacters[0x2980] = function(data) return equals(data,0x2980,0x007C,-1/8,3) end -- ||| + +-- addextra(0xFE941) -- EXTREMELY IDENTICAL TO +-- +-- virtualcharacters[0xFE941] = function(data) -- this character is only needed for mathpairs +-- local characters = data.target.characters +-- local parameters = data.target.parameters +-- local basechar = characters[0x003D] +-- local width = basechar.width or 0 +-- local height = basechar.height or 0 +-- local depth = basechar.depth or 0 +-- return { +-- unicode = 0xFE941, +-- width = width, +-- height = height, -- we cheat (no time now) +-- depth = depth, -- we cheat (no time now) +-- commands = { +-- upcommand[height/2], -- sort of works +-- charcommand[0x003D], +-- leftcommand[width], +-- downcommand[height], -- sort of works +-- charcommand[0x003D], +-- }, +-- } +-- end + +-- lucida needs this + +virtualcharacters[0x305] = function(data) + local target = data.target + local height = target.parameters.xheight/8 + local width = target.parameters.emwidth/2 + local depth = height + local used = 0.8 * width + return { + width = width, + height = height, + depth = depth, + commands = { { "rule", height, width } }, + horiz_variants = { + { + advance = width, + ["end"] = used, + glyph = 0x305, + start = 0, + }, + { + advance = width, + ["end"] = 0, + extender = 1, + glyph = 0x305, + start = used, + }, + } + } +end + +local function threedots(data,shift) + local characters = data.target.characters + local parameters = data.target.parameters + local periodchar = characters[0x002E] + local pluschar = characters[0x002B] + local period = charcommand[0x002E] + local periodwd = periodchar.width or 0 + local periodht = periodchar.height or 0 + local perioddp = periodchar.depth or 0 + local offset = 0 + if shift then + local plusht = pluschar.height or 0 + local plusdp = pluschar.depth or 0 + local axis = (plusdp + plusht)//2 - plusdp + offset = axis - periodht//2 + periodht = axis + periodht//2 + end + return { + width = 3*periodwd, + height = periodht, + depth = 0, + commands = { upcommand[offset], period, period, period } + } +end + +virtualcharacters[0x2026] = function(data) return threedots(data,false) end virtualforced[0x2026] = true +virtualcharacters[0x22EF] = function(data) return threedots(data, true) end virtualforced[0x22EF] = true diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index a481af744..74e438fc3 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -74,7 +74,7 @@ \registerctxluafile{math-ren}{} \registerctxluafile{math-noa}{autosuffix} \registerctxluafile{math-tag}{autosuffix} -\registerctxluafile{math-fbk}{} +\registerctxluafile{math-fbk}{autosuffix} \registerctxluafile{math-dir}{} \registerctxluafile{math-spa}{} \registerctxluafile{math-fnt}{autosuffix} diff --git a/tex/context/base/mkxl/spac-par.mkxl b/tex/context/base/mkxl/spac-par.mkxl index 0299c5485..f094e2807 100644 --- a/tex/context/base/mkxl/spac-par.mkxl +++ b/tex/context/base/mkxl/spac-par.mkxl @@ -31,6 +31,7 @@ + \clubpenaltyfrozenparcode + \brokenpenaltyfrozenparcode + \demeritsfrozenparcode + + \orphanpenaltyfrozenparcode \relax \setnewconstant\paragraphpenaltycodes\numexpr @@ -39,6 +40,7 @@ + \clubpenaltyfrozenparcode + \brokenpenaltyfrozenparcode + \shapingpenaltiesfrozenparcode + + \orphanpenaltyfrozenparcode \relax \setnewconstant\paragraphdemeritcodes\numexpr @@ -82,6 +84,7 @@ % \linefrozenparcode % \baselineskip \lineskip \lineskiplimit + \hyphenationfrozenparcode % \hyphenationmode + \shapingpenaltiesfrozenparcode % \shapingpenaltiesmode + + \orphanpenaltyfrozenparcode \relax \permanent\protected\def\freezeparagraphproperties {\snapshotpar\frozenparagraphdefault} diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl index 957bcea22..e2fa75133 100644 --- a/tex/context/base/mkxl/spac-ver.mkxl +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -1408,6 +1408,7 @@ \resetpenalties\widowpenalties \resetpenalties\clubpenalties \resetpenalties\interlinepenalties + \resetpenalties\orphanpenalties \stopsetups %D We use \directsetup because it's faster and we know there is no csl: @@ -1446,12 +1447,13 @@ \directsetup{\systemsetupsprefix\s!reset} - \setpenalties \widowpenalties \plustwo \maxdimen - \setpenalties \clubpenalties \plustwo \maxdimen - \frozen \brokenpenalty \maxdimen - \frozen \doublehyphendemerits \defaultdoublehyphendemerits - \frozen \finalhyphendemerits \defaultfinalhyphendemerits - \frozen \adjdemerits \defaultadjdemerits + \setpenalties \widowpenalties \plustwo \maxdimen + \setpenalties \clubpenalties \plustwo \maxdimen + \setpenalties \orphanpenalties \zerocount + \frozen \brokenpenalty \maxdimen + \frozen \doublehyphendemerits \defaultdoublehyphendemerits + \frozen \finalhyphendemerits \defaultfinalhyphendemerits + \frozen \adjdemerits \defaultadjdemerits \stopsetups diff --git a/tex/context/fonts/mkiv/libertinus-math.lfg b/tex/context/fonts/mkiv/libertinus-math.lfg new file mode 100644 index 000000000..24f58eb48 --- /dev/null +++ b/tex/context/fonts/mkiv/libertinus-math.lfg @@ -0,0 +1,55 @@ +-- Well, here we have yet another math font that does things differently: a huge prime in the ssty1 +-- slot (not an alternate but a single) and a small one in the normal location. Actually, only primes +-- have an ssty feature. Now, because we have some magic with primes in ConTeXt we cannot use some +-- fix-feature or just disable ssty, but we have to revert to a runtime fix. Lucky me that I didn't +-- remove that hardly needed 'tweaks' mechanism yet. + +return { + name = "libertinus-math", + version = "1.00", + comment = "Goodies that complement libertinus.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + tweaks = { + aftercopying = { + function(target,original) + local okay = 983068 + local crap = { + ["minute"] = "minute.ssty1", + ["second"] = "second.ssty1", + -- [8242] = 983068, + -- [8243] = 983069, + [8244] = 983070, + [8245] = 983071, + [8246] = 983072, + [8247] = 983073, + } + local characters = target.characters + local descriptions = target.descriptions + local unicodes = original.resources.unicodes + if unicodes["minute.ssty1"] == okay then + for old, new in next, crap do + if type(old) == "string" then + old = unicodes[old] + end + if type(new) == "string" then + new = unicodes[new] + end + if old and new and characters[old] then + local c = characters[new] + if c then + characters[old] = c + c.commands = { { "up", .1 * c.height }, { "slot", 0, new, .7 } } + end + end + end + else + logs.report("fonts","the libertinus tweaks need to be checked") + end + end, + }, + }, + }, +} + diff --git a/tex/context/fonts/mkiv/pagella-math.lfg b/tex/context/fonts/mkiv/pagella-math.lfg index 3908112d0..262196f70 100644 --- a/tex/context/fonts/mkiv/pagella-math.lfg +++ b/tex/context/fonts/mkiv/pagella-math.lfg @@ -1,7 +1,7 @@ local kern_V = { bottomright = { { kern = -200 } } } local kern_W = { bottomright = { { kern = -100 } } } ----- kern_f = { bottomright = { { kern = -100 } } } -local offset_f = { xoffset = "llx" } +-- local offset_f = { xoffset = "llx" } -- Beware of updates in ssty slots! @@ -18,7 +18,7 @@ return { -- [0x1D453] = offset_f, -- 𝑓 -- ["1:0x1D453"] = offset_f, -- needed for compact -- ["2:0x1D453"] = offset_f, -- needed for compact - ["*:0x1D453"] = offset_f, -- 𝑓 +-- ["*:0x1D453"] = offset_f, -- 𝑓 }, }, kerns = { diff --git a/tex/context/fonts/mkiv/termes-math.lfg b/tex/context/fonts/mkiv/termes-math.lfg index 3cf8685eb..da5a13d77 100644 --- a/tex/context/fonts/mkiv/termes-math.lfg +++ b/tex/context/fonts/mkiv/termes-math.lfg @@ -1,6 +1,6 @@ local kern_V = { bottomright = { { kern = -200 } } } local kern_W = { bottomright = { { kern = -100 } } } -local offset_f = { xoffset = "llx" } +-- local offset_f = { xoffset = "llx" } -- Beware of updates in ssty slots! @@ -16,7 +16,7 @@ return { -- [0x1D453] = offset_f, -- 𝑓 -- ["1:0x1D453"] = offset_f, -- needed for compact -- ["2:0x1D453"] = offset_f, -- needed for compact - ["*:0x1D453"] = offset_f, -- 𝑓 +-- ["*:0x1D453"] = offset_f, -- 𝑓 }, }, kerns = { diff --git a/tex/context/fonts/mkiv/type-imp-libertinus.mkiv b/tex/context/fonts/mkiv/type-imp-libertinus.mkiv index 26d17bc03..00b2a6abd 100644 --- a/tex/context/fonts/mkiv/type-imp-libertinus.mkiv +++ b/tex/context/fonts/mkiv/type-imp-libertinus.mkiv @@ -72,8 +72,8 @@ \stoptypescript \starttypescript [\s!math] [libertinus] [\s!name] - \definefontsynonym[\s!MathRoman ] [\s!file:libertinusmath-regular.otf] [\s!features={\s!math\mathsizesuffix,mathextra}] - \definefontsynonym[\s!MathRomanBold] [\s!file:libertinusmath-regular.otf] [\s!features={\s!math\mathsizesuffix,mathextra}] + \definefontsynonym[\s!MathRoman ] [\s!file:libertinusmath-regular.otf] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=libertinus-math.lfg] + \definefontsynonym[\s!MathRomanBold] [\s!file:libertinusmath-regular.otf] [\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=libertinus-math.lfg] \stoptypescript \starttypescript [libertinus] diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml index a18c9212b..1cd5a3dcf 100644 --- a/tex/context/interface/mkii/keys-it.xml +++ b/tex/context/interface/mkii/keys-it.xml @@ -191,6 +191,7 @@ <cd:variable name='enumeration' value='enumerazione'/> <cd:variable name='environment' value='ambiente'/> <cd:variable name='even' value='pari'/> + <cd:variable name='explicit' value='explicit'/> <cd:variable name='export' value='export'/> <cd:variable name='external' value='esterno'/> <cd:variable name='extremestretch' value='extremestretch'/> diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index c531fcd64..7da49fc66 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-10-18 23:11 +-- merge date : 2021-10-21 19:53 do -- begin closure to overcome local limits and interference @@ -21941,7 +21941,7 @@ local function gref(descriptions,n) end end local function cref(feature,sequence) - return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name) + return formatters["feature %a, type %a, (chain) lookup %a"](feature,sequence.type,sequence.name) end local function report_substitution(feature,sequence,descriptions,unicode,substitution) if unicode==substitution then |