From db581096187dc2d3cbdbe4cdc39d247c168b1607 Mon Sep 17 00:00:00 2001 From: Context Git Mirror Bot Date: Thu, 19 May 2016 14:44:17 +0200 Subject: 2016-05-19 13:48:00 --- doc/context/documents/general/manuals/luatex.pdf | Bin 994871 -> 995319 bytes .../general/manuals/luatex/luatex-nodes.tex | 16 +- tex/context/base/context-version.pdf | Bin 4255 -> 4250 bytes tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/font-one.lua | 14 +- tex/context/base/mkiv/font-onr.lua | 38 +- tex/context/base/mkiv/font-ots.lua | 30 +- tex/context/base/mkiv/font-sel.lua | 1354 +++++++++++--------- tex/context/base/mkiv/font-sel.mkvi | 243 +--- tex/context/base/mkiv/node-ini.lua | 27 +- tex/context/base/mkiv/node-res.lua | 64 +- tex/context/base/mkiv/spac-prf.lua | 10 +- tex/context/base/mkiv/status-files.pdf | Bin 9209 -> 9253 bytes tex/context/base/mkiv/status-lua.pdf | Bin 266761 -> 268228 bytes tex/context/base/mkiv/typo-mar.lua | 212 ++- tex/context/interface/mkiv/i-context.pdf | Bin 820905 -> 820707 bytes tex/context/interface/mkiv/i-readme.pdf | Bin 60792 -> 60793 bytes tex/context/modules/mkiv/m-scite.mkiv | 11 +- tex/context/modules/mkiv/x-setups-basics.mkiv | 9 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 61 +- 21 files changed, 1126 insertions(+), 967 deletions(-) diff --git a/doc/context/documents/general/manuals/luatex.pdf b/doc/context/documents/general/manuals/luatex.pdf index 8b746b0f2..92424d805 100644 Binary files a/doc/context/documents/general/manuals/luatex.pdf and b/doc/context/documents/general/manuals/luatex.pdf differ diff --git a/doc/context/sources/general/manuals/luatex/luatex-nodes.tex b/doc/context/sources/general/manuals/luatex/luatex-nodes.tex index e90813c33..b7b81b5a6 100644 --- a/doc/context/sources/general/manuals/luatex/luatex-nodes.tex +++ b/doc/context/sources/general/manuals/luatex/luatex-nodes.tex @@ -646,14 +646,14 @@ The \type {type} can have one of six distinct values. The number is the \ASCII\ value if the first character if the type name (so you can use string.byte("l") instead of \type {108}). -\starttabulate[|lT|p|] -\NC \rmbf value \NC \bf meaning \NC \bf explanation \NC \NR -\NC 97 \NC a \NC list of attributes (a node list) \NC \NR -\NC 100 \NC d \NC a \LUA\ number \NC \NR -\NC 108 \NC l \NC a \LUA\ value (table, number, boolean, etc) \NC \NR -\NC 110 \NC n \NC a node list \NC \NR -\NC 115 \NC s \NC a \LUA\ string \NC \NR -\NC 116 \NC t \NC a \LUA\ token list in \LUA\ table form (a list of triplets) \NC \NR +\starttabulate[|lT|lT|p|] +\NC \rmbf value \NC \bf meaning \NC \bf explanation \NC \NR +\NC 97 \NC a \NC list of attributes (a node list) \NC \NR +\NC 100 \NC d \NC a \LUA\ number \NC \NR +\NC 108 \NC l \NC a \LUA\ value (table, number, boolean, etc) \NC \NR +\NC 110 \NC n \NC a node list \NC \NR +\NC 115 \NC s \NC a \LUA\ string \NC \NR +\NC 116 \NC t \NC a \LUA\ token list in \LUA\ table form (a list of triplets) \NC \NR \stoptabulate \subsubsubsection{save_pos whatsits} diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf index b40235cc8..ff75a0a20 100644 Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 13050577d..8e4d59750 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2016.05.17 19:20} +\newcontextversion{2016.05.19 13:43} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 032682a1d..e0bd762a9 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -39,7 +39,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2016.05.17 19:20} +\edef\contextversion{2016.05.19 13:43} \edef\contextkind {current} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-one.lua b/tex/context/base/mkiv/font-one.lua index 77f2560f6..a9f78f4fb 100644 --- a/tex/context/base/mkiv/font-one.lua +++ b/tex/context/base/mkiv/font-one.lua @@ -812,7 +812,8 @@ local function check_afm(specification,fullname) end function readers.afm(specification,method) - local fullname, tfmdata = specification.filename or "", nil + local fullname = specification.filename or "" + local tfmdata = nil if fullname == "" then local forced = specification.forced or "" if forced ~= "" then @@ -841,7 +842,16 @@ function readers.pfb(specification,method) -- only called when forced if trace_defining then report_afm("using afm reader for %a",original) end - specification.specification = file.replacesuffix(original,"afm") specification.forced = "afm" + local function swap(name) + local value = specification[swap] + if value then + specification[swap] = gsub("%.pfb",".afm",1) + end + end + swap("filename") + swap("fullname") + swap("forcedname") + swap("specification") return readers.afm(specification,method) end diff --git a/tex/context/base/mkiv/font-onr.lua b/tex/context/base/mkiv/font-onr.lua index 2699f25bb..a4969ad73 100644 --- a/tex/context/base/mkiv/font-onr.lua +++ b/tex/context/base/mkiv/font-onr.lua @@ -33,6 +33,7 @@ local trace_indexing = false trackers.register("afm.indexing", function(v local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end) local report_afm = logs.reporter("fonts","afm loading") +local report_afm = logs.reporter("fonts","pfb loading") fonts = fonts or { } local handlers = fonts.handlers or { } @@ -122,19 +123,19 @@ do local data = io.loaddata(resolvers.findfile(filename)) if not data then - print("no data",filename) + report_pfb("no data in %a",filename) return end - if not find(data,"!PS%-AdobeFont%-") then - print("no font",filename) + if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then + report_pfb("no font in %a",filename) return end local ascii, binary = match(data,"(.*)eexec%s+......(.*)") if not binary then - print("no binary",filename) + report_pfb("no binary data in %a",filename) return end @@ -148,7 +149,7 @@ do end if not vector then - print("no vector",filename) + report_pfb("no vector in %a",filename) return end @@ -184,16 +185,18 @@ and reader. We only need data that is relevant for our use. We don' more complex arrangements like multiple master (obsolete), direction specific kerning, etc.

--ldx]]-- -local spacing = patterns.whitespace -local lineend = patterns.newline -local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber -local name = spacing * C((1-spacing)^1) -local words = spacing * (1 - lineend)^1 / strip -local rest = (1 - lineend)^0 -local fontdata = Carg(1) -local semicolon = spacing * P(";") -local plus = P("plus") * number -local minus = P("minus") * number +local spacer = patterns.spacer +local whitespace = patterns.whitespace +local lineend = patterns.newline +local spacing = spacer^0 +local number = spacing * S("+-")^-1 * (R("09") + S("."))^1 / tonumber +local name = spacing * C((1 - whitespace)^1) +local words = spacing * ((1 - lineend)^1 / strip) +local rest = (1 - lineend)^0 +local fontdata = Carg(1) +local semicolon = spacing * P(";") +local plus = spacing * P("plus") * number +local minus = spacing * P("minus") * number -- kern pairs @@ -333,6 +336,10 @@ local fullparser = ( P("StartFontMetrics") * fontdata * name / start ) * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0 * ( P("EndFontMetrics") / stop ) +local fullparser = ( P("StartFontMetrics") * fontdata * name / start ) + * ( p_charmetrics + p_kernpairs + p_parameters + (1-P("EndFontMetrics")) )^0 + * ( P("EndFontMetrics") / stop ) + local infoparser = ( P("StartFontMetrics") * fontdata * name / start ) * ( p_parameters + (1-P("EndFontMetrics")) )^0 * ( P("EndFontMetrics") / stop ) @@ -402,4 +409,3 @@ function readers.getinfo(filename) return data.metadata end end - diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index c173de2be..1af7bacf3 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -3064,7 +3064,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm while start do local char = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if not a or (a == attr) then local lookupmatch = lookupcache[char] if lookupmatch then @@ -3097,7 +3097,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) while start ~= stop do local char = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if not a or (a == attr) then local lookupmatch = lookupcache[char] if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check @@ -3132,7 +3132,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) end -- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) --- local a = getattr(prev,0) +-- local a = attr and getattr(prev,0) -- if not a or (a == attr) then -- local char = ischar(prev) -- can be disc -- if char then @@ -3149,7 +3149,7 @@ end -- end local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local a = getattr(sub,0) + local a = attr and getattr(sub,0) if not a or (a == attr) then for n in traverse_nodes(sub) do -- only gpos if n == last then @@ -3181,7 +3181,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm while start do local char = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if not a or (a == attr) then for i=1,nofsteps do local step = steps[i] @@ -3228,7 +3228,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) while start ~= stop do local char = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if not a or (a == attr) then for i=1,nofsteps do local step = steps[i] @@ -3271,7 +3271,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) end -- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler) --- local a = getattr(prev,0) +-- local a = attr and getattr(prev,0) -- if not a or (a == attr) then -- local char = ischar(prev) -- can be disc -- if char then @@ -3297,7 +3297,7 @@ end -- end local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local a = getattr(sub,0) + local a = attr and getattr(sub,0) if not a or (a == attr) then for n in traverse_nodes(sub) do -- only gpos if n == last then @@ -3394,6 +3394,10 @@ local function featuresprocessor(head,font,attr) end + if attr == 0 then + attr = false -- some 10% faster when no dynamics but hardly measureable on real runs + end + head = tonut(head) if trace_steps then @@ -3405,7 +3409,7 @@ local function featuresprocessor(head,font,attr) local done = false local datasets = otf.dataset(tfmdata,font,attr) - local dirstack = { } -- could move outside function btu we can have local runss + local dirstack = { } -- could move outside function but we can have local runs sweephead = { } @@ -3451,7 +3455,7 @@ local function featuresprocessor(head,font,attr) while start do local char = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if not a or (a == attr) then for i=1,nofsteps do local step = steps[i] @@ -3489,14 +3493,12 @@ local function featuresprocessor(head,font,attr) local step = steps[1] local lookupcache = step.coverage if not lookupcache then - -- can't happen, no check in loop either report_missing_coverage(dataset,sequence) else - while start do local char, id = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if a then a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) else @@ -3553,7 +3555,7 @@ local function featuresprocessor(head,font,attr) while start do local char, id = ischar(start,font) if char then - local a = getattr(start,0) + local a = attr and getattr(start,0) if a then a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) else diff --git a/tex/context/base/mkiv/font-sel.lua b/tex/context/base/mkiv/font-sel.lua index c3431a213..4c80ff1fb 100644 --- a/tex/context/base/mkiv/font-sel.lua +++ b/tex/context/base/mkiv/font-sel.lua @@ -9,15 +9,16 @@ if not modules then modules = { } end modules ['font-sel'] = { local context = context local cleanname = fonts.names.cleanname local gsub, splitup, find = string.gsub, string.splitup, string.find +local concat, sortedkeys = table.concat, table.sortedkeys +local merge, remove = table.merge, table.remove local splitbase, removesuffix = file.splitbase, file.removesuffix local splitat, lpegmatch = lpeg.splitat, lpeg.match local formatters = string.formatters local settings_to_array = utilities.parsers.settings_to_array +local settings_to_hash = utilities.parsers.settings_to_hash local v_yes = interfaces.variables.yes -local v_simplefonts = interfaces.variables.simplefonts -local v_selectfont = interfaces.variables.selectfont local v_default = interfaces.variables.default local implement = interfaces.implement @@ -34,293 +35,67 @@ selectfont.fallbacks = fallbacks local methods = selectfont.methods or { } selectfont.methods = methods -local getlookups = fonts.names.getlookups -local registerdesignsizes = fonts.goodies.designsizes.register - -local alternatives = { - ["tf"] = "regular", - ["it"] = "italic", - ["sl"] = "slanted", - ["bf"] = "bold", - ["bi"] = "bolditalic", - ["bs"] = "boldslanted", - ["sc"] = "smallcaps", -} - -local styles = { - ["rm"] = "serif", - ["ss"] = "sans", - ["tt"] = "mono", - ["hw"] = "handwriting", - ["cg"] = "calligraphy", - ["mm"] = "math", -} - -local sizes = { - ["default"] = { - { 40, "4pt" }, - { 50, "5pt" }, - { 60, "6pt" }, - { 70, "7pt" }, - { 80, "8pt" }, - { 90, "9pt" }, - { 100, "10pt" }, - { 110, "11pt" }, - { 120, "12pt" }, - { 144, "14.4pt" }, - { 173, "17.3pt" }, - }, - ["dtp"] = { - { 50, "5pt" }, - { 60, "6pt" }, - { 70, "7pt" }, - { 80, "8pt" }, - { 90, "9pt" }, - { 100, "10pt" }, - { 110, "11pt" }, - { 120, "12pt" }, - { 130, "13pt" }, - { 140, "14pt" }, - { 160, "16pt" }, - { 180, "18pt" }, - { 220, "22pt" }, - { 280, "28pt" }, - } -} - -local synonyms = { - ["rm"] = { - ["tf"] = "Serif", - ["it"] = "SerifItalic", - ["sl"] = "SerifSlanted", - ["bf"] = "SerifBold", - ["bi"] = "SerifBoldItalic", - ["bs"] = "SerifBoldSlanted", - ["sc"] = "SerifCaps", - }, - ["ss"] = { - ["tf"] = "Sans", - ["it"] = "SansItalic", - ["sl"] = "SansSlanted", - ["bf"] = "SansBold", - ["bi"] = "SansBoldItalic", - ["bs"] = "SansBoldSlanted", - ["sc"] = "SansCaps", - }, - ["tt"] = { - ["tf"] = "Mono", - ["it"] = "MonoItalic", - ["sl"] = "MonoSlanted", - ["bf"] = "MonoBold", - ["bi"] = "MonoBoldItalic", - ["bs"] = "MonoBoldSlanted", - ["sc"] = "MonoCaps", - }, - ["hw"] = { - ["tf"] = "Handwriting", - }, - ["cg"] = { - ["tf"] = "Calligraphy", - }, - ["mm"] = { - ["tf"] = "MathRoman", - ["bf"] = "MathBold", - } -} +local extras = selectfont.extras or { } +selectfont.extras = extras -local replacement = { - ["style"] = { - ["it"] = "tf", - ["sl"] = "it", - ["bf"] = "tf", - ["bi"] = "bf", - ["bs"] = "bi", - ["sc"] = "tf", - }, - ["weight"] = { - ["it"] = "tf", - ["sl"] = "tf", - ["bf"] = "tf", - ["bi"] = "bf", - ["bs"] = "bf", - ["sc"] = "tf", - }, -} +local alternatives = selectfont.alternatives or { } +selectfont.alternatives = alternatives -local names = { - ["selectfont"] = { -- weight, style, width, variant, italic - ["regular"] = { weight = "normal", style = "normal", width = "normal", variant = "normal", italic = false }, - ["italic"] = { weight = "normal", style = "italic", width = "normal", variant = "normal", italic = true }, - ["slanted"] = { weight = "normal", style = "slanted", width = "normal", variant = "normal", italic = true }, - ["medium"] = { weight = "medium", style = "normal", width = "normal", variant = "normal", italic = false }, - ["mediumitalic"] = { weight = "medium", style = "italic", width = "normal", variant = "normal", italic = true }, - ["mediumcaps"] = { weight = "medium", style = "normal", width = "normal", variant = "smallcaps", italic = true }, - ["bold"] = { weight = "bold", style = "normal", width = "normal", variant = "normal", italic = false }, - ["bolditalic"] = { weight = "bold", style = "italic", width = "normal", variant = "normal", italic = true }, - ["boldslanted"] = { weight = "bold", style = "slanted", width = "normal", variant = "normal", italic = true }, - ["smallcaps"] = { weight = "normal", style = "normal", width = "normal", variant = "smallcaps", italic = false }, - }, - ["simplefonts"] = { - ["light"] = { "lightregular", "light" }, - ["lightitalic"] = { "lightitalic", "lightit", "lightoblique" }, - ["lightcaps"] = { "smallcapslight" }, - ["regular"] = { "roman", "regular", "book", "" }, - ["italic"] = { "italic", "it", "oblique", "kursiv", "bookitalic", "bookit" }, - ["medium"] = { "mediumregular", "medregular", "medium" }, - ["mediumitalic"] = { "mediumitalic", "meditalic" }, - ["mediumcaps"] = { "mediumcaps" }, - ["bold"] = { "bold", "bd", "kraeftig", "mediumregular", "semibold", "demi" }, - ["bolditalic"] = { "bolditalic", "boldit", "bdit", "boldoblique", "mediumitalic", "semibolditalic", "demiitalic" }, - ["smallcaps"] = { "smallcaps", "capitals", "sc" }, - ["heavy"] = { "heavyregular", "heavy" }, - ["heavyitalic"] = { "heavyitalic" }, - }, - ["default"] = { -- weight, width, italic - ["thin"] = { weight = { 100, 200, 300, 400, 500 }, width = 5, italic = false }, - ["thinitalic"] = { weight = { 100, 200, 300, 400, 500 }, width = 5, italic = true }, - ["extralight"] = { weight = { 200, 100, 300, 400, 500 }, width = 5, italic = false }, - ["extralightitalic"] = { weight = { 200, 100, 300, 400, 500 }, width = 5, italic = true }, - ["light"] = { weight = { 300, 200, 100, 400, 500 }, width = 5, italic = false }, - ["lightitalic"] = { weight = { 300, 200, 100, 400, 500 }, width = 5, italic = true }, - ["regular"] = { weight = { 400, 500, 300, 200, 100 }, width = 5, italic = false }, - ["italic"] = { weight = { 400, 500, 300, 200, 100 }, width = 5, italic = true }, - ["medium"] = { weight = { 500, 400, 300, 200, 100 }, width = 5, italic = false }, - ["mediumitalic"] = { weight = { 500, 400, 300, 200, 100 }, width = 5, italic = true }, - ["demibold"] = { weight = { 600, 700, 800, 900 }, width = 5, italic = false }, - ["demibolditalic"] = { weight = { 600, 700, 800, 900 }, width = 5, italic = true }, - ["bold"] = { weight = { 700, 600, 800, 900 }, width = 5, italic = false }, - ["bolditalic"] = { weight = { 700, 600, 800, 900 }, width = 5, italic = true }, - ["extrabold"] = { weight = { 800, 900, 700, 600 }, width = 5, italic = false }, - ["extrabolditalic"] = { weight = { 800, 900, 700, 600 }, width = 5, italic = true }, - ["heavy"] = { weight = { 900, 800, 700, 600 }, width = 5, italic = false }, - ["heavyitalic"] = { weight = { 900, 800, 700, 600 }, width = 5, italic = true }, - } -} +local presets = selectfont.presets or { } +selectfont.presets = presets --- simplefonts synonyms - -names.simplefonts.slanted = names.simplefonts.italic -names.simplefonts.boldslanted = names.simplefonts.bolditalic - --- default synonyms - -names.default.ultralight = names.default.extralight -names.default.semibold = names.default.demibold -names.default.ultrabold = names.default.extrabold -names.default.black = names.default.heavy - -names.default.ultralightitalic = names.default.extralightitalic -names.default.semibolditalic = names.default.demibolditalic -names.default.ultrabolditalic = names.default.extrabolditalic -names.default.blackitalic = names.default.heavyitalic - -names.default.thinslanted = names.default.thinitalic -names.default.extralightslanted = names.default.extralightitalic -names.default.ultralightslanted = names.default.extralightitalic -names.default.lightslanted = names.default.lightitalic -names.default.slanted = names.default.italic -names.default.demiboldslanted = names.default.demibolditalic -names.default.semiboldslanted = names.default.demibolditalic -names.default.boldslanted = names.default.bolditalic -names.default.extraboldslanted = names.default.extrabolditalic -names.default.ultraboldslanted = names.default.extrabolditalic -names.default.heavyslanted = names.default.heavyitalic -names.default.blackslanted = names.default.heavyitalic - -names.default.smallcaps = names.default.regular - -local mathsettings = { - ["asanamath"] = { - extras = "asana-math", - goodies = { - ["tf"] = "anana-math", - }, - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["cambriamath"] = { - extras = "cambria-math", - goodies = { - ["tf"] = "cambria-math", - }, - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["neoeuler"] = { - extras = "euler-math", - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["latinmodernmath"] = { - extras = "lm,lm-math", - goodies = { - ["tf"] = "lm", - }, - features = { - ["tf"] = "math\\mathsizesuffix,lm-math", - }, - }, - ["lucidabrightmathot"] = { - extras = "lucida-opentype-math", - goodies = { - ["tf"] = "lucida-opentype-math", - }, - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["texgyrepagellamath"] = { - extras = "texgyre", - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["texgyrebonummath"] = { - extras = "texgyre", - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["texgyretermesmath"] = { - extras = "texgyre", - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, - ["xitsmath"] = { - extras = "xits-math", - goodies = { - ["tf"] = "xits-math", - }, - features = { - ["tf"] = "math\\mathsizesuffix", - }, - }, -} +local defaults = selectfont.defaults or { } +selectfont.defaults = defaults -function selectfont.define(settings) - local index = #data + 1 - data[index] = settings - selectfont.searchfiles(index) - selectfont.filterinput(index) - return index -end - -local function savefont(data,alternative,entries) - local f = data.fonts - if not f then - f = { } - data.fonts = f - end - f[alternative] = entries -end - -local function savefeatures(data,alternative,entries) - local e = gsub(entries,"{(.*)}","%1") +local getlookups = fonts.names.getlookups +local registerdesignsizes = fonts.goodies.designsizes.register +local bodyfontsizes = storage.shared.bodyfontsizes + +local ctx_definefontsynonym = context.definefontsynonym +local ctx_resetfontfallback = context.resetfontfallback +local ctx_startfontclass = context.startfontclass +local ctx_stopfontclass = context.stopfontclass +local ctx_loadfontgoodies = context.loadfontgoodies +local ctx_definefontfallback = context.definefontfallback +local ctx_definetypeface = context.definetypeface +local ctx_definebodyfont = context.definebodyfont + +local trace_register = false trackers.register("selectfont.register", function(v) trace_register = v end) +local trace_files = false trackers.register("selectfont.files", function(v) trace_files = v end) +local trace_features = false trackers.register("selectfont.features", function(v) trace_features = v end) +local trace_goodies = false trackers.register("selectfont.goodies", function(v) trace_goodies = v end) +local trace_alternatives = false trackers.register("selectfont.alternatives", function(v) trace_alternatives = v end) +local trace_typescript = false trackers.register("selectfont.typescripts", function(v) trace_typescript = v end) + +local report_selectfont = logs.reporter("selectfont") +local report_files = logs.reporter("selectfont","files") +local report_features = logs.reporter("selectfont","features") +local report_goodies = logs.reporter("selectfont","goodies") +local report_alternatives = logs.reporter("selectfont","alternatives") +local report_typescript = logs.reporter("selectfont","typescripts") + +defaults["rm"] = { features = { ["sc"] = "*,f:smallcaps" } } +defaults["ss"] = { features = { ["sc"] = "*,f:smallcaps" } } + +defaults["asanamath"] = { options = { extras = "asana-math", features = "math\\mathsizesuffix", goodies = "anana-math" } } +defaults["cambriamath"] = { options = { extras = "cambria-math", features = "math\\mathsizesuffix", goodies = "cambria-math" } } +defaults["dejavumath"] = { options = { extras = "dejavu", features = "math\\mathsizesuffix" } } +defaults["neoeuler"] = { options = { extras = "euler-math", features = "math\\mathsizesuffix" } } +defaults["latinmodernmath"] = { options = { extras = "lm,lm-math", features = "math\\mathsizesuffix,lm-math", goodies = "lm" } } +defaults["lucidabrightmathot"] = { options = { extras = "lucida-opentype-math", features = "math\\mathsizesuffix", goodies = "lucida-opentype-math" } } +defaults["texgyrepagellamath"] = { options = { extras = "texgyre", features = "math\\mathsizesuffix" } } +defaults["texgyrebonummath"] = { options = { extras = "texgyre", features = "math\\mathsizesuffix" } } +defaults["texgyrescholamath"] = { options = { extras = "texgyre", features = "math\\mathsizesuffix" } } +defaults["texgyretermesmath"] = { options = { extras = "texgyre", features = "math\\mathsizesuffix" } } +defaults["xitsmath"] = { options = { extras = "xits-math", features = "math\\mathsizesuffix", goodies = "xits-math" } } + +extras["features"] = function(data,alternative,features) + local d = data.options.features + local e = gsub(gsub(features,"*",d),"{(.*)}","%1") local f = data.features + if trace_features then + report_features("Alternative '%s': Saving features '%s'",alternative,e) + end if not f then f = { } data.features = f @@ -328,443 +103,824 @@ local function savefeatures(data,alternative,entries) f[alternative] = e end -local function savegoodies(data,alternative,entries) - local e = gsub(entries,"{(.*)}","%1") +extras["goodies"] = function(data,alternative,goodies) + local e = gsub(goodies,"{(.*)}","%1") local g = data.goodies - if not f then + if trace_goodies then + report_goodies("Alternative '%s': Saving goodies '%s'",alternative,e) + end + if not g then g = { } data.goodies = g end g[alternative] = e end -methods[v_simplefonts] = function(data,alternative,style) - local family = data.metadata.family - local names = names["simplefonts"][style] or names["simplefonts"]["regular"] - for _, name in next, names do - local filename = cleanname(formatters["%s%s"](family,name)) - local fullname = getlookups{ fullname = filename } - local fontname = getlookups{ fontname = filename } - local cleanfilename = getlookups{ cleanfilename = filename } - if #fullname > 0 then - savefont(data,alternative,fullname) - break - elseif #fontname > 0 then - savefont(data,alternative,fontname) - break - elseif #cleanfilename > 0 then - savefont(data,alternative,cleanfilename) - break - end +local function selectfont_savefile(data,alternative,bodyfontsize,size,file) + local f = data.files + local p, n = splitbase(file["filename"]) + local t = file["format"] + local r = file["rawname"] + if t == "ttc" then + n = formatters["%s(%s)"](n,r) end -end - -methods[v_default] = function(data,alternative,style) - local family = data.metadata.family - local spec = names["default"][style] or names["default"]["regular"] - local weights = spec["weight"] - for _, weight in next, weights do - local pattern = getlookups{ - familyname = cleanname(family), - pfmweight = weight, - pfmwidth = spec["width"], - } - if #pattern > 0 then - local fontfiles = { } - for _, fontfile in next, pattern do - if (fontfile["angle"] and spec["italic"] == true) or (not fontfile["angle"] and spec["italic"] == false) then - fontfiles[#fontfiles + 1] = fontfile - end - end - savefont(data,alternative,fontfiles) - break - end + if not f then + f = { } + data.files = f end -end - -methods[v_selectfont] = function(data,alternative,style) - local family = data.metadata.family - local spec = names["selectfont"][style] or names["selectfont"]["regular"] - local pattern = getlookups{ - familyname = cleanname(family), - weight = spec["weight"], - style = spec["style"], - width = spec["width"], - variant = spec["variant"] - } - if #pattern > 0 then - local fontfiles = { } - for _, fontfile in next, pattern do - if (fontfile["angle"] and spec["italic"] == true) or (not fontfile["angle"] and spec["italic"] == false) then - fontfiles[#fontfiles + 1] = fontfile - end - end - savefont(data,alternative,fontfiles) + local a = f[alternative] + if not a then + a = { } + f[alternative] = a + end + a[bodyfontsize] = { size, n } + if trace_files then + report_files("Alternative '%s': Saving file '%s' for size '%s'",alternative,n,size) end end -methods["name"] = function(data,alternative,filename) - local data = data +methods["name"] = function(data,alternative,name) local family = data.metadata.family - local filename = cleanname(gsub(filename,"*",family)) - local fullname = getlookups{ fullname = filename } + local filename = cleanname(gsub(name,"*",family)) + if trace_alternatives then + report_selectfont("Alternative '%s': Using method 'name' with argument '%s'",alternative,filename) + end local fontname = getlookups{ fontname = filename } - if #fullname > 0 then - savefont(data,alternative,fullname) - elseif #fontname > 0 then - savefont(data,alternative,fontname) + local fullname = getlookups{ fullname = filename } + if #fontname > 0 then + selectfont_savefile(data,alternative,0,"default",fullname[1]) + elseif #fullname > 0 then + selectfont_savefile(data,alternative,0,"default",fontname[1]) + else + if trace_alternatives then + report_selectfont("Alternative '%s': No font was found for the requested name '%s'",alternative,filename) + end end end -methods["file"] = function(data,alternative,filename) - local data = data +methods["file"] = function(data,alternative,file) local family = data.metadata.family - local filename = gsub(removesuffix(filename),"*",family) + local filename = cleanname(gsub(removesuffix(file),"*",family)) + if trace_alternatives then + report_selectfont("Alternative '%s': Using method 'file' with argument '%s'",alternative,filename) + end local filename = getlookups{ cleanfilename = cleanname(filename) } if #filename > 0 then - savefont(data,alternative,filename) + selectfont_savefile(data,alternative,0,"default",filename[1]) + else + if trace_alternatives then + report_selectfont("Alternative '%s': No font was found for the requested file '%s'",alternative,cleanname(gsub(removesuffix(file),"*",family))) + end end end -methods["spec"] = function(data,alternative,filename) - local family = data.metadata.family - local weight, style, width, variant = splitup(filename,"-") - local pattern = getlookups{ - familyname = cleanname(family), - weight = weight or "normal", - style = style or "normal", - width = width or "normal", - variant = variant or "normal", - } - if #pattern > 0 then - savefont(data,alternative,pattern) - end -end +local m_weight = { + ["thin"] = 100, + ["extralight"] = 200, + ["light"] = 300, + ["regular"] = 400, + ["medium"] = 500, + ["semibold"] = 600, + ["bold"] = 700, + ["extrabold"] = 800, + ["black"] = 900 +} -methods["style"] = function(data,alternative,style) - local method = data.options.alternative or nil - (methods[method] or methods[v_default])(data,alternative,style) -end +local m_width = { + ["ultracondensed"] = 1, + ["extracondensed"] = 2, + ["condensed"] = 3, + ["semicondensed"] = 4, + ["normal"] = 5, + ["semiexpanded"] = 6, + ["expanded"] = 7, + ["extraexpanded"] = 8, + ["ultraexpanded"] = 9, +} -methods["features"] = function(data,alternative,features) - savefeatures(data,alternative,features) -end +local m_name = { + ["thin"] = { weight = "thin" }, + ["thinitalic"] = { weight = "thin", style = "italic" }, + ["extralight"] = { weight = "extralight" }, + ["extralightitalic"] = { weight = "extralight", style = "italic" }, + ["light"] = { weight = "light" }, + ["lightitalic"] = { weight = "light", style = "italic" }, + ["regular"] = { weight = { "regular", "medium" } }, + ["italic"] = { weight = { "regular", "medium" }, style = "italic" }, + ["medium"] = { weight = "medium" }, + ["mediumitalic"] = { weight = "medium", style = "italic" }, + ["semibold"] = { weight = "semibold" }, + ["semibolditalic"] = { weight = "semibold", style = "italic" }, + ["bold"] = { weight = { "bold", "semibold" } }, + ["bolditalic"] = { weight = { "bold", "semibold" }, style = "italic" }, + ["extrabold"] = { weight = "extrabold" }, + ["extrabolditalic"] = { weight = "extrabold", style = "italic" }, + ["black"] = { weight = "black" }, + ["blackitalic"] = { weight = "black", style = "italic" }, + ["smallcaps"] = { weight = "regular", variant = "smallcaps" }, +} -methods["goodies"] = function(data,alternative,goodies) - savegoodies(data,alternative,goodies) +local m_alternative = { + ["tf"] = "regular", + ["bf"] = "bold", + ["it"] = "italic", + ["sl"] = "italic", + ["bi"] = "bolditalic", + ["bs"] = "bolditalic", + ["sc"] = "regular" +} + +--~ methods["style"] = function(data,alternative,style) +--~ local family = data.metadata.family +--~ local style = m_alternative[style] or style +--~ if trace_alternatives then +--~ report_selectfont("Alternative '%s': Using method 'style' with argument '%s'",alternative,style) +--~ end +--~ local fontweight = m_name[style] and m_name[style]["weight"] or "regular" +--~ local fontstyle = m_name[style] and m_name[style]["style"] or "normal" +--~ local fontwidth = m_name[style] and m_name[style]["width"] or "normal" +--~ local pattern = getlookups{ +--~ familyname = cleanname(family), +--~ pfmweight = m_weight[fontweight], +--~ style = fontstyle +--~ } +--~ if #pattern == 1 then +--~ selectfont_savefile(data,alternative,0,"default",pattern[1]) +--~ elseif #pattern > 1 then +--~ local bodyfontsize, minsize, maxsize, width = nil, nil, nil, nil +--~ for patternindex, patternentry in next, pattern do +--~ minsize = patternentry["minsize"] +--~ maxsize = patternentry["maxsize"] +--~ width = patternentry["pfmwidth"] +--~ if minsize and maxsize then +--~ for fontsize, fontstate in next, bodyfontsizes do +--~ bodyfontsize, _ = number.splitdimen(fontsize) +--~ bodyfontsize = bodyfontsize * 10 +--~ if minsize < bodyfontsize and bodyfontsize < maxsize then +--~ if bodyfontsize == 100 then +--~ selectfont_savefile(data,alternative,0,"default",patternentry) +--~ end +--~ selectfont_savefile(data,alternative,bodyfontsize,fontsize,patternentry) +--~ end +--~ end +--~ else +--~ if width == m_width[fontwidth] then +--~ selectfont_savefile(data,alternative,0,"default",patternentry) +--~ end +--~ end +--~ end +--~ else +--~ if trace_alternatives then +--~ report_selectfont("Alternative '%s': No font was found for the requested style '%s' from '%s'",alternative,style,family) +--~ end +--~ end +--~ end + +local function m_style_family(family) + local askedname = cleanname(family) + local familyname = getlookups{ familyname = askedname } + local family = getlookups{ family = askedname } + local fontname = getlookups{ fontname = askedname } + if #familyname > 0 then + return familyname + elseif #family > 0 then + return family + elseif #fontname > 0 then + local fontfamily = fontname[1]["familyname"] + report_selectfont("The name '%s' is not a proper family name, use '%s' instead.",askedname,fontfamily) + return nil + else + return nil + end end -function selectfont.searchfiles(index) - local data = data[index] - for alternative, _ in next, alternatives do - local filename = data.files[alternative] - local method = data.options.alternative - local family = data.metadata.family - local style = alternatives[alternative] - if filename == "" then - local pattern = getlookups{ familyname = cleanname(family) } - if #pattern == 1 and alternative == "tf" then -- needs to be improved - savefont(data,alternative,pattern) - else - (methods[method] or methods[v_default])(data,alternative,style) +local function m_style_weight(entries,style) + local t = { } + local weight = m_name[style] and m_name[style]["weight"] or "regular" + if type(weight) == "table" then + for _, w in next, weight do + local found = false + local pfmweight = m_weight[w] + for index, entry in next, entries do + if entry["pfmweight"] == pfmweight then + found = true + t[#t+1] = entry + elseif entry["weight"] == w then + found = true + t[#t+1] = entry + end end - else - method, filename = splitup(filename,":") - if not filename then - filename = method - method = "name" + if found then break end + end + else + local pfmweight = m_weight[weight] + for index, entry in next, entries do + if entry["pfmweight"] == pfmweight then + t[#t+1] = entry + elseif entry["weight"] == weight then + t[#t+1] = entry end - (methods[method] or methods["name"])(data,alternative,filename) end end + return #t ~= 0 and t or nil end -function selectfont.filterinput(index) - local data = data[index] - local p = splitat(":",true) - for alternative, _ in next, alternatives do - local list = settings_to_array(data.alternatives[alternative]) - for _, entry in next, list do - method, entries = lpegmatch(p,entry) - if not entries then - entries = method - method = "name" - end - (methods[method] or methods["name"])(data,alternative,entries) +local function m_style_style(entries,style) + local t = { } + local style = m_name[style] and m_name[style]["style"] or "normal" + for index, entry in next, entries do + if style == "italic" and entry["angle"] and entry["angle"] ~= 0 then + t[#t+1] = entry + elseif style == "normal" and entry["angle"] and entry["angle"] ~= 0 then + --~ Fix needed for fonts with wrong value for the style field + elseif entry["style"] == style then + t[#t+1] = entry end end + return #t ~= 0 and t or nil end -local ctx_definefontsynonym = context.definefontsynonym -local ctx_resetfontfallback = context.resetfontfallback -local ctx_startfontclass = context.startfontclass -local ctx_stopfontclass = context.stopfontclass -local ctx_loadfontgoodies = context.loadfontgoodies -local ctx_definefontfallback = context.definefontfallback -local ctx_definetypeface = context.definetypeface - -local function definefontsynonym(data,alternative,index,fallback) - local fontdata = data.fonts and data.fonts[alternative] - local style = data.metadata.style - local typeface = data.metadata.typeface - local mathsettings = mathsettings[cleanname(data.metadata.family)] - local features = mathsettings and mathsettings["features"] and (mathsettings["features"][alternative] or mathsettings["features"]["tf"]) or data.features and data.features[alternative] or "" - local goodies = mathsettings and mathsettings["goodies"] and (mathsettings["goodies"] [alternative] or mathsettings["goodies"] ["tf"]) or data.goodies and data.goodies [alternative] or "" - local parent = replacement["style"][alternative] or "" - local fontname, fontfile, fontparent - if fallback then - fontname = formatters["%s-%s-%s-fallback-%s"](typeface, style, alternative, index) - fontfile = formatters["%s-%s-%s-%s"] (typeface, style, alternative, index) - fontparent = formatters["%s-%s-%s-fallback-%s"](typeface, style, parent, index) +local function m_style_variant(entries,style) + local t = { } + local variant = m_name[style] and m_name[style]["variant"] or "normal" + for index, entry in next, entries do + if entry["variant"] == variant then + t[#t+1] = entry + end + end + return #t ~= 0 and t or nil +end + +local function m_style_width(entries,style) + local t = { } + local width = m_name[style] and m_name[style]["width"] or "normal" + local pfmwidth = m_width[width] + for index, entry in next, entries do + if entry["pfmwidth"] == pfmwidth then + t[#t+1] = entry + end + end + return #t ~= 0 and t or nil +end + +local function m_style_size(data,alternative,entries) + if #entries == 1 then + selectfont_savefile(data,alternative,0,"default",entries[1]) else - fontname = synonyms[style][alternative] - fontfile = formatters["%s-%s-%s"](typeface, style, alternative) - fontparent = formatters["%s-%s-%s"](typeface, style, parent) - end - if fontdata and #fontdata > 0 then - for _, size in next, sizes["default"] do - for _, entry in next, fontdata do - if entry["minsize"] and entry["maxsize"] then - if size[1] > entry["minsize"] and size[1] <= entry["maxsize"] then - local filepath, filename = splitbase(entry["filename"]) - registerdesignsizes( fontfile, size[2], filename ) + for index, entry in next, entries do + local minsize = entry["minsize"] + local maxsize = entry["maxsize"] + if minsize and maxsize then + for size, state in next, bodyfontsizes do + local bodyfontsize, _ = number.splitdimen(size) + bodyfontsize = bodyfontsize * 10 + if minsize < bodyfontsize and bodyfontsize < maxsize then + if bodyfontsize == 100 then + selectfont_savefile(data,alternative,0,"default",entry) + end + selectfont_savefile(data,alternative,bodyfontsize,size,entry) end end + else + if trace_alternatives then + report_selectfont("Alternative '%s': Multiple files are available for the requested style '%s' from '%s'",alternative,style,family) + end end end - for _, entry in next, fontdata do - local designsize = entry["designsize"] or 100 - if designsize == 100 or designsize == 110 or designsize == 120 or designsize == 0 or #fontdata == 1 then - local filepath, filename = splitbase(entry["filename"]) - if entry["format"] == "ttc" or entry["format"] == "dfont" then - filename = formatters["%s(%s)"](filename, entry["rawname"]) + end +end + +methods["style"] = function(data,alternative,style) + local fontfamily = data.metadata.family + local designsize = data.options.designsize + local fontstyle = m_alternative[style] or style + local entries = m_style_family(fontfamily) + if entries then + entries = m_style_weight(entries,fontstyle) + if entries then + entries = m_style_style(entries,fontstyle) + if entries then + entries = m_style_variant(entries,fontstyle) + if entries and #entries > 1 and designsize == "default" then + entries = m_style_width(entries,fontstyle) end - registerdesignsizes( fontfile, "default", filename ) - break end end - if fallback then - -- can we use - ctx_definefontsynonym( { fontname }, { fontfile }, { features = features } ) - else - ctx_definefontsynonym( { fontname }, { fontfile }, { features = features, fallbacks = fontfile, goodies = goodies } ) + end + if entries then + m_style_size(data,alternative,entries) + else + if trace_alternatives then + report_selectfont("Alternative '%s': No font was found for the requested style '%s' from '%s'",alternative,style,family) + end + end +end + +methods[v_default] = function(data,alternative) + local family = data.metadata.family + if trace_alternatives then + report_selectfont("Alternative '%s': Using method 'default'",alternative) + end + local result = getlookups{ familyname = cleanname(family) } + if #result == 1 and alternative == "tf" then + if trace_alternatives then + report_selectfont("Alternative '%s': The family '%s' contains only one font",alternative,family) end + selectfont_savefile(data,alternative,0,"default",result[1]) + --~ if trace_alternatives then + --~ report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative) + --~ end + --~ methods["file"](data,alternative,result[1]["filename"]) else - if fallback then - ctx_definefontsynonym( { fontname }, { fontparent }, { features = features } ) - else - ctx_definefontsynonym( { fontname }, { fontparent }, { features = features, fallbacks = fontfile, goodies = goodies } ) + if trace_alternatives then + report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative) end + methods["style"](data,alternative,alternative) + end +end + +local function selectfont_savealternative(data,alternative,userdata) + local a = data.alternatives + local e = userdata[alternative] + if not a then + a = { } + data.alternatives = a end + a[alternative] = e end -local function definetypescript(index) - local data = data[index] - local entry = data.fonts - local mathsettings = mathsettings[cleanname(data.metadata.family)] - local goodies = mathsettings and mathsettings.extras or data.options.goodies - local typeface = data.metadata.typeface - local style = data.metadata.style - if entry and entry["tf"] then - ctx_startfontclass( { typeface } ) - if goodies ~= "" then - goodies = utilities.parsers.settings_to_array(goodies) - for _, goodie in next, goodies do - ctx_loadfontgoodies( { goodie } ) +function selectfont.fontdata(index) + local data = data[index] + local style = data.metadata.style + local defaults = defaults[style] + if defaults then + for category, argument in next, defaults do + local extra = extras[category] + if extra then + for alternative, entry in next, argument do + extra(data,alternative,entry) + end end end - for alternative, _ in next, alternatives do - if synonyms[style][alternative] then -- prevent unnecessary synonyms for handwriting, calligraphy and math - definefontsynonym(data,alternative) + end +end + +function selectfont.userdata(index) + local data = data[index] + local preset = data.options.preset + local presets = presets[preset] + local userdata = settings_to_hash(data.userdata) + if presets then + merge(userdata,presets) + end + for alternative, _ in next, alternatives do + selectfont_savealternative(data,alternative,userdata) + end +end + +--~ function selectfont.registerfiles(index) +--~ local data = data[index] +--~ local colon = splitat(":",true) +--~ for alternative, _ in next, alternatives do +--~ local arguments = data.alternatives[alternative] +--~ if arguments ~= "" then +--~ local entries = settings_to_array(arguments) +--~ local setmethod = false +--~ for index, entry in next, entries do +--~ method, argument = lpegmatch(colon,entry) +--~ if not argument then +--~ argument = method +--~ method = "name" +--~ end +--~ if extras[method] then +--~ extras[method](data,alternative,argument) +--~ elseif methods[method] then +--~ if not setmethod then +--~ setmethod = true +--~ methods[method](data,alternative,argument) +--~ end +--~ end +--~ end +--~ if not setmethod then +--~ methods[v_default](data,alternative) +--~ end +--~ else +--~ methods[v_default](data,alternative) +--~ end +--~ end +--~ end + +function selectfont.registerfiles(index) + local data = data[index] + local colon = splitat(":",true) + for alternative, _ in next, alternatives do + local arguments = data.alternatives[alternative] + if arguments and arguments ~= "" then + local entries = settings_to_array(arguments) + for index, entry in next, entries do + method, argument = lpegmatch(colon,entry) + if not argument then + argument = method + method = "name" + end + (extras[method] or methods[method] or methods[v_default])(data,alternative,argument) end + else + methods[v_default](data,alternative) end - ctx_stopfontclass() + end +end + +function selectfont.registerfontalternative(alternative) + local a = alternatives[alternative] + if not a then + if trace_register then + report_selectfont("Register alternative '%s'",alternative) + end + a = true + alternatives[alternative] = a + end +end + +function selectfont.registerfallback(index) + local data = data[index] + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local fallback = fallbacks[fontclass] + if not fallback then + fallback = { } + fallbacks[fontclass] = fallback + end + local entries = fallback[fontstyle] + if not entries then + entries = { } + fallback[fontstyle] = entries + end + entries[#entries+1] = index +end + +function selectfont.registerfontfamily(settings) + local index = #data + 1 + data[index] = settings + selectfont.fontdata (index) + selectfont.userdata (index) + selectfont.registerfiles(index) + return index +end + +local m_synonym = { + ["rm"] = { + ["tf"] = "Serif", + ["bf"] = "SerifBold", + ["it"] = "SerifItalic", + ["sl"] = "SerifSlanted", + ["bi"] = "SerifBoldItalic", + ["bs"] = "SerifBoldSlanted", + ["sc"] = "SerifCaps", + }, + ["ss"] = { + ["tf"] = "Sans", + ["bf"] = "SansBold", + ["it"] = "SansItalic", + ["sl"] = "SansSlanted", + ["bi"] = "SansBoldItalic", + ["bs"] = "SansBoldSlanted", + ["sc"] = "SansCaps", + }, + ["tt"] = { + ["tf"] = "Mono", + ["bf"] = "MonoBold", + ["it"] = "MonoItalic", + ["sl"] = "MonoSlanted", + ["bi"] = "MonoBoldItalic", + ["bs"] = "MonoBoldSlanted", + ["sc"] = "MonoCaps", + }, + ["mm"] = { + ["tf"] = "MathRoman", + ["bf"] = "MathBold", + }, + ["hw"] = { + ["tf"] = "Handwriting", + }, + ["cg"] = { + ["tf"] = "Calligraphy", + }, +} + +function selectfont.features(data,style,alternative) + local family = data.metadata.family + local features = data.features + local options = data.options + local defaults = defaults[cleanname(family)] + if features and features[alternative] then + return features[alternative] + elseif defaults and defaults.options and defaults.options.features then + return defaults.options.features else - -- regular style not available, loading aborted + return options.features end end -function selectfont.registerfallback(typeface,style,index) - local t = fallbacks[typeface] - if not t then - fallbacks[typeface] = { [style] = { index } } +function selectfont.goodies(data,style,alternative) + local family = data.metadata.family + local goodies = data.goodies + local options = data.options + local defaults = defaults[cleanname(family)] + if goodies and goodies[alternative] then + return goodies[alternative] + elseif defaults and defaults.options and defaults.options.goodies then + return defaults.options.goodies else - local s = t[style] - if not s then - fallbacks[typeface][style] = { index } - else - fallbacks[typeface][style][#s+1] = index + return options.goodies + end +end + +function selectfont.fontsynonym(data,class,style,alternative,index) + local fontfiles = data.files[alternative] or data.files["tf"] + local fontsizes = sortedkeys(fontfiles) + local fallback = index ~= 0 + --~ local fontfeature = data.features and data.features[alternative] or data.options.features + --~ local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies + local fontfeature = selectfont.features(data,style,alternative) + local fontgoodie = selectfont.goodies (data,style,alternative) + local synonym = m_synonym[style] and m_synonym[style][alternative] + local fontfile = formatters ["file-%s-%s-%s"](class,style,alternative) + local fontsynonym = formatters ["synonym-%s-%s-%s"](class,style,alternative) + if fallback then + fontfile = formatters ["file-%s-%s-%s-%s"](class,style,alternative,index) + fontsynonym = formatters ["synonym-%s-%s-%s-%s"](class,style,alternative,index) + end + local fontfallback = formatters["fallback-%s-%s-%s"](class,style,alternative) + for _, fontsize in next, fontsizes do + --~ if trace_typescript then + --~ report_typescript("Synonym: '%s', Size: '%s', File: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2]) + --~ end + registerdesignsizes(fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2]) + end + if fallback then + --~ if trace_typescript then + --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s'",fontsynonym,fontfile,fontfeature) + --~ end + ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature } ) + else + --~ if trace_typescript then + --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s', Goodies: '%s', Fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback) + --~ end + ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature, goodies = fontgoodie, fallbacks = fontfallback } ) + if synonym then + --~ if trace_typescript then + --~ report_typescript("Synonym: '%s', File: '%s'",synonym,fontsynonym) + --~ end + ctx_definefontsynonym( { synonym }, { fontsynonym } ) end end end -local function definetextfontfallback(data,alternative,index) - local typeface = data.metadata.typeface - local style = data.metadata.style - local features = data.features[alternative] - local range = data.options.range - local rscale = data.options.scale ~= "" and data.options.scale or 1 - local check = data.options.check ~= "" and data.options.check or "yes" - local force = data.options.force ~= "" and data.options.force or "yes" - local synonym = formatters["%s-%s-%s-fallback-%s"](typeface, style, alternative, index) - local fallback = formatters["%s-%s-%s"] (typeface, style, alternative) +function selectfont.fontfallback(data,class,style,alternative,index) + local range = data.options.range + local scale = data.options.rscale ~= "" and data.options.rscale or 1 + local check = data.options.check ~= "" and data.options.check or "yes" + local force = data.options.force ~= "" and data.options.force or "no" + local fontfeature = data.features and data.features[alternative] or data.options.features + local fontsynonym = formatters["synonym-%s-%s-%s-%s"](class,style,alternative,index) + local fontfallback = formatters["fallback-%s-%s-%s"] (class,style,alternative) if index == 1 then - ctx_resetfontfallback( { fallback } ) + ctx_resetfontfallback( { fontfallback } ) end - ctx_definefontfallback( { fallback }, { synonym }, { range }, { rscale = rscale, check = check, force = force } ) + --~ if trace_typescript then + --~ report_typescript("Fallback: '%s', Synonym: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s'",fontfallback,fontsynonym,range,scale,check,force) + --~ end + ctx_definefontfallback( { fontfallback }, { fontsynonym }, { range }, { rscale = scale, check = check, force = force } ) end -local function definetextfallback(entry,index) - local data = data[index] - local typeface = data.metadata.typeface - ctx_startfontclass( { typeface } ) - for alternative, _ in next, alternatives do - definefontsynonym (data,alternative,entry,true) - definetextfontfallback(data,alternative,entry) +function selectfont.filefallback(data,class,style,alternative,index) + local range = data.options.range + local offset = data.options.offset + local scale = data.options.rscale ~= "" and data.options.rscale or 1 + local check = data.options.check ~= "" and data.options.check or "yes" + local force = data.options.force ~= "" and data.options.force or "yes" + local fontfile = data.files[alternative] and data.files[alternative][0] or data.files["tf"][0] + local fontfeature = data.features and data.features[alternative] or data.options.features + local fontfallback = formatters["fallback-%s-%s-%s"](class,style,alternative) + if index == 1 then + ctx_resetfontfallback( { fontfallback } ) end + --~ if trace_typescript then + --~ report_typescript("Fallback: '%s', File: '%s', Features: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s', Offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset) + --~ end + ctx_definefontfallback( { fontfallback }, { formatters["file:%s*%s"](fontfile[2],fontfeature) }, { range }, { rscale = scale, check = check, force = force, offset = offset } ) +end + +function selectfont.mathfallback(index,entry,class,style) + local data = data[entry] + ctx_startfontclass( { class } ) + for alternative, _ in next, alternatives do + if alternative == "tf" or alternative == "bf" then + selectfont.filefallback(data,class,style,alternative,index) + end + end ctx_stopfontclass() - -- inspect(data) end -local function definemathfontfallback(data,alternative,index) - local typeface = data.metadata.typeface - local style = data.metadata.style - local range = data.options.range - local rscale = data.options.scale ~= "" and data.options.scale or 1 - local check = data.options.check ~= "" and data.options.check or "yes" - local force = data.options.force ~= "" and data.options.force or "yes" - local offset = data.options.offset - local features = data.features[alternative] - local fontdata = data.fonts and data.fonts[alternative] - local fallback = formatters["%s-%s-%s"](typeface, style, alternative) - if index == 1 then - ctx_resetfontfallback( { fallback } ) - end - if fontdata and #fontdata > 0 then - for _, entry in next, fontdata do - local filename = entry["filename"] - local designsize = entry["designsize"] or 100 - if designsize == 100 or designsize == 110 or designsize == 120 or designsize == 0 or #fontdata == 1 then - ctx_definefontfallback( { fallback }, { formatters["file:%s*%s"](filename,features) }, { range }, { rscale = rscale, check = check, force = force, offset = offset } ) - break +function selectfont.textfallback(index,entry,class,style) + local data = data[entry] + ctx_startfontclass( { class } ) + for alternative, _ in next, alternatives do + selectfont.fontsynonym (data,class,style,alternative,index) + selectfont.fontfallback(data,class,style,alternative,index) + end + ctx_stopfontclass() +end + +function selectfont.fallback(data) + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local fallbacks = fallbacks[fontclass] and fallbacks[fontclass][fontstyle] + if fallbacks then + for index, entry in next, fallbacks do + --~ I need different fallback routines for math and text because + --~ font synonyms can’t be used with math fonts and I have to apply + --~ feature settings with the \definefontfallback command. + if fontstyle == "mm" then + selectfont.mathfallback(index,entry,fontclass,fontstyle) + else + selectfont.textfallback(index,entry,fontclass,fontstyle) end end end end -local function definemathfallback(entry,index) - local data = data[index] - local typeface = data.metadata.typeface +function selectfont.typescript(data) + local class = data.metadata.typeface + local family = data.metadata.family local style = data.metadata.style - ctx_startfontclass( { typeface } ) - for alternative, _ in next, alternatives do - if synonyms[style][alternative] then - definemathfontfallback(data,alternative,entry) - end + local extras = data.options.extras + local defaults = defaults[cleanname(family)] + if extras == "" then + extras = defaults and defaults.options and defaults.options.extras or "" end - ctx_stopfontclass() - -- inspect(data) -end - -local function definefallbackfont(index) - local data = data[index] - local f = fallbacks[data.metadata.typeface] - if f then - local s = f[data.metadata.style] - if s then - for entry, fallback in next, s do - if data.metadata.style == "mm" then - definemathfallback(entry,fallback) - else - definetextfallback(entry,fallback) + ctx_startfontclass( { class } ) + if extras ~= "" then + extras = settings_to_array(extras) + for _, extra in next, extras do + ctx_loadfontgoodies( { extra } ) + end + end + for alternative, _ in next, alternatives do + if style == "mm" then -- Set math fonts only for upright and bold alternatives + if alternative == "tf" or alternative == "bf" then + selectfont.fontsynonym (data,class,style,alternative,0) end + else + selectfont.fontsynonym (data,class,style,alternative,0) end end + ctx_stopfontclass() +end + +function selectfont.bodyfont(data) + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local fontsizes = concat(sortedkeys(bodyfontsizes),",") + local fontsynonym = nil + local fontlist = { } + for alternative, _ in next, alternatives do + fontsynonym = formatters["synonym-%s-%s-%s"](fontclass,fontstyle,alternative) + fontlist[#fontlist+1] = formatters["%s=%s sa 1"] (alternative,fontsynonym) + --~ if trace_typescript then + --~ report_typescript("Alternative '%s': Synonym '%s'",alternative,fontsynonym) + --~ end + end + fontlist = concat(fontlist,",") + ctx_definebodyfont( { fontclass }, { fontsizes }, { fontstyle }, { fontlist } ) +end + +local m_style = { + ["rm"] = "serif", + ["ss"] = "sans", + ["tt"] = "mono", + ["mm"] = "math", + ["hw"] = "handwriting", + ["cg"] = "calligraphy", +} + +function selectfont.typeface(data) + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local style = m_style[fontstyle] + local size = data.options.designsize ~= "" and data.options.designsize or "default" + local scale = data.options.rscale ~= "" and data.options.rscale or 1 + --~ if trace_typescript then + --~ report_typescript("Class: '%s', Style: '%s', Size: '%s', Scale: '%s'",fontclass,fontstyle,size,scale) + --~ end + if fontstyle == "mm" then -- math uses the default bodyfont settings because it uses 'ma' and 'mb' as alternative names + ctx_definetypeface( { fontclass }, { fontstyle }, { style }, { "" }, { "default" }, { designsize = size, rscale = scale } ) + else + ctx_definetypeface( { fontclass }, { fontstyle }, { "" }, { "" }, { "" }, { designsize = size, rscale = scale } ) end end -local function definetextfont(index) - local data = data[index] - local fontclass = data.metadata.typeface - local shortstyle = data.metadata.style - local style = styles[data.metadata.style] - local designsize = data.options.opticals == v_yes and "auto" or "default" - local scale = data.options.scale ~= "" and data.options.scale or 1 - ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { "" }, { "default" }, { designsize = designsize, rscale = scale } ) +function selectfont.default(data) + local family = data.metadata.family + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local style = m_style[fontstyle] + report_selectfont("The requested font '%s' has no files for the 'tf' alternative, Latin Modern is used instead.",family) + ctx_definetypeface( { fontclass }, { fontstyle }, { style }, { "modern" }, { "default" } ) end -local function definemathfont(index) - local data = data[index] - local fontclass = data.metadata.typeface - local shortstyle = data.metadata.style - local style = styles[data.metadata.style] - local scale = data.options.scale ~= "" and data.options.scale or 1 - local typescript = cleanname(data.metadata.family) - local entries = data.fonts - if entries then - ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { "" }, { "default" }, { rscale = scale } ) +function selectfont.definefontfamily(index) + local data = data[index] + local fontstyle = data.metadata.style + local fontfiles = data.files and data.files["tf"] + if fontfiles then + selectfont.fallback (data) + selectfont.typescript(data) + if fontstyle ~= "mm" then + selectfont.bodyfont(data) + end + selectfont.typeface(data) else - ctx_definetypeface( { fontclass }, { shortstyle }, { style }, { typescript }, { "default" }, { rscale = scale } ) + selectfont.default(data) end end -function selectfont.definetypeface(index) - local data = data[index] - if data.metadata.style == "mm" then - definefallbackfont(index) - definetypescript (index) - definemathfont (index) +function selectfont.definefallbackfamily(index) + local data = data[index] + local family = data.metadata.family + local fontclass = data.metadata.typeface + local fontstyle = data.metadata.style + local fontfiles = data.files + if fontfiles then + selectfont.registerfallback(index) else - definefallbackfont(index) - definetypescript (index) - definetextfont (index) + report_selectfont("The requested fallback font '%s' for typeface '%s' style '%s' was ignored because no files where found.",family,fontclass,fontstyle) end - -- inspect(data) end -local styles = { - { "tf" }, { "bf" }, { "it" }, { "sl" }, { "bi" }, { "bs" }, { "sc" }, -} +function selectfont.definefontfamilypreset(name,data) + local p = presets[name] + local d = settings_to_hash(data) + if not p then + p = d + presets[name] = p + end +end implement { - name = "defineselectfont", - actions = { selectfont.define, context }, + name = "registerfontfamily", + actions = { selectfont.registerfontfamily, context }, arguments = { { { "metadata", { { "typeface" }, { "style" }, - { "family" }, + { "family" } } }, { "options", { - { "opticals" }, - { "scale" }, + { "designsize" }, + { "rscale" }, { "goodies" }, - { "alternative" }, + { "preset" }, + { "extras" }, + { "features" }, { "range" }, { "offset" }, { "check" }, - { "force" }, + { "force" } } }, - { "alternatives", styles }, - { "files", styles }, - { "features", styles }, + { + "userdata" + } } - } + } +} + +implement { + name = "registerfontalternative", + actions = selectfont.registerfontalternative, + arguments = "string" } implement { name = "definefontfamily", - actions = selectfont.definetypeface, + actions = selectfont.definefontfamily, arguments = "integer" } implement { name = "definefallbackfamily", - actions = selectfont.registerfallback, - arguments = { "string", "string", "integer"} + actions = selectfont.definefallbackfamily, + arguments = "integer" } + +implement { + name = "definefontfamilypreset", + actions = selectfont.definefontfamilypreset, + arguments = { "string", "string" } +} \ No newline at end of file diff --git a/tex/context/base/mkiv/font-sel.mkvi b/tex/context/base/mkiv/font-sel.mkvi index eb45ea033..4e74f6864 100644 --- a/tex/context/base/mkiv/font-sel.mkvi +++ b/tex/context/base/mkiv/font-sel.mkvi @@ -1,6 +1,6 @@ %D \module %D [ file=font-sel, -%D version=2014.07.27, +%D version=2016.05.16, %D title=\CONTEXT\ User Module, %D subtitle=Selectfont, %D author=Wolfgang Schuster, @@ -17,7 +17,7 @@ \installcorenamespace {selectfont} \installsimplecommandhandler \??selectfont {selectfont} -\unexpanded\def\selectfont_setparameters[#settings]% +\unexpanded\def\selectfont_register[#settings]% {\begingroup \setupcurrentselectfont[#settings]% \edef\p_selectfont_preset{\selectfontparameter\c!preset}% @@ -25,74 +25,31 @@ \processcommacommand[\p_selectfont_preset]\selectfont_preset_process \setupcurrentselectfont[#settings]% \fi - \setexpandedselectfontparameter\c!style {\expandnamespaceparameter\??selectfontstyle \selectfontparameter\c!style \s!rm }% - \setexpandedselectfontparameter\c!alternative{\expandnamespaceparameter\??selectfontalternative\selectfontparameter\c!alternative\v!default}% - \xdef\selectfont_index{\clf_defineselectfont + \font_helpers_process_alternative_list\clf_registerfontalternative + \setexpandedselectfontparameter\c!style{\expandnamespaceparameter\??fontshortstyle\selectfontparameter\c!style\s!rm}% + \xdef\selectfont_index{\clf_registerfontfamily metadata {% - typeface {\selectfontparameter\c!name}% + typeface {\selectfontparameter\c!label}% style {\selectfontparameter\c!style}% - family {\selectfontparameter\c!family}% + family {\selectfontparameter\c!name}% } options {% - opticals {\selectfontparameter\c!opticalsize}% - scale {\selectfontparameter\c!scale}% + designsize {\selectfontparameter\s!designsize}% + rscale {\selectfontparameter\s!rscale}% goodies {\selectfontparameter\c!goodies}% - alternative {\selectfontparameter\c!alternative}% + extras {\selectfontparameter\c!extras}% + features {\selectfontparameter\c!features}% + preset {\selectfontparameter\c!preset}% range {\selectfontparameter\c!range}% fallback only offset {\selectfontparameter\c!offset}% fallback only check {\selectfontparameter\c!check}% fallback only force {\selectfontparameter\c!force}% fallback only } - alternatives {% - tf {\selectfontparameter\s!tf}% - bf {\selectfontparameter\s!bf}% - it {\selectfontparameter\s!it}% - sl {\selectfontparameter\s!sl}% - bi {\selectfontparameter\s!bi}% - bs {\selectfontparameter\s!bs}% - sc {\selectfontparameter\s!sc}% - } - files {% - tf {\selectfontparameter\c!regularfont}% - bf {\selectfontparameter\c!boldfont}% - it {\selectfontparameter\c!italicfont}% - sl {\selectfontparameter\c!slantedfont}% - bi {\selectfontparameter\c!bolditalicfont}% - bs {\selectfontparameter\c!boldslantedfont}% - sc {\selectfontparameter\c!smallcapsfont}% - } - features {% - tf {\selectfontparameter\c!regularfeatures}% - bf {\selectfontparameter\c!boldfeatures}% - it {\selectfontparameter\c!italicfeatures}% - sl {\selectfontparameter\c!slantedfeatures}% - bi {\selectfontparameter\c!bolditalicfeatures}% - bs {\selectfontparameter\c!boldslantedfeatures}% - sc {\selectfontparameter\c!smallcapsfeatures}% - }}% + userdata {% + \luaexpanded{#settings}% + }}% \endgroup} -%D \macros -%D {defineselectfontstyle} - -\installcorenamespace {selectfontstyle} - -\unexpanded\def\defineselectfontstyle - {\dodoubleargument\selectfont_style_define} - -\def\selectfont_style_define[#styles][#shortstyle]% - {\processcommalist[#styles]{\selectfont_style_define_indeed{#shortstyle}}} - -\def\selectfont_style_define_indeed#shortstyle#style% - {\setvalue{\??selectfontstyle#style}{#shortstyle}} - -\defineselectfontstyle [\s!rm,\s!serif] [\s!rm] -\defineselectfontstyle [\s!ss,\s!sans] [\s!ss] -\defineselectfontstyle [\s!tt,\s!mono] [\s!tt] -\defineselectfontstyle [\s!hw,\s!handwriting] [\s!hw] -\defineselectfontstyle [\s!cg,\s!calligraphy] [\s!cg] -\defineselectfontstyle [\s!mm,\s!math] [\s!mm] - %D \macros %D {definefontfamilypreset} @@ -113,6 +70,10 @@ % unknown preset \fi} +\def\selectfont_preset_define[#name][#settings]% + {\setvalue{\??selectfontpreset#name}{\setupcurrentselectfont[#settings]}% + \clf_definefontfamilypreset{#name}{\luaexpanded{#settings}}} + \definefontfamilypreset [range:chinese] [\c!range={cjkcompatibilityforms, @@ -131,19 +92,19 @@ \definefontfamilypreset [range:japanese] - [\crange={cjkcompatibilityforms, - cjkcompatibilityideographs, - cjkcompatibilityideographssupplement, - cjkradicalssupplement, - cjkstrokes, - cjksymbolsandpunctuation, - cjkunifiedideographs, - cjkunifiedideographsextensiona, - cjkunifiedideographsextensionb, - halfwidthandfullwidthforms, - verticalforms, - hiragana, - katakana}] + [\c!range={cjkcompatibilityforms, + cjkcompatibilityideographs, + cjkcompatibilityideographssupplement, + cjkradicalssupplement, + cjkstrokes, + cjksymbolsandpunctuation, + cjkunifiedideographs, + cjkunifiedideographsextensiona, + cjkunifiedideographsextensionb, + halfwidthandfullwidthforms, + verticalforms, + hiragana, + katakana}] \definefontfamilypreset [range:korean] @@ -207,36 +168,6 @@ \definefontfamilypreset [math:uppercasegreekbold] [\c!range=uppercasegreeknormal,\c!offset=uppercasegreekbold, \s!tf=style:bold] \definefontfamilypreset [math:uppercasegreekbolditalic] [\c!range=uppercasegreeknormal,\c!offset=uppercasegreekbolditalic,\s!tf=style:bolditalic] - -%D \macros -%D {defineselectfontalternative} -%D -%D The results between the old {\em simplefonts} and the new {\em selectfont} -%D can be different because simplefonts the name entries in the database to find -%D the styles for a font while selectfont the newer spec-method to the find the -%D files for each style. -%D -%D The used method depends on the command one uses to load a font but it is -%D also possible to switch between them with the {\em alternative} key, possible -%D values are: -%D -%D \startitemize[packed] -%D \startitem selectfont and \stopitem -%D \startitem simplefonts. \stopitem -%D \stopitemize - -\installcorenamespace {selectfontalternative} - -\unexpanded\def\defineselectfontalternative - {\dodoubleargument\selectfont_alternative_define} - -\def\selectfont_alternative_define[#name][#alternative]% - {\setvalue{\??selectfontalternative#name}{#alternative}} - -\defineselectfontalternative [\v!selectfont ] [\v!selectfont ] -\defineselectfontalternative [\v!simplefonts] [\v!simplefonts] -\defineselectfontalternative [\v!default ] [\v!default ] - %D \macros %D {definefontfamily,definefallbackfamily} %D @@ -250,17 +181,17 @@ %D \definefontfamily [dejavu] [serif] [DejaVu Serif] %D \definefontfamily [dejavu] [sans] [DejaVu Sans] %D \definefontfamily [dejavu] [mono] [DejaVu Sans Mono] -%D \definefontfamily [dejavu] [math] [XITS Math] [scale=1.1] +%D \definefontfamily [dejavu] [math] [XITS Math] [rscale=1.1] %D %D \definefontfamily [office] [serif] [Times New Roman] -%D \definefontfamily [office] [sans] [Arial] [scale=0.9] +%D \definefontfamily [office] [sans] [Arial] [rscale=0.9] %D \definefontfamily [office] [mono] [Courier] %D \definefontfamily [office] [math] [TeX Gyre Termes Math] %D %D \definefontfamily [linux] [serif] [Linux Libertine O] %D \definefontfamily [linux] [sans] [Linux Biolinum O] %D \definefontfamily [linux] [mono] [Latin Modern Mono] -%D \definefontfamily [linux] [math] [TeX Gyre Pagella Math] [scale=0.9] +%D \definefontfamily [linux] [math] [TeX Gyre Pagella Math] [rscale=0.9] %D %D \setupbodyfont[dejavu] %D @@ -306,7 +237,7 @@ %D optical sizes when they are a feature of the requested font. %D %D \starttyping -%D \definefontfamily[mainface][serif][Latin Modern Roman][opticalsize=yes] +%D \definefontfamily[mainface][serif][Latin Modern Roman][designsize=auto] %D %D \setupbodyfont[mainface] %D @@ -319,15 +250,15 @@ %D \stoptext %D \stoptyping -% regularfont = … | * … | name:… | name:* … | file:… | file:* … | spec:…-…-… | style:medium +% tf = … | * … | name:… | name:* … | file:… | file:* … | style:medium \unexpanded\def\definefontfamily {\doquadrupleempty\selectfont_family_define} \def\selectfont_family_define[#typeface][#style][#family][#settings]% {\doifelseassignment{#settings} - {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},#settings]} - {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},\c!preset={#settings}]}% + {\selectfont_register[\c!label={#typeface},\c!style={#style},\c!name={#family},#settings]} + {\selectfont_register[\c!label={#typeface},\c!style={#style},\c!name={#family},\c!preset={#settings}]}% \clf_definefontfamily\selectfont_index\relax} \unexpanded\def\definefallbackfamily @@ -335,95 +266,13 @@ \def\selectfont_fallback_define[#typeface][#style][#family][#settings]% {\doifelseassignment{#settings} - {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},#settings]} - {\selectfont_setparameters[\c!name={#typeface},\c!style={#style},\c!family={#family},\c!preset={#settings}]}% - \edef\p_selectfont_style{\expandnamespacevalue\??selectfontstyle{#style}\s!rm}% - \clf_definefallbackfamily{#typeface}{\p_selectfont_style}\selectfont_index\relax} - -%D \macros -%D {setupfontfamily,setupfallbackfamily} -%D -%D For simple documents which don’t need complex font settings one could use -%D the \tex{setupfontfamily} command where the requested font is enabled immediately -%D without the need to load it with \tex{setupbodyfont}. The downside of this method -%D is that processing of the document takes longer with each additional font which -%D is set with \tex{setupfontfamily}. -%D -%D \starttyping -%D \setupfontfamily [serif] [DejaVu Serif] -%D \setupfontfamily [sans] [DejaVu Sans] -%D \setupfontfamily [mono] [DejaVu Sans Mono] -%D \setupfontfamily [math] [XITS Math] [scale=1.1] -%D -%D \starttext -%D -%D \rm Serif 123 \ss Sans \tt Mono \m{1+2=3} -%D -%D \stoptext -%D \stoptyping - -\newcount\c_selectfont_family -\newtoks \t_selectfont_fallback -\newtoks \t_selectfont_styles - -\unexpanded\def\setupfontfamily - {\dotripleempty\selectfont_family_setup} - -\def\selectfont_family_setup - {\ifsecondargument - \expandafter\selectfont_family_setup_yes - \else - \expandafter\selectfont_family_setup_nop - \fi} - -\def\selectfont_family_setup_yes[#style][#family][#settings]% - {\normalexpanded{\t_selectfont_styles{\selectfont_set_font_family[#style][#family][#settings]\the\t_selectfont_styles}}% - \selectfont_set_font_indeed} - -\def\selectfont_family_setup_nop[#settings][#dummya][#dummyb]% - {\setupselectfont[#settings]} - -\unexpanded\def\selectfont_set_default - {\selectfont_set_font_family[\v!serif][Latin Modern Roman][\c!opticalsize=\v!yes]% - \selectfont_set_font_family[\v!sans] [Latin Modern Sans] [\c!opticalsize=\v!yes]% - \selectfont_set_font_family[\v!mono] [Latin Modern Mono] [\c!opticalsize=\v!yes,\c!features=\s!none]% - \selectfont_set_font_family[\v!math] [Latin Modern Math] [\c!opticalsize=\v!yes]} - -\unexpanded\def\setupfallbackfamily - {\dotripleempty\selectfont_fallback_setup} - -\def\selectfont_fallback_setup[#style][#family][#settings]% - {\normalexpanded{\t_selectfont_fallback{\the\t_selectfont_fallback\selectfont_set_font_fallback[#style][#family][#settings]}}} - -\def\selectfont_set_font_indeed - {\global\advance\c_selectfont_family\plusone - \edef\m_selectfont_typeface{\v!selectfont-\number\c_selectfont_family}% - \the\t_selectfont_fallback - \the\t_selectfont_styles - \selectfont_set_default - \setupbodyfont[\m_selectfont_typeface,\rootselectfontparameter\c!style]} - -\unexpanded\def\selectfont_set_font_family[#style]#dummy[#family]#dummy[#settings]% - {\ifcsname\m_selectfont_typeface#style\endcsname \else - \expandafter\let\csname\m_selectfont_typeface#style\endcsname\relax - \selectfont_family_define[\m_selectfont_typeface][#style][#family][#settings]% - \fi} - -\unexpanded\def\selectfont_set_font_fallback[#style]#dummy[#family]#dummy[#settings]% - {\selectfont_fallback_define[\m_selectfont_typeface][#style][#family][#settings]} - -%D You can apply a different feature set to each style of a font but if nothing -%D is set the global features are used. + {\selectfont_register[\c!label={#typeface},\c!style={#style},\c!name={#family},#settings]} + {\selectfont_register[\c!label={#typeface},\c!style={#style},\c!name={#family},\c!preset={#settings}]}% + \clf_definefallbackfamily\selectfont_index\relax} \setupselectfont - [ \c!features=\s!default, - \c!regularfeatures=\selectfontparameter\c!features, - \c!boldfeatures=\selectfontparameter\c!features, - \c!italicfeatures=\selectfontparameter\c!features, - \c!slantedfeatures=\selectfontparameter\c!features, - \c!bolditalicfeatures=\selectfontparameter\c!features, - \c!boldslantedfeatures=\selectfontparameter\c!features, - \c!smallcapsfeatures=\s!smallcaps, - \c!style=\s!rm] + [ \c!features=\s!default, + \s!designsize=\s!default, + \s!rscale=1] -\protect +\protect \ No newline at end of file diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua index bb8a7d331..f8720f717 100644 --- a/tex/context/base/mkiv/node-ini.lua +++ b/tex/context/base/mkiv/node-ini.lua @@ -265,6 +265,15 @@ end local nodecodes = simplified(node.types()) local whatcodes = simplified(node.whatsits()) +local usercodes = allocate { + [ 97] = "attributes", -- a + [100] = "number", -- d + [108] = "lua", -- l + [110] = "nodes", -- n + [115] = "string", -- s + [116] = "tokens" -- t +} + skipcodes = allocate(swapped(skipcodes,skipcodes)) boundarycodes = allocate(swapped(boundarycodes,boundarycodes)) noadcodes = allocate(swapped(noadcodes,noadcodes)) @@ -283,25 +292,32 @@ accentcodes = allocate(swapped(accentcodes,accentcodes)) fencecodes = allocate(swapped(fencecodes,fencecodes)) rulecodes = allocate(swapped(rulecodes,rulecodes)) leadercodes = allocate(swapped(leadercodes,leadercodes)) +usercodes = allocate(swapped(usercodes,usercodes)) -nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official +nodes.skipcodes = skipcodes nodes.boundarycodes = boundarycodes nodes.noadcodes = noadcodes nodes.nodecodes = nodecodes -nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official +nodes.whatcodes = whatcodes nodes.listcodes = listcodes nodes.glyphcodes = glyphcodes nodes.kerncodes = kerncodes nodes.penaltycodes = penaltycodes nodes.mathcodes = mathcodes nodes.fillcodes = fillcodes -nodes.margincodes = margincodes nodes.marginkerncodes = margincodes -nodes.disccodes = disccodes nodes.discretionarycodes = disccodes +nodes.margincodes = margincodes +nodes.disccodes = disccodes nodes.accentcodes = accentcodes nodes.radicalcodes = radicalcodes nodes.fencecodes = fencecodes nodes.rulecodes = rulecodes nodes.leadercodes = leadercodes +nodes.usercodes = usercodes + +nodes.gluecodes = skipcodes -- more official +nodes.whatsitcodes = whatcodes -- more official +nodes.marginkerncodes = margincodes +nodes.discretionarycodes = disccodes listcodes.row = listcodes.alignment listcodes.column = listcodes.alignment @@ -327,6 +343,9 @@ nodes.codes = allocate { -- mostly for listing whatsit = whatcodes, accent = accentcodes, fence = fencecodes, + rule = rulecodes, + leader = leadercodes, + user = usercodes, } local report_codes = logs.reporter("nodes","codes") diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index 4d25314ad..bb09656fb 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -27,6 +27,7 @@ local kerncodes = nodes.kerncodes local rulecodes = nodes.rulecodes local nodecodes = nodes.nodecodes local boundarycodes = nodes.boundarycodes +local usercodes = nodes.usercodes local glyph_code = nodecodes.glyph @@ -150,11 +151,15 @@ local textdir = register_nut(new_nut("dir")) local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua)) local special = register_nut(new_nut("whatsit",whatsitcodes.special)) -local user_n = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_n,"type",100) -- 44 -local user_l = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_l,"type",110) -- 44 -local user_s = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_s,"type",115) -- 44 -local user_t = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_t,"type",116) -- 44 ------ user_c = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_c,"type",108) -- 44 + +local user_node = new_nut("whatsit",whatsitcodes.userdefined) + +local user_number = register_nut(copy_nut(user_node)) setfield(user_number, "type",usercodes.number) +local user_nodes = register_nut(copy_nut(user_node)) setfield(user_nodes, "type",usercodes.nodes) +local user_string = register_nut(copy_nut(user_node)) setfield(user_string, "type",usercodes.string) +local user_tokens = register_nut(copy_nut(user_node)) setfield(user_tokens, "type",usercodes.tokens) +----- user_lua = register_nut(copy_nut(user_node)) setfield(user_lua, "type",usercodes.lua) -- in > 0.95 +local user_attributes = register_nut(copy_nut(user_node)) setfield(user_attributes,"type",usercodes.attributes) local left_margin_kern = register_nut(new_nut("margin_kern",0)) local right_margin_kern = register_nut(new_nut("margin_kern",1)) @@ -571,7 +576,7 @@ end -- local str = userids[num] function nutpool.usernumber(id,num) - local n = copy_nut(user_n) + local n = copy_nut(user_number) if num then setfield(n,"user_id",id) setfield(n,"value",num) @@ -582,7 +587,7 @@ function nutpool.usernumber(id,num) end function nutpool.userlist(id,list) - local n = copy_nut(user_l) + local n = copy_nut(user_nodes) if list then setfield(n,"user_id",id) setfield(n,"value",list) @@ -593,7 +598,7 @@ function nutpool.userlist(id,list) end function nutpool.userstring(id,str) - local n = copy_nut(user_s) + local n = copy_nut(user_string) if str then setfield(n,"user_id",id) setfield(n,"value",str) @@ -604,7 +609,7 @@ function nutpool.userstring(id,str) end function nutpool.usertokens(id,tokens) - local n = copy_nut(user_t) + local n = copy_nut(user_tokens) if tokens then setfield(n,"user_id",id) setfield(n,"value",tokens) @@ -614,16 +619,27 @@ function nutpool.usertokens(id,tokens) return n end --- function nutpool.usercode(id,code) --- local n = copy_nut(user_c) --- if code then --- setfield(n,"user_id",id) --- setfield(n,"value",code) --- else --- setfield(n,"value",id) --- end --- return n --- end +function nutpool.userlua(id,code) + local n = copy_nut(user_lua) + if code then + setfield(n,"user_id",id) + setfield(n,"value",code) + else + setfield(n,"value",id) + end + return n +end + +function nutpool.userattributes(id,attr) + local n = copy_nut(user_attributes) + if attr then + setfield(n,"user_id",id) + setfield(n,"value",attr) + else + setfield(n,"value",id) + end + return n +end function nutpool.special(str) local n = copy_nut(special) @@ -637,24 +653,22 @@ local function cleanup(nofboxes) -- todo if nodes.tracers.steppers then -- to be resolved nodes.tracers.steppers.reset() -- todo: make a registration subsystem end - local nl, nr = 0, nofreserved + local nl = 0 + local nr = nofreserved for i=1,nofreserved do local ri = reserved[i] - -- if not (getid(ri) == glue_spec and not getfield(ri,"is_writable")) then - free_nut(reserved[i]) - -- end + free_nut(reserved[i]) end if nofboxes then for i=0,nofboxes do local l = getbox(i) if l then --- print(nodes.listtoutf(getlist(l))) free_nut(l) -- also list ? nl = nl + 1 end end end - reserved = { } + reserved = { } nofreserved = 0 return nr, nl, nofboxes -- can be nil end diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua index 39d90794c..4cd39336e 100644 --- a/tex/context/base/mkiv/spac-prf.lua +++ b/tex/context/base/mkiv/spac-prf.lua @@ -60,6 +60,9 @@ local setlink = nuts.setlink local setlist = nuts.setlist local setattr = nuts.setattr +local properties = nodes.properties.data +local setprop = nuts.setprop +local getprop = nuts.getprop local theprop = nuts.theprop local floor = math.floor @@ -73,12 +76,10 @@ local link_nodes = nuts.link local find_node_tail = nuts.tail local setglue = nuts.setglue -local properties = nodes.properties.data - local a_visual = attributes.private("visual") local a_snapmethod = attributes.private("snapmethod") local a_profilemethod = attributes.private("profilemethod") -local a_specialcontent = attributes.private("specialcontent") +----- a_specialcontent = attributes.private("specialcontent") local variables = interfaces.variables local v_none = variables.none @@ -203,7 +204,8 @@ local function getprofile(line,step) -- we could do a nested check .. but then we need to push / pop glue local shift = getfield(current,"shift") wd = getfield(current,"width") - if getattr(current,a_specialcontent) then + -- if getattr(current,a_specialcontent) then + if getprop(current,"specialcontent") then -- like a margin note, maybe check for wd ht = 0 dp = 0 diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 2df57c9f6..e1434d8c7 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 07fdd4da4..1a1577b9e 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/typo-mar.lua b/tex/context/base/mkiv/typo-mar.lua index cbac9f851..727846678 100644 --- a/tex/context/base/mkiv/typo-mar.lua +++ b/tex/context/base/mkiv/typo-mar.lua @@ -74,7 +74,7 @@ if not modules then modules = { } end modules ['typo-mar'] = { -- so far local format, validstring = string.format, string.valid -local insert, remove, sortedkeys = table.insert, table.remove, table.sortedkeys +local insert, remove, sortedkeys, fastcopy = table.insert, table.remove, table.sortedkeys, table.fastcopy local setmetatable, next = setmetatable, next local formatters = string.formatters local toboolean = toboolean @@ -86,7 +86,7 @@ local trace_margindata = false trackers.register("typesetters.margindata", local trace_marginstack = false trackers.register("typesetters.margindata.stack", function(v) trace_marginstack = v end) local trace_margingroup = false trackers.register("typesetters.margindata.group", function(v) trace_margingroup = v end) -local report_margindata = logs.reporter("typesetters","margindata") +local report_margindata = logs.reporter("margindata") local tasks = nodes.tasks local prependaction = tasks.prependaction @@ -147,6 +147,9 @@ local getbox = nuts.getbox local getlist = nuts.getlist local setlist = nuts.setlist +local setprop = nuts.setprop +local getprop = nuts.getprop + local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes local gluecodes = nodes.gluecodes @@ -183,8 +186,7 @@ local addtoline = paragraphs.addtoline local moveinline = paragraphs.moveinline local calculatedelta = paragraphs.calculatedelta -local a_margindata = attributes.private("margindata") -local a_specialcontent = attributes.private("specialcontent") +----- a_specialcontent = attributes.private("specialcontent") local a_linenumber = attributes.private('linenumber') local inline_mark = nodepool.userids["margins.inline"] @@ -268,7 +270,8 @@ end function margins.save(t) setmetatable(t,defaults) local content = getbox(t.number) -setattr(content,a_specialcontent,1) -- todo: a property + -- setattr(content,a_specialcontent,1) + setprop(content,"specialcontent","margindata") local location = t.location local category = t.category local inline = t.inline @@ -276,10 +279,6 @@ setattr(content,a_specialcontent,1) -- todo: a property local name = t.name local option = t.option local stack = t.stack - if stack == v_yes or stack == v_continue then - inline = false - t.inline = false - end if option then option = settings_to_hash(option) t.option = option @@ -388,8 +387,6 @@ end -- When the prototype inner/outer code that was part of this proved to be -- okay it was moved elsewhere. -local status, nofstatus = { }, 0 - -- local f_anchor = formatters["_plib_.set('md:h',%i,{x=true,c=true})"] -- local s_anchor = 'md:h' -- @@ -420,7 +417,6 @@ local function realign(current,candidate) local atleft = true local hmove = 0 local delta = 0 - -- local realpageno = candidate.realpageno local leftpage = isleftpage(false,true) local leftdelta = 0 local rightdelta = 0 @@ -489,11 +485,10 @@ local function realign(current,candidate) moveinline(hook,candidate.node,delta) end -local function realigned(current,a) - local candidate = status[a] +local function realigned(current,candidate) realign(current,candidate) nofdelayed = nofdelayed - 1 - status[a] = nil + setprop(current,"margindata",false) return true end @@ -509,36 +504,43 @@ end local stacked = { } -- left/right keys depending on location local cache = { } - -local function resetstacked() - stacked = { } +local anchors = { } + +local function resetstacked(location) + if location then + local s = { } + stacked[location] = s + anchors[location] = false + return s + else + stacked = { } + anchors = { } + return stacked + end end --- resetstacked() +-- anchors are only set for lines that have a note -local function ha(tag) -- maybe l/r keys ipv left/right keys +local function sa(tag) -- maybe l/r keys ipv left/right keys local p = cache[tag] + if trace_marginstack then + report_margindata("updating anchor %a",tag) + end p.p = true p.y = true +-- p.a = tag setposition('md:v',tag,p) cache[tag] = nil end -margins.ha = ha - -local f_anchor = formatters["typesetters.margins.ha(%s)"] - -local function setanchor(v_anchor) - return new_latelua(f_anchor(v_anchor)) +local function setanchor(v_anchor) -- freezes the global here + return lateluafunction(function() sa(v_anchor) end) end --- local function setanchor(v_anchor) -- freezes the global here --- return lateluafunction(function() ha(v_anchor) end) --- end - local function markovershoot(current) -- todo: alleen als offset > line v_anchors = v_anchors + 1 - cache[v_anchors] = stacked + cache[v_anchors] = fastcopy(stacked) +-- cache[v_anchors] = stacked -- so we adapt the previous too local anchor = setanchor(v_anchors) -- local list = hpack_nodes(linked_nodes(anchor,getlist(current))) -- not ok, we need to retain width local list = hpack_nodes(linked_nodes(anchor,getlist(current)),getfield(current,"width"),"exactly")-- @@ -550,27 +552,66 @@ local function markovershoot(current) -- todo: alleen als offset > line setlist(current,list) end +-- local function getovershoot(location) +-- local p = getposition("md:v",v_anchors) +-- local c = getposition("md:v",v_anchors+1) +-- if p and c and p.p and p.p == c.p then +-- local distance = p.y - c.y +-- local offset = p[location] or 0 +-- local overshoot = offset - distance +-- if trace_marginstack then +-- report_margindata("location %a, anchor %a, distance %p, offset %p, overshoot %p",location,v_anchors,distance,offset,overshoot) +-- end +-- if overshoot > 0 then +-- return overshoot, offset, distance +-- else +-- return 0, offset, distance +-- end +-- elseif trace_marginstack then +-- report_margindata("location %a, anchor %a, nothing to correct",location,v_anchors) +-- end +-- return 0, 0, 0 +-- end + local function getovershoot(location) - local p = getposition("md:v",v_anchors) local c = getposition("md:v",v_anchors+1) - if p and c and p.p and p.p == c.p then - local distance = p.y - c.y - local offset = p[location] or 0 - local overshoot = offset - distance - if trace_marginstack then - report_margindata("location %a, anchor %a, distance %p, offset %p, overshoot %p",location,v_anchors,distance,offset,overshoot) + if c then + local p = false + local cp = c.p + for i=v_anchors,1,-1 do + local pi = getposition("md:v",i) + if pi.p == cp then + p = pi + else + break + end end - if overshoot > 0 then - return overshoot + if p then + local distance = p.y - c.y + local offset = p[location] or 0 + local overshoot = offset - distance + if trace_marginstack then + report_margindata("location %a, anchor %a, distance %p, offset %p, overshoot %p",location,v_anchors,distance,offset,overshoot) + end + if overshoot > 0 then + return overshoot, offset, distance + else + return 0, offset, distance + end end - elseif trace_marginstack then + end + if trace_marginstack then report_margindata("location %a, anchor %a, nothing to correct",location,v_anchors) end - return 0 + return 0, 0, 0 +end + +local function getanchor(location,anchor) + return getposition("md:v",anchor) end local function inject(parent,head,candidate) - local box = candidate.box + local box = candidate.box if not box then return head, nil, false -- we can have empty texts end @@ -586,12 +627,11 @@ local function inject(parent,head,candidate) local baseline = candidate.baseline local strutheight = candidate.strutheight local strutdepth = candidate.strutdepth + local inline = candidate.inline local psubtype = getsubtype(parent) local offset = stacked[location] local firstonstack = offset == false or offset == nil - nofstatus = nofstatus + 1 nofdelayed = nofdelayed + 1 - status[nofstatus] = candidate -- yet untested baseline = tonumber(baseline) if not baseline then @@ -613,6 +653,34 @@ local function inject(parent,head,candidate) if trace_margindata then report_margindata("processing, index %s, height %p, depth %p, parent %a, method %a",candidate.n,height,depth,listcodes[psubtype],method) end + -- The next section handles the inline notes that are checked for overlap which + -- is somewhat tricky as that mechanism is mostly for paragraph boundnotes. + local stackedinline = inline and (stack == v_yes or stack == v_continue) + if stackedinline then + firstonstack = true + if anchors[location] then + local a1 = getanchor(location,anchors[location]) + local a2 = getanchor(location,v_anchors+1) + if a1 and a2 then + local distance = a1.y - a2.y + if distance > offset then + -- report_margindata("location %s, no overlap, case 1",location) + elseif offset > 0 then + offset = offset - distance + firstonstack = false + -- report_margindata("location %s, overlap %a",location,offset) + -- else + -- report_margindata("location %s, no overlap, case 2",location) + end + -- else + -- report_margindata("location %s, no overlap, case 3",location) + end + -- else + -- report_margindata("location %s, no overlap, case 4",location) + end + anchors[location] = v_anchors + 1 + end + -- end of special section if firstonstack then offset = 0 else @@ -693,7 +761,7 @@ local function inject(parent,head,candidate) -- candidate.hook, candidate.node = addtoline(parent,box) -- - setattr(box,a_margindata,nofstatus) + setprop(box,"margindata",candidate) if trace_margindata then report_margindata("injected, location %a, shift %p",location,shift) end @@ -704,14 +772,16 @@ local function inject(parent,head,candidate) depth = offset, slack = candidate.bottomspace, -- todo: 'depth' => strutdepth lineheight = candidate.lineheight, -- only for tracing + stacked = stackedinline, } offset = offset + height - stacked[location] = offset -- weird, no table ? + -- we need a restart ... when there is no overlap at all + stacked[location] = offset -- todo: if no real depth then zero if trace_margindata then report_margindata("status, offset %s",offset) end - return getlist(parent), room, stack == v_continue + return getlist(parent), room, stackedinline or (stack == v_continue) end local function flushinline(parent,head) @@ -729,9 +799,15 @@ local function flushinline(parent,head) inlinestore[n] = nil nofinlined = nofinlined - 1 head, room, con = inject(parent,head,candidate) -- maybe return applied offset - continue = continue or con - done = true + done = true + continue = continue or con nofstored = nofstored - 1 + if room and room.stacked then + -- for now we also check for inline+yes/continue, maybe someday no such check + -- will happen; we can assume most inlines are one line heigh; also this + -- together feature can become optional + registertogether(tonode(parent),room) -- !! tonode + end end end elseif id == hlist_code or id == vlist_code then @@ -761,8 +837,8 @@ local function flushed(scope,parent) -- current is hlist local candidate = remove(store,1) -- brr, local stores are sparse if candidate then -- no vpack, as we want to realign head, room, con = inject(parent,head,candidate) - done = true - continue = continue or con + done = true + continue = continue or con nofstored = nofstored - 1 if room then registertogether(tonode(parent),room) -- !! tonode @@ -817,11 +893,11 @@ local function handler(scope,head,group) local done = false while current do local id = getid(current) - if (id == vlist_code or id == hlist_code) and not getattr(current,a_margindata) then + if (id == vlist_code or id == hlist_code) and getprop(current,"margindata") == nil then local don, continue = flushed(scope,current) if don then done = true - setattr(current,a_margindata,0) -- signal to prevent duplicate processing + setprop(current,"margindata",false) -- signal to prevent duplicate processing if continue then markovershoot(current) end @@ -909,8 +985,9 @@ local function finalhandler(head) while current and nofdelayed > 0 do local id = getid(current) if id == hlist_code then -- only lines? - local a = getattr(current,a_margindata) - if not a or a == 0 then + local a = getprop(current,"margindata") +-- if not a or a == 0 then + if not a then finalhandler(getlist(current)) elseif realigned(current,a) then done = true @@ -946,26 +1023,23 @@ end -- Somehow the vbox builder (in combinations) gets pretty confused and decides to -- go horizontal. So this needs more testing. -prependaction("finalizers", "lists", "typesetters.margins.localhandler") --- ("vboxbuilders", "normalizers", "typesetters.margins.localhandler") -prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") -prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler") +prependaction("finalizers", "lists", "typesetters.margins.localhandler") +prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") +prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler") -disableaction("finalizers", "typesetters.margins.localhandler") --- ("vboxbuilders", "typesetters.margins.localhandler") -disableaction("mvlbuilders", "typesetters.margins.globalhandler") -disableaction("shipouts", "typesetters.margins.finalhandler") +disableaction("finalizers", "typesetters.margins.localhandler") +disableaction("mvlbuilders", "typesetters.margins.globalhandler") +disableaction("shipouts", "typesetters.margins.finalhandler") enablelocal = function() - enableaction("finalizers", "typesetters.margins.localhandler") - -- enableaction("vboxbuilders", "typesetters.margins.localhandler") - enableaction("shipouts", "typesetters.margins.finalhandler") + enableaction("finalizers", "typesetters.margins.localhandler") + enableaction("shipouts", "typesetters.margins.finalhandler") enablelocal = nil end enableglobal = function() - enableaction("mvlbuilders", "typesetters.margins.globalhandler") - enableaction("shipouts", "typesetters.margins.finalhandler") + enableaction("mvlbuilders", "typesetters.margins.globalhandler") + enableaction("shipouts", "typesetters.margins.finalhandler") enableglobal = nil end diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf index d07ada96c..fb29c8b5b 100644 Binary files a/tex/context/interface/mkiv/i-context.pdf and b/tex/context/interface/mkiv/i-context.pdf differ diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf index 73a93c89a..652553799 100644 Binary files a/tex/context/interface/mkiv/i-readme.pdf and b/tex/context/interface/mkiv/i-readme.pdf differ diff --git a/tex/context/modules/mkiv/m-scite.mkiv b/tex/context/modules/mkiv/m-scite.mkiv index e033235c3..fd4a3c7a1 100644 --- a/tex/context/modules/mkiv/m-scite.mkiv +++ b/tex/context/modules/mkiv/m-scite.mkiv @@ -62,6 +62,8 @@ local f_fore_bold = formatters["\\def\\slx%s#1{{\\slxc%s\\bf#1}}%%"] local f_none_bold = formatters["\\def\\slx%s#1{{\\bf#1}}%%"] local f_none_none = formatters["\\def\\slx%s#1{{#1}}%%"] local f_texstyled = formatters["\\slx%s{%s}"] +local f_hanging = formatters["\\slxb{%s}%s\\slxe"] + local f_mapping = [[ \let\string\slxL\string\letterleftbrace @@ -165,20 +167,21 @@ function scite.installcommands() context(exportcolors()) end -local p = lpeg.P("\\slxS ")^1 +local p1 = lpeg.tsplitat(lpeg.patterns.newline) +local p2 = lpeg.P("\\slxS ")^1 local function indent(str) - local l = string.split(str,"\n") + local l = lpegmatch(p1,str) for i=1,#l do local s = l[i] if #s > 0 then - local n = lpegmatch(p,s) + local n = lpegmatch(p2,s) if n then n = (n-1)/6 else n = 0 end - l[i] = formatters["\\slxb{%s}%s\\slxe"](n,s) + l[i] = f_hanging(n,s) end end return concat(l,"\n") diff --git a/tex/context/modules/mkiv/x-setups-basics.mkiv b/tex/context/modules/mkiv/x-setups-basics.mkiv index 02376deea..4a7859c7f 100644 --- a/tex/context/modules/mkiv/x-setups-basics.mkiv +++ b/tex/context/modules/mkiv/x-setups-basics.mkiv @@ -686,6 +686,13 @@ \getsetupstring{\xmlatt{#1}{type}} \stopxmlsetups +\definebar % in case we mess with underbar settings + [cmd_underbar] + [\v!underbar] + [\c!foregroundcolor=, + \c!foregroundstyle=, + \c!color=] + \startxmlsetups xml:setups:constant \doifelsemode {setups-pass-one} { } { @@ -694,7 +701,7 @@ \xmlmappedvalue{setups:method}{\xmlatt{#1}{method}}{none} } { \doif {\xmlatt{#1}{default}} {yes} { - \underbar % next needs to be {braced} + \cmd_underbar % next needs to be {braced} } } {\getsetupstring{\xmlatt{#1}{type}}} diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 83efc517f..b8d5ef8f0 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 : 05/17/16 19:20:58 +-- merge date : 05/19/16 13:43:44 do -- begin closure to overcome local limits and interference @@ -19686,7 +19686,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm while start do local char=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if not a or (a==attr) then local lookupmatch=lookupcache[char] if lookupmatch then @@ -19716,7 +19716,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) while start~=stop do local char=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if not a or (a==attr) then local lookupmatch=lookupcache[char] if lookupmatch then @@ -19749,7 +19749,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) end end local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler) - local a=getattr(sub,0) + local a=attr and getattr(sub,0) if not a or (a==attr) then for n in traverse_nodes(sub) do if n==last then @@ -19780,7 +19780,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm while start do local char=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if not a or (a==attr) then for i=1,nofsteps do local step=steps[i] @@ -19821,7 +19821,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) while start~=stop do local char=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if not a or (a==attr) then for i=1,nofsteps do local step=steps[i] @@ -19862,7 +19862,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) end end local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler) - local a=getattr(sub,0) + local a=attr and getattr(sub,0) if not a or (a==attr) then for n in traverse_nodes(sub) do if n==last then @@ -19944,6 +19944,9 @@ local function featuresprocessor(head,font,attr) nesting=nesting-1 return head,false end + if attr==0 then + attr=false + end head=tonut(head) if trace_steps then checkstep(head) @@ -19981,7 +19984,7 @@ local function featuresprocessor(head,font,attr) while start do local char=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if not a or (a==attr) then for i=1,nofsteps do local step=steps[i] @@ -20022,7 +20025,7 @@ local function featuresprocessor(head,font,attr) while start do local char,id=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if a then a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) else @@ -20072,7 +20075,7 @@ local function featuresprocessor(head,font,attr) while start do local char,id=ischar(start,font) if char then - local a=getattr(start,0) + local a=attr and getattr(start,0) if a then a=(a==attr) and (not attribute or getprop(start,a_state)==attribute) else @@ -22272,6 +22275,7 @@ local lpegmatch,patterns=lpeg.match,lpeg.patterns local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) local report_afm=logs.reporter("fonts","afm loading") +local report_afm=logs.reporter("fonts","pfb loading") fonts=fonts or {} local handlers=fonts.handlers or {} fonts.handlers=handlers @@ -22324,16 +22328,16 @@ do local function loadpfbvector(filename) local data=io.loaddata(resolvers.findfile(filename)) if not data then - print("no data",filename) + report_pfb("no data in %a",filename) return end - if not find(data,"!PS%-AdobeFont%-") then - print("no font",filename) + if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then + report_pfb("no font in %a",filename) return end local ascii,binary=match(data,"(.*)eexec%s+......(.*)") if not binary then - print("no binary",filename) + report_pfb("no binary data in %a",filename) return end binary=decrypt(binary,4) @@ -22342,7 +22346,7 @@ do vector[0]=table.remove(vector,1) end if not vector then - print("no vector",filename) + report_pfb("no vector in %a",filename) return end return vector @@ -22367,16 +22371,18 @@ do end end end -local spacing=patterns.whitespace +local spacer=patterns.spacer +local whitespace=patterns.whitespace local lineend=patterns.newline +local spacing=spacer^0 local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber -local name=spacing*C((1-spacing)^1) -local words=spacing*(1-lineend)^1/strip +local name=spacing*C((1-whitespace)^1) +local words=spacing*((1-lineend)^1/strip) local rest=(1-lineend)^0 local fontdata=Carg(1) local semicolon=spacing*P(";") -local plus=P("plus")*number -local minus=P("minus")*number +local plus=spacing*P("plus")*number +local minus=spacing*P("minus")*number local function addkernpair(data,one,two,value) local chr=data.characters[one] if chr then @@ -22461,6 +22467,7 @@ local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName +(fontdata*C("AXISHEIGHT")*number*rest)/set_1 ) local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) +local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop ) local function read(filename,parser) local afmblob=io.loaddata(filename) @@ -23195,7 +23202,8 @@ local function check_afm(specification,fullname) end end function readers.afm(specification,method) - local fullname,tfmdata=specification.filename or "",nil + local fullname=specification.filename or "" + local tfmdata=nil if fullname=="" then local forced=specification.forced or "" if forced~="" then @@ -23223,8 +23231,17 @@ function readers.pfb(specification,method) if trace_defining then report_afm("using afm reader for %a",original) end - specification.specification=file.replacesuffix(original,"afm") specification.forced="afm" + local function swap(name) + local value=specification[swap] + if value then + specification[swap]=gsub("%.pfb",".afm",1) + end + end + swap("filename") + swap("fullname") + swap("forcedname") + swap("specification") return readers.afm(specification,method) end -- cgit v1.2.3