diff options
26 files changed, 745 insertions, 643 deletions
diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua index 4cae856ab..574d0e39e 100644 --- a/scripts/context/lua/mtx-fonts.lua +++ b/scripts/context/lua/mtx-fonts.lua @@ -14,8 +14,8 @@ local suffix, addsuffix, removesuffix, replacesuffix = file.suffix, file.addsuff local nameonly, basename, joinpath, collapsepath = file.nameonly, file.basename, file.join, file.collapsepath local lower = string.lower -local otfversion = 2.824 -local otlversion = 3.019 +local otfversion = 2.825 +local otlversion = 3.020 local helpinfo = [[ <?xml version="1.0"?> diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex fbb5c71c9..50805410f 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv index ab9e4160c..3e055ea83 100644 --- a/tex/context/base/mkiv/back-pdf.mkiv +++ b/tex/context/base/mkiv/back-pdf.mkiv @@ -42,7 +42,7 @@ %D %D Here we initialize some internal quantities. We also protect them. -\outputmode \plusone \let\modeoutput \undefined \newcount\outputmode \outputmode \plusone +\outputmode\plusone \let\outputmode\relax \newcount\outputmode \outputmode\plusone %D Because we do a lot in \LUA\ and don't want interferences, we nil most of the %D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable}, @@ -113,7 +113,7 @@ \let\pdfimagegamma \relax \newcount\pdfimagegamma \let\pdfimagehicolor \relax \newcount\pdfimagehicolor \let\pdfimageresolution \relax \newcount\pdfimageresolution -\let\pdfincludechars \relax \newtoks \pdffontsize +\let\pdfincludechars \relax \newtoks \pdfincludechars \let\pdfinclusioncopyfonts \relax \newcount\pdfinclusioncopyfonts \let\pdfinclusionerrorlevel \relax \newcount\pdfinclusionerrorlevel \let\pdfinfoomitdate \relax \newcount\pdfinfoomitdate diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 1b0ec7432..7925f8797 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.08 17:30} +\newcontextversion{2016.05.10 23: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 c66b2856a..228e3f0cd 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.08 17:30} +\edef\contextversion{2016.05.10 23:43} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-ext.lua b/tex/context/base/mkiv/font-ext.lua index 189a588f1..98ad9e09e 100644 --- a/tex/context/base/mkiv/font-ext.lua +++ b/tex/context/base/mkiv/font-ext.lua @@ -554,17 +554,17 @@ local function initializemathitalics(tfmdata,value) -- yes no delay tfmdata.properties.mathitalics = toboolean(value) end -local mathitalics_specification = { - name = "mathitalics", - description = "use alternative math italic correction", - initializers = { - base = initializemathitalics, - node = initializemathitalics, - } -} +-- local mathitalics_specification = { +-- name = "mathitalics", +-- description = "use alternative math italic correction", +-- initializers = { +-- base = initializemathitalics, +-- node = initializemathitalics, +-- } +-- } -registerotffeature(mathitalics_specification) -registerafmfeature(mathitalics_specification) +-- registerotffeature(mathitalics_specification) +-- registerafmfeature(mathitalics_specification) -- slanting @@ -925,6 +925,45 @@ registerotffeature { -- } -- } +-- not to be used! experimental code, only needed when testing + +local is_letter = characters.is_letter +local always = true + +local function collapseitalics(tfmdata,key,value) + local threshold = value == true and 100 or tonumber(value) + if threshold and threshold > 0 then + if threshold > 100 then + threshold = 100 + end + for unicode, data in next, tfmdata.characters do + if always or is_letter[unicode] or is_letter[data.unicode] then + local italic = data.italic + if italic and italic ~= 0 then + local width = data.width + if width and width ~= 0 then + local delta = threshold * italic / 100 + data.width = width + delta + data.italic = italic - delta + end + end + end + end + end +end + +local dimensions_specification = { + name = "collapseitalics", + description = "collapse italics", + manipulators = { + base = collapseitalics, + node = collapseitalics, + } +} + +registerotffeature(dimensions_specification) +registerafmfeature(dimensions_specification) + -- a handy helper (might change or be moved to another namespace) local nodepool = nodes.pool diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua index 509e75107..838c74173 100644 --- a/tex/context/base/mkiv/font-map.lua +++ b/tex/context/base/mkiv/font-map.lua @@ -45,7 +45,7 @@ of obsolete. Some code may move to runtime or auxiliary modules.</p> -- end -- end -local hex = R("AF","09") +local hex = R("AF","af","09") ----- hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end ----- hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end @@ -295,145 +295,145 @@ function mappings.addtounicode(data,filename,checklookups) local ns = 0 local nl = 0 -- - for unic, glyph in next, descriptions do + for du, glyph in next, descriptions do local name = glyph.name if name then - local index = glyph.index - local r = overloads[name] - if r then + local overload = overloads[name] + if overload then -- get rid of weird ligatures - -- glyph.name = r.name - glyph.unicode = r.unicode - elseif not unic or unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then - local unicode = unicodevector[name] or contextvector[name] - if unicode then - glyph.unicode = unicode - ns = ns + 1 - end - -- cidmap heuristics, beware, there is no guarantee for a match unless - -- the chain resolves - if (not unicode) and usedmap then - local foundindex = lpegmatch(oparser,name) - if foundindex then - unicode = cidcodes[foundindex] -- name to number - if unicode then - glyph.unicode = unicode - ns = ns + 1 - else - local reference = cidnames[foundindex] -- number to name - if reference then - local foundindex = lpegmatch(oparser,reference) - if foundindex then - unicode = cidcodes[foundindex] - if unicode then - glyph.unicode = unicode - ns = ns + 1 + -- glyph.name = overload.name + glyph.unicode = overload.unicode + else + local gu = glyph.unicode -- can already be set (number or table) + if not gu or gu == -1 or du >= private or (du >= 0xE000 and du <= 0xF8FF) or du == 0xFFFE or du == 0xFFFF then + local unicode = unicodevector[name] or contextvector[name] + if unicode then + glyph.unicode = unicode + ns = ns + 1 + end + -- cidmap heuristics, beware, there is no guarantee for a match unless + -- the chain resolves + if (not unicode) and usedmap then + local foundindex = lpegmatch(oparser,name) + if foundindex then + unicode = cidcodes[foundindex] -- name to number + if unicode then + glyph.unicode = unicode + ns = ns + 1 + else + local reference = cidnames[foundindex] -- number to name + if reference then + local foundindex = lpegmatch(oparser,reference) + if foundindex then + unicode = cidcodes[foundindex] + if unicode then + glyph.unicode = unicode + ns = ns + 1 + end end - end - if not unicode or unicode == "" then - local foundcodes, multiple = lpegmatch(uparser,reference) - if foundcodes then - glyph.unicode = foundcodes - if multiple then - nl = nl + 1 - unicode = true - else - ns = ns + 1 - unicode = foundcodes + if not unicode or unicode == "" then + local foundcodes, multiple = lpegmatch(uparser,reference) + if foundcodes then + glyph.unicode = foundcodes + if multiple then + nl = nl + 1 + unicode = true + else + ns = ns + 1 + unicode = foundcodes + end end end end end end end - end - -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_ - -- - -- It is not trivial to find a solution that suits all fonts. We tried several alternatives - -- and this one seems to work reasonable also with fonts that use less standardized naming - -- schemes. The extra private test is tested by KE and seems to work okay with non-typical - -- fonts as well. - -- - if not unicode or unicode == "" then - local split = lpegmatch(namesplitter,name) - local nsplit = split and #split or 0 -- add if - if nsplit == 0 then - -- skip - elseif nsplit == 1 then - local base = split[1] - local u = unicodes[base] or unicodevector[base] or contextvector[name] - if not u then + -- a.whatever or a_b_c.whatever or a_b_c (no numbers) a.b_ + -- + -- It is not trivial to find a solution that suits all fonts. We tried several alternatives + -- and this one seems to work reasonable also with fonts that use less standardized naming + -- schemes. The extra private test is tested by KE and seems to work okay with non-typical + -- fonts as well. + -- + if not unicode or unicode == "" then + local split = lpegmatch(namesplitter,name) + local nsplit = split and #split or 0 -- add if + if nsplit == 0 then -- skip - elseif type(u) == "table" then - -- unlikely - if u[1] < private then - unicode = u - glyph.unicode = unicode - end - elseif u < private then - unicode = u - glyph.unicode = unicode - end - else - local t, n = { }, 0 - for l=1,nsplit do - local base = split[l] + elseif nsplit == 1 then + local base = split[1] local u = unicodes[base] or unicodevector[base] or contextvector[name] if not u then - break + -- skip elseif type(u) == "table" then - if u[1] >= private then - break + -- unlikely + if u[1] < private then + unicode = u + glyph.unicode = unicode end - n = n + 1 - t[n] = u[1] - else - if u >= private then + elseif u < private then + unicode = u + glyph.unicode = unicode + end + else + local t, n = { }, 0 + for l=1,nsplit do + local base = split[l] + local u = unicodes[base] or unicodevector[base] or contextvector[name] + if not u then break + elseif type(u) == "table" then + if u[1] >= private then + break + end + n = n + 1 + t[n] = u[1] + else + if u >= private then + break + end + n = n + 1 + t[n] = u + end + end + if n > 0 then + if n == 1 then + unicode = t[1] + else + unicode = t end - n = n + 1 - t[n] = u + glyph.unicode = unicode end end - if n > 0 then - if n == 1 then - unicode = t[1] + nl = nl + 1 + end + -- last resort (we might need to catch private here as well) + if not unicode or unicode == "" then + local foundcodes, multiple = lpegmatch(uparser,name) + if foundcodes then + glyph.unicode = foundcodes + if multiple then + nl = nl + 1 + unicode = true else - unicode = t + ns = ns + 1 + unicode = foundcodes end - glyph.unicode = unicode end end - nl = nl + 1 - end - -- last resort (we might need to catch private here as well) - if not unicode or unicode == "" then - local foundcodes, multiple = lpegmatch(uparser,name) - if foundcodes then - glyph.unicode = foundcodes - if multiple then - nl = nl + 1 - unicode = true - else - ns = ns + 1 - unicode = foundcodes - end + -- check using substitutes and alternates + local r = overloads[unicode] + if r then + unicode = r.unicode + glyph.unicode = unicode + end + -- + if not unicode then + missing[du] = true + nofmissing = nofmissing + 1 end - end - -- check using substitutes and alternates - local r = overloads[unicode] - if r then - unicode = r.unicode - glyph.unicode = unicode - end - -- - if not unicode then - missing[unic] = true - nofmissing = nofmissing + 1 end end - else - -- no name end end if type(checklookups) == "function" then diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua index b50da5417..d359e2132 100644 --- a/tex/context/base/mkiv/font-mis.lua +++ b/tex/context/base/mkiv/font-mis.lua @@ -21,7 +21,7 @@ local readers = otf.readers if readers then - otf.version = otf.version or 3.019 + otf.version = otf.version or 3.020 otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true) function fonts.helpers.getfeatures(name,save) diff --git a/tex/context/base/mkiv/font-one.lua b/tex/context/base/mkiv/font-one.lua index 3602fd465..af3246342 100644 --- a/tex/context/base/mkiv/font-one.lua +++ b/tex/context/base/mkiv/font-one.lua @@ -21,13 +21,13 @@ add features.</p> local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers -local next, type, tonumber = next, type, tonumber +local next, type, tonumber, rawget = next, type, tonumber, rawget local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find local char, byte, sub = string.char, string.byte, string.sub local abs = math.abs local bxor, rshift = bit32.bxor, bit32.rshift -local P, S, R, Cmt, C, Ct, Cs, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.match, lpeg.patterns -local derivetable = table.derive +local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg +local lpegmatch, patterns = lpeg.match, lpeg.patterns local trace_features = false trackers.register("afm.features", function(v) trace_features = v end) local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end) @@ -37,6 +37,7 @@ local trace_defining = false trackers.register("fonts.defining", function(v local report_afm = logs.reporter("fonts","afm loading") local setmetatableindex = table.setmetatableindex +local derivetable = table.derive local findbinfile = resolvers.findbinfile @@ -54,7 +55,7 @@ local otfenhancers = otf.enhancers local afmfeatures = constructors.newfeatures("afm") local registerafmfeature = afmfeatures.register -afm.version = 1.505 -- incrementing this number one up will force a re-cache +afm.version = 1.507 -- incrementing this number one up will force a re-cache afm.cache = containers.define("fonts", "afm", afm.version, true) afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*) @@ -66,54 +67,55 @@ local overloads = fonts.mappings.overloads local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes --[[ldx-- -<p>We start with the basic reader which we give a name similar to the -built in <l n='tfm'/> and <l n='otf'/> reader.</p> +<p>We start with the basic reader which we give a name similar to the built in <l n='tfm'/> +and <l n='otf'/> reader.</p> --ldx]]-- ---~ Comment FONTIDENTIFIER LMMATHSYMBOLS10 ---~ Comment CODINGSCHEME TEX MATH SYMBOLS ---~ Comment DESIGNSIZE 10.0 pt ---~ Comment CHECKSUM O 4261307036 ---~ Comment SPACE 0 plus 0 minus 0 ---~ Comment QUAD 1000 ---~ Comment EXTRASPACE 0 ---~ Comment NUM 676.508 393.732 443.731 ---~ Comment DENOM 685.951 344.841 ---~ Comment SUP 412.892 362.892 288.889 ---~ Comment SUB 150 247.217 ---~ Comment SUPDROP 386.108 ---~ Comment SUBDROP 50 ---~ Comment DELIM 2390 1010 ---~ Comment AXISHEIGHT 250 +-- Comment FONTIDENTIFIER LMMATHSYMBOLS10 +-- Comment CODINGSCHEME TEX MATH SYMBOLS +-- Comment DESIGNSIZE 10.0 pt +-- Comment CHECKSUM O 4261307036 +-- Comment SPACE 0 plus 0 minus 0 +-- Comment QUAD 1000 +-- Comment EXTRASPACE 0 +-- Comment NUM 676.508 393.732 443.731 +-- Comment DENOM 685.951 344.841 +-- Comment SUP 412.892 362.892 288.889 +-- Comment SUB 150 247.217 +-- Comment SUPDROP 386.108 +-- Comment SUBDROP 50 +-- Comment DELIM 2390 1010 +-- Comment AXISHEIGHT 250 local comment = P("Comment") local spacing = patterns.spacer -- S(" \t")^1 local lineend = patterns.newline -- S("\n\r") -local words = C((1 - lineend)^1) -local number = C((R("09") + S("."))^1) / tonumber * spacing^0 -local data = lpeg.Carg(1) +local words = spacing * C((1 - lineend)^1) +local number = spacing * C((R("09") + S("."))^1) / tonumber * spacing^0 +local data = Carg(1) +local plus = P("plus") * number +local minus = P("minus") * number local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's - comment * spacing * - ( - data * ( - ("CODINGSCHEME" * spacing * words ) / function(fd,a) end + - ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end + - ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end + - ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end + - ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end + - ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end + - ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end + - ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end + - ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end + - ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end + - ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end + - ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end + - ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end + - ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end - ) - + (1-lineend)^0 + comment * spacing * ( + data * ( + ("CODINGSCHEME" * words ) / function(t,a) end + + ("DESIGNSIZE" * number * words ) / function(t,a) t[ 1] = a end + + ("CHECKSUM" * number * words ) / function(t,a) t[ 2] = a end + + ("SPACE" * number * plus * minus ) / function(t,a,b,c) t[ 3], t[ 4], t[ 5] = a, b, c end + + ("QUAD" * number ) / function(t,a) t[ 6] = a end + + ("EXTRASPACE" * number ) / function(t,a) t[ 7] = a end + + ("NUM" * number * number * number ) / function(t,a,b,c) t[ 8], t[ 9], t[10] = a, b, c end + + ("DENOM" * number * number ) / function(t,a,b) t[11], t[12] = a, b end + + ("SUP" * number * number * number ) / function(t,a,b,c) t[13], t[14], t[15] = a, b, c end + + ("SUB" * number * number ) / function(t,a,b) t[16], t[17] = a, b end + + ("SUPDROP" * number ) / function(t,a) t[18] = a end + + ("SUBDROP" * number ) / function(t,a) t[19] = a end + + ("DELIM" * number * number ) / function(t,a,b) t[20], t[21] = a, b end + + ("AXISHEIGHT" * number ) / function(t,a) t[22] = a end ) + + (1-lineend)^0 + ) + (1-comment)^1 )^0 @@ -123,27 +125,47 @@ local function scan_comment(str) return fd end --- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader --- as in now supports afm/pfb loading but it's not too bad to have different methods --- for testing approaches. - -local keys = { } - -function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces - data.metadata.fullname = strip (line) end -function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end -function keys.IsFixedPitch(data,line) data.metadata.monospaced = toboolean(line,true) end -function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end -function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end -function keys.Descender (data,line) data.metadata.descender = tonumber (line) end -function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end -function keys.Comment (data,line) - -- Comment DesignSize 12 (pts) - -- Comment TFM designsize: 12 (in points) - line = lower(line) - local designsize = match(line,"designsize[^%d]*(%d+)") - if designsize then data.metadata.designsize = tonumber(designsize) end -end +-- Comment DesignSize 12 (pts) +-- Comment TFM designsize: 12 (in points) + +local keys = { + + FontName = function(data,line) + data.metadata.fontname = strip(line) -- get rid of spaces + data.metadata.fullname = strip(line) + end, + + ItalicAngle = function(data,line) + data.metadata.italicangle = tonumber(line) + end, + + IsFixedPitch = function(data,line) + data.metadata.monospaced = toboolean(line,true) + end, + + CharWidth = function(data,line) + data.metadata.charwidth = tonumber(line) + end, + + XHeight = function(data,line) + data.metadata.xheight = tonumber(line) + end, + + Descender = function(data,line) + data.metadata.descender = tonumber (line) + end, + + Ascender = function(data,line) + data.metadata.ascender = tonumber (line) + end, + + Comment = function(data,line) + line = lower(line) + local designsize = match(line,"designsize[^%d]*(%d+)") + if designsize then data.metadata.designsize = tonumber(designsize) end + end, + +} local function get_charmetrics(data,charmetrics,vector) local characters = data.characters @@ -202,8 +224,10 @@ local function get_variables(data,fontmetrics) end end --- new (unfinished) pfb loader but i see no differences between --- old and new (one bad vector with old) +--[[ldx-- +<p>We now use a new (unfinished) pfb loader but I see no differences between the old +and new vectors (we actually had one bad vector with the old loader).</p> +--ldx]]-- local get_indexes @@ -353,29 +377,30 @@ local function readafm(filename) -- the final store }, } - afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics) +-- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics) + for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do if trace_loading then report_afm("loading char metrics") end get_charmetrics(data,charmetrics,vector) - return "" - end) - afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs) + break + end + for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do if trace_loading then report_afm("loading kern pairs") end get_kernpairs(data,kernpairs) - return "" - end) - afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics) + break + end + for version, fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do if trace_loading then report_afm("loading variables") end data.afmversion = version get_variables(data,fontmetrics) data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now - return "" - end) + break + end return data else if trace_loading then @@ -391,10 +416,38 @@ ligatures and kern information to the afm derived data. That way we can set them when defining a font.</p> <p>We still keep the loading two phased: first we load the data in a traditional -fashion and later we transform it to sequences.</p> +fashion and later we transform it to sequences. Then we apply some methods also +used in opentype fonts (like <t>tlig</t>).</p> --ldx]]-- -local addkerns, unify, normalize, fixnames, addligatures, addtexligatures +local enhancers = { + -- It's cleaner to implement them after we've seen what we are + -- dealing with. +} + +local steps = { + "unify names", + "add ligatures", + "add extra kerns", + "normalize features", + "fix names", +-- "add tounicode data", +} + +local function applyenhancers(data,filename) + for i=1,#steps do + local step = steps[i] + local enhancer = enhancers[step] + if enhancer then + if trace_loading then + report_afm("applying enhancer %a",step) + end + enhancer(data,filename) + else + report_afm("invalid enhancer %a",step) + end + end +end function afm.load(filename) filename = resolvers.findfile(filename,'afm') or "" @@ -427,29 +480,7 @@ function afm.load(filename) -- data.resources.filename = "unset" -- better than loading the afm file end -- we now have all the data loaded - if trace_loading then - report_afm("unifying %a",filename) - end - unify(data,filename) - if trace_loading then - report_afm("add ligatures") -- there can be missing ones - end - addligatures(data) - if trace_loading then - report_afm("add extra kerns") - end - addkerns(data) - if trace_loading then - report_afm("normalizing") - end - normalize(data) - if trace_loading then - report_afm("fixing names") - end - fixnames(data) - if trace_loading then - report_afm("add tounicode data") - end + applyenhancers(data,filename) -- otfreaders.addunicodetable(data) -- only when not done yet fonts.mappings.addtounicode(data,filename) -- otfreaders.extend(data) @@ -475,14 +506,14 @@ function afm.load(filename) end end return data - else - return nil end end -local uparser = fonts.mappings.makenameparser() +-- we run a more advanced analyzer later on anyway -unify = function(data, filename) +local uparser = fonts.mappings.makenameparser() -- each time + +enhancers["unify names"] = function(data, filename) local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context local unicodes = { } local names = { } @@ -492,7 +523,7 @@ unify = function(data, filename) local code = unicodevector[name] -- or characters.name_to_unicode[name] if not code then code = lpegmatch(uparser,name) - if not code then + if type(code) ~= "number" then code = private private = private + 1 report_afm("assigning private slot %U for unknown glyph name %a",code,name) @@ -538,7 +569,7 @@ end local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } } local noflags = { false, false, false, false } -normalize = function(data) +enhancers["normalize features"] = function(data) local ligatures = setmetatableindex("table") local kerns = setmetatableindex("table") local extrakerns = setmetatableindex("table") @@ -639,7 +670,7 @@ normalize = function(data) data.resources.sequences = sequences end -fixnames = function(data) +enhancers["fix names"] = function(data) for k, v in next, data.descriptions do local n = v.name local r = overloads[n] @@ -686,8 +717,13 @@ local addthem = function(rawdata,ligatures) end end -addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end -addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end +enhancers["add ligatures"] = function(rawdata) + addthem(rawdata,afm.helpdata.ligatures) +end + +-- enhancers["add tex ligatures"] = function(rawdata) +-- addthem(rawdata,afm.helpdata.texligatures) +-- end --[[ldx-- <p>We keep the extra kerns in separate kerning tables so that we can use @@ -701,7 +737,7 @@ them selectively.</p> -- we don't use the character database. (Ok, we can have a context specific -- variant). -addkerns = function(rawdata) -- using shcodes is not robust here +enhancers["add extra kerns"] = function(rawdata) -- using shcodes is not robust here local descriptions = rawdata.descriptions local resources = rawdata.resources local unicodes = resources.unicodes @@ -929,10 +965,9 @@ local function copytotfm(data) end --[[ldx-- -<p>Originally we had features kind of hard coded for <l n='afm'/> -files but since I expect to support more font formats, I decided -to treat this fontformat like any other and handle features in a -more configurable way.</p> +<p>Originally we had features kind of hard coded for <l n='afm'/> files but since I +expect to support more font formats, I decided to treat this fontformat like any +other and handle features in a more configurable way.</p> --ldx]]-- function afm.setfeatures(tfmdata,features) @@ -1046,85 +1081,9 @@ local function read_from_afm(specification) end --[[ldx-- -<p>Here comes the implementation of a few features. We only implement -those that make sense for this format.</p> +<p>We have the usual two modes and related features initializers and processors.</p> --ldx]]-- -local function prepareligatures(tfmdata,ligatures,value) - if value then - local descriptions = tfmdata.descriptions - local hasligatures = false - for unicode, character in next, tfmdata.characters do - local description = descriptions[unicode] - local dligatures = description.ligatures - if dligatures then - local cligatures = character.ligatures - if not cligatures then - cligatures = { } - character.ligatures = cligatures - end - for unicode, ligature in next, dligatures do - cligatures[unicode] = { - char = ligature, - type = 0 - } - end - hasligatures = true - end - end - tfmdata.properties.hasligatures = hasligatures - end -end - -local function preparekerns(tfmdata,kerns,value) - if value then - local rawdata = tfmdata.shared.rawdata - local resources = rawdata.resources - local unicodes = resources.unicodes - local descriptions = tfmdata.descriptions - local haskerns = false - for u, chr in next, tfmdata.characters do - local d = descriptions[u] - local newkerns = d[kerns] - if newkerns then - local kerns = chr.kerns - if not kerns then - kerns = { } - chr.kerns = kerns - end - for k,v in next, newkerns do - local uk = unicodes[k] - if uk then - kerns[uk] = v - end - end - haskerns = true - end - end - tfmdata.properties.haskerns = haskerns - end -end - -local list = { - -- [0x0022] = 0x201D, - [0x0027] = 0x2019, - -- [0x0060] = 0x2018, -} - -local function texreplacements(tfmdata,value) - local descriptions = tfmdata.descriptions - local characters = tfmdata.characters - for k, v in next, list do - characters [k] = characters [v] -- we forget about kerns - descriptions[k] = descriptions[v] -- we forget about kerns - end -end - --- local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end --- local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end --- local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end -local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end - local function setmode(tfmdata,value) if value then tfmdata.properties.mode = lower(value) @@ -1214,7 +1173,7 @@ function readers.pfb(specification,method) -- only called when forced if trace_defining then report_afm("using afm reader for %a",original) end - specification.specification = gsub(original,"%.pfb",".afm") + specification.specification = file.replacesuffix(original,"afm") specification.forced = "afm" return readers.afm(specification,method) end diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua index be9ba8660..a91dac5cf 100644 --- a/tex/context/base/mkiv/font-otc.lua +++ b/tex/context/base/mkiv/font-otc.lua @@ -52,6 +52,10 @@ local noflags = { false, false, false, false } -- beware: shared, maybe we should copy the sequence local function addfeature(data,feature,specifications) + + -- todo: add some validator / check code so that we're more tolerant to + -- user errors + local descriptions = data.descriptions local resources = data.resources local features = resources.features @@ -254,26 +258,30 @@ local function addfeature(data,feature,specifications) local function prepare_pair(list,featuretype) local coverage = { } local cover = coveractions[featuretype] - for code, replacement in next, list do - local unicode = tounicode(code) - local description = descriptions[unicode] - if description and type(replacement) == "table" then - local r = { } - for k, v in next, replacement do - local u = tounicode(k) - if u then - r[u] = v + if cover then + for code, replacement in next, list do + local unicode = tounicode(code) + local description = descriptions[unicode] + if description and type(replacement) == "table" then + local r = { } + for k, v in next, replacement do + local u = tounicode(k) + if u then + r[u] = v + end + end + if next(r) then + cover(coverage,unicode,r) + done = done + 1 + else + skip = skip + 1 end - end - if next(r) then - cover(coverage,unicode,r) - done = done + 1 else skip = skip + 1 end - else - skip = skip + 1 end + else + report_otf("unknown cover type %a",featuretype) end return coverage end @@ -447,7 +455,7 @@ local function addfeature(data,feature,specifications) coverage = prepare_multiple(list,featuretype) elseif featuretype == "kern" then category = "gpos" - format = kern + format = "kern" coverage = prepare_kern(list,featuretype) elseif featuretype == "pair" then category = "gpos" diff --git a/tex/context/base/mkiv/font-otf.lua b/tex/context/base/mkiv/font-otf.lua index cbdc79678..a1730aced 100644 --- a/tex/context/base/mkiv/font-otf.lua +++ b/tex/context/base/mkiv/font-otf.lua @@ -58,7 +58,7 @@ local otf = fonts.handlers.otf otf.glists = { "gsub", "gpos" } -otf.version = 2.824 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 2.825 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otf", otf.version, true) local hashes = fonts.hashes @@ -2961,6 +2961,7 @@ otf.coverup = { multiple = justset, ligature = justset, kern = justset, + pair = justset, chainsubstitution = justset, chainposition = justset, }, diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua index 01342a9be..304b6b989 100644 --- a/tex/context/base/mkiv/font-otl.lua +++ b/tex/context/base/mkiv/font-otl.lua @@ -53,7 +53,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.019 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 3.020 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otl", otf.version, true) local otfreaders = otf.readers diff --git a/tex/context/base/mkiv/font-otn.lua b/tex/context/base/mkiv/font-otn.lua index 1c17e889d..7e701c4b4 100644 --- a/tex/context/base/mkiv/font-otn.lua +++ b/tex/context/base/mkiv/font-otn.lua @@ -3715,6 +3715,9 @@ local function ligature(lookupdata,lookupname,unicode,lookuphash) target.ligature = unicode end +-- this is not ok .. it doesn't work for the old loader with new loader extension +-- specs + local function pair(lookupdata,lookupname,unicode,lookuphash) local target = lookuphash[lookupname] if not target then @@ -3723,7 +3726,9 @@ local function pair(lookupdata,lookupname,unicode,lookuphash) end local others = target[unicode] local paired = lookupdata[1] - if others then + if not paired then + -- something is wrong + elseif others then others[paired] = lookupdata else others = { [paired] = lookupdata } diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua index 3b6d8ea53..bd47e71dd 100644 --- a/tex/context/base/mkiv/font-oup.lua +++ b/tex/context/base/mkiv/font-oup.lua @@ -586,7 +586,8 @@ local function checklookups(fontdata,missing,nofmissing) local done = { } for i, r in next, missing do if r then - local name = descriptions[i].name or f_index(i) + local data = descriptions[i] + local name = data and data.name or f_index(i) if not ignore[name] then done[name] = true end diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua index d3409e01b..95b5a8ac9 100644 --- a/tex/context/base/mkiv/math-noa.lua +++ b/tex/context/base/mkiv/math-noa.lua @@ -1236,10 +1236,15 @@ italics[math_char] = function(pointer,what,n,parent) if not next_noad then if n == 1 then -- only at the outer level .. will become an option (always,endonly,none) if trace_italics then - report_italics("method %a, flagging italic correction between %C and end math",method,correction,char) + report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) end - setattr(pointer,a_mathitalics,101) - setattr(parent,a_mathitalics,101) + if correction > 0 then + correction = correction + 100 + else + correction = correction - 100 + end + setattr(pointer,a_mathitalics,correction) + setattr(parent,a_mathitalics,correction) end end end @@ -1258,6 +1263,8 @@ enable = function() if trace_italics then report_italics("enabling math italics") end + -- we enable math (unless already enabled elsewhere) + typesetters.italics.enablemath() enable = false end diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua index e0649e99b..5ac43ea4a 100644 --- a/tex/context/base/mkiv/node-rul.lua +++ b/tex/context/base/mkiv/node-rul.lua @@ -11,7 +11,6 @@ if not modules then modules = { } end modules ['node-rul'] = { -- -- todo: make robust for layers ... order matters - local attributes, nodes, node = attributes, nodes, node local nuts = nodes.nuts @@ -275,9 +274,13 @@ local data = rules.data -- we implement user rules here as it takes less code this way -local function userrule(t) +local function userrule(t,noattributes) local r = new_userrule(t.width or 0,t.height or 0,t.depth or 0) - setfield(r,"attr",attribs()) + if noattributes == false or noattributes == nil then + -- avoid fuzzy ones + else + setfield(r,"attr",attribs()) + end properties[r] = t return tonode(r) end @@ -289,10 +292,12 @@ rules.ruleactions = ruleactions callback.register("process_rule",function(n,h,v) local n = tonut(n) local p = properties[n] - local i = p.type or "draw" - local a = ruleactions[i] - if a then - a(p,h,v,i,n) + if p then + local i = p.type or "draw" + local a = ruleactions[i] + if a then + a(p,h,v,i,n) + end end end) diff --git a/tex/context/base/mkiv/page-mul.mkiv b/tex/context/base/mkiv/page-mul.mkiv index 631232368..c72057010 100644 --- a/tex/context/base/mkiv/page-mul.mkiv +++ b/tex/context/base/mkiv/page-mul.mkiv @@ -913,10 +913,10 @@ \settrue\c_page_mul_balance_possible % balance indeed \fi \fi - \else - \setfalse\c_page_mul_balance_possible % balancing does not make sense - \fi - \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight + \else + \setfalse\c_page_mul_balance_possible % balancing does not make sense + \fi + \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight \page_mul_balance_try_one \ifinheritcolumns \page_mul_balance_try_two @@ -955,8 +955,7 @@ \d_page_mul_balance_step\spacingfactor\onepoint % rubish \fi \doloop\page_mul_balance_try_one_attempt - \dohandleallcolumns - {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% + \page_mul_balance_try_one_attempt_final \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax \showmessage\m!columns7\empty \else @@ -983,9 +982,44 @@ \exitloop \fi\fi} +% \def\page_mul_balance_try_one_attempt_final +% {\dohandleallcolumns +% {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}} +% +% \def\page_mul_balance_try_one_attempt_step +% {\setbox\b_page_mul_balance_column\vbox +% {\unvcopy\currentcolumnbox +% \unpenalty +% \unskip +% \unpenalty +% \unskip}% maybe better in main splitter +% \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height +% \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column +% \fi} +% +% In mkiv we juggle node lists and we cannot work on copies that easily but in +% practice context hardly uses copies except here. So, the next variant doesn't +% use copies but the original in the final result, for which we need an extra +% split pass. A simple test case is: +% +% \starttext +% \startcolumns +% \inleft{!} x \par x +% \stopcolumns +% \stoptext + +\def\page_mul_balance_try_one_attempt_final % we need this because we want to have the non copied content + {\global\setbox\b_page_mul_preceding_rest_of_page\box\b_page_mul_balance_content + \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target + \dohandlemidcolumns + {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}% + \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target + \dohandleallcolumns + {\global\setbox\currentcolumnbox\vbox{\unvbox\currentcolumnbox}}} + \def\page_mul_balance_try_one_attempt_step {\setbox\b_page_mul_balance_column\vbox - {\unvcopy\currentcolumnbox + {\unvbox\currentcolumnbox % was copy but not needed with the above \unpenalty \unskip \unpenalty diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 6ea8ed23f..bc8c201e7 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex cb96b7185..5260d86f0 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/typo-itc.lua b/tex/context/base/mkiv/typo-itc.lua index cf54187d7..ea8103aad 100644 --- a/tex/context/base/mkiv/typo-itc.lua +++ b/tex/context/base/mkiv/typo-itc.lua @@ -168,7 +168,83 @@ local function correction_glue(glue,n) return g end -function italics.handler(head) +local mathokay = false +local textokay = false +local enablemath = false +local enabletext = false + +local function domath(head,current, done) + current = end_of_math(current) + local next = getnext(current) + if next then + local char, id = isglyph(next) + if char then + -- we can have an old font where italic correction has been applied + -- or a new one where it hasn't been done + local kern = getprev(current) + if kern and getid(kern) == kern_code then + local glyph = getprev(kern) + if glyph and getid(glyph) == glyph_code then + -- [math: <glyph><kern>]<glyph> : we remove the correction when we have + -- punctuation + if is_punctuation[char] then + local a = getattr(glyph,a_mathitalics) + if a and (a < 100 or a > 100) then + if a > 100 then + a = a - 100 + else + a = a + 100 + end + if getfield(next,"height") < 1.25*ex then + if trace_italics then + report_italics("removing italic between math %C and punctuation %C",getchar(glyph),char) + end + setfield(kern,"kern",0) -- or maybe a small value or half the ic + done = true + end + end + end + end + else + local glyph = kern + if glyph and getid(glyph) == glyph_code then + -- [math: <glyph>]<glyph> : we add the correction when we have + -- no punctuation + if not is_punctuation[char] then + local a = getattr(glyph,a_mathitalics) + if a and (a < 100 or a > 100) then + if a > 100 then + a = a - 100 + else + a = a + 100 + end + if trace_italics then + report_italics("adding italic between math %C and non punctuation %C",getchar(glyph),char) + end + insert_node_after(head,glyph,new_correction_kern(a)) + done = true + end + end + end + end + end + end + return current, done +end + +local function mathhandler(head) + local current = tonut(head) + local done = false + while current do + if getid(current) == math_code then + current, done = domath(head,current,done) + end + current = getnext(current) + end + return head, done +end + +local function texthandler(head) local prev = nil local prevchar = nil @@ -398,36 +474,17 @@ function italics.handler(head) end end elseif id == math_code then - current = end_of_math(current) + -- is this still needed ... the current engine implementation has been redone previnserted = nil previtalic = 0 replaceinserted = nil replaceitalic = 0 postinserted = nil postitalic = 0 - local next = getnext(current) - if next then - local char, id = isglyph(next) - if char and is_punctuation[char] then - local kern = getprev(current) - if kern and getid(kern) == kern_code then - local glyph = getprev(kern) - if glyph and getid(glyph) == glyph_code then - local a = getattr(glyph,a_mathitalics) - if a == 101 then - local font = getfont(next) - local ex = exheights[font] - -- we need an extrat punctuation checker: . ; etc - if getfield(next,"height") < 1.25*ex then - if trace_italics then - report_italics("removing italic between math %C and punctuation %C",getchar(glyph),char) - end - setfield(kern,"kern",0) -- or maybe a small value or half the ic - end - end - end - end - end + if mathokay then + current, done = domath(head,current,done) + else + current = end_of_math(current) end else if previtalic ~= 0 then @@ -500,19 +557,49 @@ function italics.handler(head) return head, done end -local enable +function italics.handler(head) + if textokay then + return texthandler(head) + elseif mathokay then + return mathhandler(head) + else + return head, false + end +end + +enabletext = function() + tasks.enableaction("processors","typesetters.italics.handler") + if trace_italics then + report_italics("enabling text/text italics") + end + enabletext = false + textokay = true +end -enable = function() +enablemath = function() tasks.enableaction("processors","typesetters.italics.handler") if trace_italics then - report_italics("enabling text italics") + report_italics("enabling math/text italics") + end + enablemath = false + mathokay = true +end + +function italics.enabletext() + if enabletext then + enabletext() + end +end + +function italics.enablemath() + if enablemath then + enablemath() end - enable = false end function italics.set(n) - if enable then - enable() + if enabletext then + enabletext() end if n == variables.reset then texsetattribute(a_italics,unsetvalue) @@ -540,8 +627,8 @@ local variables = interfaces.variables local settings_to_hash = utilities.parsers.settings_to_hash local function setupitaliccorrection(option) -- no grouping ! - if enable then - enable() + if enabletext then + enabletext() end local options = settings_to_hash(option) local variant = unsetvalue diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua index 40a27dd39..5fc26a354 100644 --- a/tex/context/base/mkiv/typo-lin.lua +++ b/tex/context/base/mkiv/typo-lin.lua @@ -379,11 +379,13 @@ local function setanchor(h_anchor) return new_latelua(f_anchor(h_anchor)) end --- local t_anchor = { x = true, c = true } --- --- local function setanchor(h_anchor) --- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end) --- end +-- local lateluafunction = nodepool.lateluafunction +-- local setposition = job.positions.set +-- local t_anchor = { x = true, c = true } + +-- local function setanchor(h_anchor) +-- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end) +-- end function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area) local line = type(n) ~= "table" and getprop(n,"line") or n diff --git a/tex/context/fonts/mkiv/cambria.lfg b/tex/context/fonts/mkiv/cambria.lfg index 04211009b..a109fc07a 100644 --- a/tex/context/fonts/mkiv/cambria.lfg +++ b/tex/context/fonts/mkiv/cambria.lfg @@ -4,13 +4,13 @@ return { comment = "Goodies that complement cambria.", author = "Hans Hagen", copyright = "ConTeXt development team", - extensions = { - { - name = "kern", -- adds to kerns - type = "pair", - data = { - [0x0153] = { [0x0301] = { false, { -500, 0, 0, 0 } } }, - } - } - } +-- extensions = { +-- { +-- name = "kern", -- adds to kerns +-- type = "pair", +-- data = { +-- [0x0153] = { [0x0301] = { false, { -500, 0, 0, 0 } } }, +-- } +-- } +-- } } diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex f83e7b524..525127f6f 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex 0c981cc83..cc920a21b 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/modules/mkiv/x-ldx.mkiv b/tex/context/modules/mkiv/x-ldx.mkiv index 06163a594..051019ac4 100644 --- a/tex/context/modules/mkiv/x-ldx.mkiv +++ b/tex/context/modules/mkiv/x-ldx.mkiv @@ -93,7 +93,7 @@ \startxmlsetups ldx:code \startpacked \xmlflush{#1}\relax - \scitepacked + \stoppacked \stopxmlsetups \startluacode diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 3e6f1d138..b84893719 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/08/16 17:30:49 +-- merge date : 05/10/16 23:43:55 do -- begin closure to overcome local limits and interference @@ -6414,7 +6414,7 @@ local fonts=fonts or {} local mappings=fonts.mappings or {} fonts.mappings=mappings local allocate=utilities.storage.allocate -local hex=R("AF","09") +local hex=R("AF","af","09") local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end local dec=(R("09")^1)/tonumber @@ -6549,127 +6549,128 @@ function mappings.addtounicode(data,filename,checklookups) end local ns=0 local nl=0 - for unic,glyph in next,descriptions do + for du,glyph in next,descriptions do local name=glyph.name if name then - local index=glyph.index - local r=overloads[name] - if r then - glyph.unicode=r.unicode - elseif not unic or unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then - local unicode=unicodevector[name] or contextvector[name] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - if (not unicode) and usedmap then - local foundindex=lpegmatch(oparser,name) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - else - local reference=cidnames[foundindex] - if reference then - local foundindex=lpegmatch(oparser,reference) - if foundindex then - unicode=cidcodes[foundindex] - if unicode then - glyph.unicode=unicode - ns=ns+1 - end - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,reference) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else + local overload=overloads[name] + if overload then + glyph.unicode=overload.unicode + else + local gu=glyph.unicode + if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==0xFFFF then + local unicode=unicodevector[name] or contextvector[name] + if unicode then + glyph.unicode=unicode + ns=ns+1 + end + if (not unicode) and usedmap then + local foundindex=lpegmatch(oparser,name) + if foundindex then + unicode=cidcodes[foundindex] + if unicode then + glyph.unicode=unicode + ns=ns+1 + else + local reference=cidnames[foundindex] + if reference then + local foundindex=lpegmatch(oparser,reference) + if foundindex then + unicode=cidcodes[foundindex] + if unicode then + glyph.unicode=unicode ns=ns+1 - unicode=foundcodes + end + end + if not unicode or unicode=="" then + local foundcodes,multiple=lpegmatch(uparser,reference) + if foundcodes then + glyph.unicode=foundcodes + if multiple then + nl=nl+1 + unicode=true + else + ns=ns+1 + unicode=foundcodes + end end end end end end end - end - if not unicode or unicode=="" then - local split=lpegmatch(namesplitter,name) - local nsplit=split and #split or 0 - if nsplit==0 then - elseif nsplit==1 then - local base=split[1] - local u=unicodes[base] or unicodevector[base] or contextvector[name] - if not u then - elseif type(u)=="table" then - if u[1]<private then - unicode=u - glyph.unicode=unicode - end - elseif u<private then - unicode=u - glyph.unicode=unicode - end - else - local t,n={},0 - for l=1,nsplit do - local base=split[l] + if not unicode or unicode=="" then + local split=lpegmatch(namesplitter,name) + local nsplit=split and #split or 0 + if nsplit==0 then + elseif nsplit==1 then + local base=split[1] local u=unicodes[base] or unicodevector[base] or contextvector[name] if not u then - break elseif type(u)=="table" then - if u[1]>=private then - break + if u[1]<private then + unicode=u + glyph.unicode=unicode end - n=n+1 - t[n]=u[1] - else - if u>=private then + elseif u<private then + unicode=u + glyph.unicode=unicode + end + else + local t,n={},0 + for l=1,nsplit do + local base=split[l] + local u=unicodes[base] or unicodevector[base] or contextvector[name] + if not u then break + elseif type(u)=="table" then + if u[1]>=private then + break + end + n=n+1 + t[n]=u[1] + else + if u>=private then + break + end + n=n+1 + t[n]=u end - n=n+1 - t[n]=u + end + if n>0 then + if n==1 then + unicode=t[1] + else + unicode=t + end + glyph.unicode=unicode end end - if n>0 then - if n==1 then - unicode=t[1] + nl=nl+1 + end + if not unicode or unicode=="" then + local foundcodes,multiple=lpegmatch(uparser,name) + if foundcodes then + glyph.unicode=foundcodes + if multiple then + nl=nl+1 + unicode=true else - unicode=t + ns=ns+1 + unicode=foundcodes end - glyph.unicode=unicode end end - nl=nl+1 - end - if not unicode or unicode=="" then - local foundcodes,multiple=lpegmatch(uparser,name) - if foundcodes then - glyph.unicode=foundcodes - if multiple then - nl=nl+1 - unicode=true - else - ns=ns+1 - unicode=foundcodes - end + local r=overloads[unicode] + if r then + unicode=r.unicode + glyph.unicode=unicode + end + if not unicode then + missing[du]=true + nofmissing=nofmissing+1 end - end - local r=overloads[unicode] - if r then - unicode=r.unicode - glyph.unicode=unicode - end - if not unicode then - missing[unic]=true - nofmissing=nofmissing+1 end end - else end end if type(checklookups)=="function" then @@ -13052,7 +13053,8 @@ local function checklookups(fontdata,missing,nofmissing) local done={} for i,r in next,missing do if r then - local name=descriptions[i].name or f_index(i) + local data=descriptions[i] + local name=data and data.name or f_index(i) if not ignore[name] then done[name]=true end @@ -14514,7 +14516,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.019 +otf.version=3.020 otf.cache=containers.define("fonts","otl",otf.version,true) local otfreaders=otf.readers local hashes=fonts.hashes @@ -22260,19 +22262,20 @@ if not modules then modules={} end modules ['font-one']={ license="see context related readme files" } local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers -local next,type,tonumber=next,type,tonumber +local next,type,tonumber,rawget=next,type,tonumber,rawget local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find local char,byte,sub=string.char,string.byte,string.sub local abs=math.abs local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,lpegmatch,patterns=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.match,lpeg.patterns -local derivetable=table.derive +local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg +local lpegmatch,patterns=lpeg.match,lpeg.patterns local trace_features=false trackers.register("afm.features",function(v) trace_features=v end) 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 trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) local report_afm=logs.reporter("fonts","afm loading") local setmetatableindex=table.setmetatableindex +local derivetable=table.derive local findbinfile=resolvers.findbinfile local definers=fonts.definers local readers=fonts.readers @@ -22284,7 +22287,7 @@ local otfreaders=otf.readers local otfenhancers=otf.enhancers local afmfeatures=constructors.newfeatures("afm") local registerafmfeature=afmfeatures.register -afm.version=1.505 +afm.version=1.507 afm.cache=containers.define("fonts","afm",afm.version,true) afm.autoprefixed=true afm.helpdata={} @@ -22294,35 +22297,52 @@ local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes local comment=P("Comment") local spacing=patterns.spacer local lineend=patterns.newline -local words=C((1-lineend)^1) -local number=C((R("09")+S("."))^1)/tonumber*spacing^0 -local data=lpeg.Carg(1) +local words=spacing*C((1-lineend)^1) +local number=spacing*C((R("09")+S("."))^1)/tonumber*spacing^0 +local data=Carg(1) +local plus=P("plus")*number +local minus=P("minus")*number local pattern=( comment*spacing*( - data*( - ("CODINGSCHEME"*spacing*words )/function(fd,a) end+("DESIGNSIZE"*spacing*number*words )/function(fd,a) fd[ 1]=a end+("CHECKSUM"*spacing*number*words )/function(fd,a) fd[ 2]=a end+("SPACE"*spacing*number*"plus"*number*"minus"*number)/function(fd,a,b,c) fd[ 3],fd[ 4],fd[ 5]=a,b,c end+("QUAD"*spacing*number )/function(fd,a) fd[ 6]=a end+("EXTRASPACE"*spacing*number )/function(fd,a) fd[ 7]=a end+("NUM"*spacing*number*number*number )/function(fd,a,b,c) fd[ 8],fd[ 9],fd[10]=a,b,c end+("DENOM"*spacing*number*number )/function(fd,a,b ) fd[11],fd[12]=a,b end+("SUP"*spacing*number*number*number )/function(fd,a,b,c) fd[13],fd[14],fd[15]=a,b,c end+("SUB"*spacing*number*number )/function(fd,a,b) fd[16],fd[17]=a,b end+("SUPDROP"*spacing*number )/function(fd,a) fd[18]=a end+("SUBDROP"*spacing*number )/function(fd,a) fd[19]=a end+("DELIM"*spacing*number*number )/function(fd,a,b) fd[20],fd[21]=a,b end+("AXISHEIGHT"*spacing*number )/function(fd,a) fd[22]=a end - )+(1-lineend)^0 - )+(1-comment)^1 + data*( + ("CODINGSCHEME"*words )/function(t,a) end+("DESIGNSIZE"*number*words )/function(t,a) t[ 1]=a end+("CHECKSUM"*number*words )/function(t,a) t[ 2]=a end+("SPACE"*number*plus*minus )/function(t,a,b,c) t[ 3],t[ 4],t[ 5]=a,b,c end+("QUAD"*number )/function(t,a) t[ 6]=a end+("EXTRASPACE"*number )/function(t,a) t[ 7]=a end+("NUM"*number*number*number )/function(t,a,b,c) t[ 8],t[ 9],t[10]=a,b,c end+("DENOM"*number*number )/function(t,a,b) t[11],t[12]=a,b end+("SUP"*number*number*number )/function(t,a,b,c) t[13],t[14],t[15]=a,b,c end+("SUB"*number*number )/function(t,a,b) t[16],t[17]=a,b end+("SUPDROP"*number )/function(t,a) t[18]=a end+("SUBDROP"*number )/function(t,a) t[19]=a end+("DELIM"*number*number )/function(t,a,b) t[20],t[21]=a,b end+("AXISHEIGHT"*number )/function(t,a) t[22]=a end + )+(1-lineend)^0 + )+(1-comment)^1 )^0 local function scan_comment(str) local fd={} lpegmatch(pattern,str,1,fd) return fd end -local keys={} -function keys.FontName (data,line) data.metadata.fontname=strip (line) - data.metadata.fullname=strip (line) end -function keys.ItalicAngle (data,line) data.metadata.italicangle=tonumber (line) end -function keys.IsFixedPitch(data,line) data.metadata.monospaced=toboolean(line,true) end -function keys.CharWidth (data,line) data.metadata.charwidth=tonumber (line) end -function keys.XHeight (data,line) data.metadata.xheight=tonumber (line) end -function keys.Descender (data,line) data.metadata.descender=tonumber (line) end -function keys.Ascender (data,line) data.metadata.ascender=tonumber (line) end -function keys.Comment (data,line) - line=lower(line) - local designsize=match(line,"designsize[^%d]*(%d+)") - if designsize then data.metadata.designsize=tonumber(designsize) end -end +local keys={ + FontName=function(data,line) + data.metadata.fontname=strip(line) + data.metadata.fullname=strip(line) + end, + ItalicAngle=function(data,line) + data.metadata.italicangle=tonumber(line) + end, + IsFixedPitch=function(data,line) + data.metadata.monospaced=toboolean(line,true) + end, + CharWidth=function(data,line) + data.metadata.charwidth=tonumber(line) + end, + XHeight=function(data,line) + data.metadata.xheight=tonumber(line) + end, + Descender=function(data,line) + data.metadata.descender=tonumber (line) + end, + Ascender=function(data,line) + data.metadata.ascender=tonumber (line) + end, + Comment=function(data,line) + line=lower(line) + local designsize=match(line,"designsize[^%d]*(%d+)") + if designsize then data.metadata.designsize=tonumber(designsize) end + end, +} local function get_charmetrics(data,charmetrics,vector) local characters=data.characters local chr,ind={},0 @@ -22483,29 +22503,29 @@ local function readafm(filename) descriptions={ }, } - afmblob=gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics",function(charmetrics) + for charmetrics in gmatch(afmblob,"StartCharMetrics(.-)EndCharMetrics") do if trace_loading then report_afm("loading char metrics") end get_charmetrics(data,charmetrics,vector) - return "" - end) - afmblob=gsub(afmblob,"StartKernPairs(.-)EndKernPairs",function(kernpairs) + break + end + for kernpairs in gmatch(afmblob,"StartKernPairs(.-)EndKernPairs") do if trace_loading then report_afm("loading kern pairs") end get_kernpairs(data,kernpairs) - return "" - end) - afmblob=gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics",function(version,fontmetrics) + break + end + for version,fontmetrics in gmatch(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics") do if trace_loading then report_afm("loading variables") end data.afmversion=version get_variables(data,fontmetrics) data.fontdimens=scan_comment(fontmetrics) - return "" - end) + break + end return data else if trace_loading then @@ -22514,7 +22534,29 @@ local function readafm(filename) return nil end end -local addkerns,unify,normalize,fixnames,addligatures,addtexligatures +local enhancers={ +} +local steps={ + "unify names", + "add ligatures", + "add extra kerns", + "normalize features", + "fix names", +} +local function applyenhancers(data,filename) + for i=1,#steps do + local step=steps[i] + local enhancer=enhancers[step] + if enhancer then + if trace_loading then + report_afm("applying enhancer %a",step) + end + enhancer(data,filename) + else + report_afm("invalid enhancer %a",step) + end + end +end function afm.load(filename) filename=resolvers.findfile(filename,'afm') or "" if filename~="" and not fonts.names.ignoredfile(filename) then @@ -22543,29 +22585,7 @@ function afm.load(filename) elseif trace_loading then report_afm("no pfb file for %a",filename) end - if trace_loading then - report_afm("unifying %a",filename) - end - unify(data,filename) - if trace_loading then - report_afm("add ligatures") - end - addligatures(data) - if trace_loading then - report_afm("add extra kerns") - end - addkerns(data) - if trace_loading then - report_afm("normalizing") - end - normalize(data) - if trace_loading then - report_afm("fixing names") - end - fixnames(data) - if trace_loading then - report_afm("add tounicode data") - end + applyenhancers(data,filename) fonts.mappings.addtounicode(data,filename) otfreaders.pack(data) data.size=size @@ -22587,12 +22607,10 @@ function afm.load(filename) end end return data - else - return nil end end -local uparser=fonts.mappings.makenameparser() -unify=function(data,filename) +local uparser=fonts.mappings.makenameparser() +enhancers["unify names"]=function(data,filename) local unicodevector=fonts.encodings.agl.unicodes local unicodes={} local names={} @@ -22602,7 +22620,7 @@ unify=function(data,filename) local code=unicodevector[name] if not code then code=lpegmatch(uparser,name) - if not code then + if type(code)~="number" then code=private private=private+1 report_afm("assigning private slot %U for unknown glyph name %a",code,name) @@ -22644,7 +22662,7 @@ unify=function(data,filename) end local everywhere={ ["*"]={ ["*"]=true } } local noflags={ false,false,false,false } -normalize=function(data) +enhancers["normalize features"]=function(data) local ligatures=setmetatableindex("table") local kerns=setmetatableindex("table") local extrakerns=setmetatableindex("table") @@ -22742,7 +22760,7 @@ normalize=function(data) data.resources.features=features data.resources.sequences=sequences end -fixnames=function(data) +enhancers["fix names"]=function(data) for k,v in next,data.descriptions do local n=v.name local r=overloads[n] @@ -22781,9 +22799,10 @@ local addthem=function(rawdata,ligatures) end end end -addligatures=function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end -addtexligatures=function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end -addkerns=function(rawdata) +enhancers["add ligatures"]=function(rawdata) + addthem(rawdata,afm.helpdata.ligatures) +end +enhancers["add extra kerns"]=function(rawdata) local descriptions=rawdata.descriptions local resources=rawdata.resources local unicodes=resources.unicodes @@ -23083,71 +23102,6 @@ local function read_from_afm(specification) end return tfmdata end -local function prepareligatures(tfmdata,ligatures,value) - if value then - local descriptions=tfmdata.descriptions - local hasligatures=false - for unicode,character in next,tfmdata.characters do - local description=descriptions[unicode] - local dligatures=description.ligatures - if dligatures then - local cligatures=character.ligatures - if not cligatures then - cligatures={} - character.ligatures=cligatures - end - for unicode,ligature in next,dligatures do - cligatures[unicode]={ - char=ligature, - type=0 - } - end - hasligatures=true - end - end - tfmdata.properties.hasligatures=hasligatures - end -end -local function preparekerns(tfmdata,kerns,value) - if value then - local rawdata=tfmdata.shared.rawdata - local resources=rawdata.resources - local unicodes=resources.unicodes - local descriptions=tfmdata.descriptions - local haskerns=false - for u,chr in next,tfmdata.characters do - local d=descriptions[u] - local newkerns=d[kerns] - if newkerns then - local kerns=chr.kerns - if not kerns then - kerns={} - chr.kerns=kerns - end - for k,v in next,newkerns do - local uk=unicodes[k] - if uk then - kerns[uk]=v - end - end - haskerns=true - end - end - tfmdata.properties.haskerns=haskerns - end -end -local list={ - [0x0027]=0x2019, -} -local function texreplacements(tfmdata,value) - local descriptions=tfmdata.descriptions - local characters=tfmdata.characters - for k,v in next,list do - characters [k]=characters [v] - descriptions[k]=descriptions[v] - end -end -local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns',value) end local function setmode(tfmdata,value) if value then tfmdata.properties.mode=lower(value) @@ -23228,7 +23182,7 @@ function readers.pfb(specification,method) if trace_defining then report_afm("using afm reader for %a",original) end - specification.specification=gsub(original,"%.pfb",".afm") + specification.specification=file.replacesuffix(original,"afm") specification.forced="afm" return readers.afm(specification,method) end |