summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2013-10-05 00:40:31 +0300
committerMarius <mariausol@gmail.com>2013-10-05 00:40:31 +0300
commit3b2e97139b40df9c0308de41fb619cfad7dc6f18 (patch)
treef85782e0609559dbe29232b51a15612b2a8e58ec
parenta90bcf0dcd9265b64b65b1f874b39f4c75553137 (diff)
downloadcontext-3b2e97139b40df9c0308de41fb619cfad7dc6f18.tar.gz
beta 2013.10.04 23:41
-rw-r--r--metapost/context/base/mp-mlib.mpiv4
-rw-r--r--tex/context/base/chem-str.mkiv41
-rw-r--r--tex/context/base/cont-log.mkiv13
-rw-r--r--tex/context/base/cont-new.mkiv2
-rw-r--r--tex/context/base/context-version.pdfbin4105 -> 4112 bytes
-rw-r--r--tex/context/base/context.mkiv32
-rw-r--r--tex/context/base/font-ctx.lua47
-rw-r--r--tex/context/base/font-fea.mkvi10
-rw-r--r--tex/context/base/font-gds.lua52
-rw-r--r--tex/context/base/font-hsh.lua13
-rw-r--r--tex/context/base/font-otn.lua265
-rw-r--r--tex/context/base/font-pre.mkiv17
-rw-r--r--tex/context/base/mult-def.mkiv1
-rw-r--r--tex/context/base/node-fnt.lua19
-rw-r--r--tex/context/base/node-tra.lua17
-rw-r--r--tex/context/base/phys-dim.lua38
-rw-r--r--tex/context/base/s-fonts-vectors.lua4
-rw-r--r--tex/context/base/spac-cha.mkiv191
-rw-r--r--tex/context/base/status-files.pdfbin24732 -> 24707 bytes
-rw-r--r--tex/context/base/status-lua.log2
-rw-r--r--tex/context/base/status-mkiv.lua18
-rw-r--r--tex/context/base/tabl-ntb.mkiv37
-rw-r--r--tex/context/base/tabl-tbl.mkiv35
-rw-r--r--tex/context/base/task-ini.lua2
-rw-r--r--tex/context/base/trac-vis.lua2
-rw-r--r--tex/context/base/typo-krn.lua64
-rw-r--r--tex/context/base/typo-krn.mkiv54
-rw-r--r--tex/context/base/typo-tal.lua265
-rw-r--r--tex/context/base/typo-tal.mkiv112
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua196
30 files changed, 1104 insertions, 449 deletions
diff --git a/metapost/context/base/mp-mlib.mpiv b/metapost/context/base/mp-mlib.mpiv
index 088c856a7..12608d450 100644
--- a/metapost/context/base/mp-mlib.mpiv
+++ b/metapost/context/base/mp-mlib.mpiv
@@ -822,11 +822,11 @@ vardef mfun_cmykcolor_to_string(expr c) =
enddef ;
vardef mfun_path_to_string(expr p) =
- mfun_point_to_string(value,1) for i=2 upto length(value) : & " " & mfun_point_to_string(value,i) endfor
+ mfun_point_to_string(p,1) for i=2 upto length(p) : & " " & mfun_point_to_string(p,i) endfor
enddef ;
vardef mfun_boolean_to_string(expr b) =
- if value : "true" else : "false" fi
+ if b : "true" else : "false" fi
enddef ;
def passvariable(expr key, value) =
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
index 9c31a3c14..d9ec1842b 100644
--- a/tex/context/base/chem-str.mkiv
+++ b/tex/context/base/chem-str.mkiv
@@ -317,16 +317,21 @@
% special macros (probably needs some more work)
-\let\chem_box_visual\ruledhbox
-\let\chem_box_visual\hbox
-\let\chem_box_normal\hbox
+\let\chem_box_normal_yes\hbox
+\let\chem_box_visual_yes\hbox
+\let\chem_box_visual_nop\relax
+
+\installtextracker
+ {chemistry.boxes}
+ {\let\chem_box_visual_yes\ruledhbox \let\chem_box_visual_nop\ruledhbox}
+ {\let\chem_box_visual_yes\hbox \let\chem_box_visual_nop\relax }
\def\chem_top_construct#1#2#3#4%
{\hbox\bgroup
\setstrut
- \setbox\scratchboxone\chem_box_visual{\strut#3}%
- \setbox\scratchboxtwo\chem_box_visual{\strut\molecule{#4}}%
- \setbox\scratchboxone\chem_box_normal{\raise\dimexpr\dp\scratchboxone+\ht\scratchboxtwo\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\raise\dimexpr\dp\scratchboxone+\ht\scratchboxtwo\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
\smashbox\scratchboxone
\box\scratchboxone
\box\scratchboxtwo
@@ -335,9 +340,9 @@
\def\chem_bottom_construct#1#2#3#4%
{\hbox\bgroup
\setstrut
- \setbox\scratchboxone\chem_box_visual{\strut#3}%
- \setbox\scratchboxtwo\chem_box_visual{\strut\molecule{#4}}%
- \setbox\scratchboxone\chem_box_normal{\lower\dimexpr\dp\scratchboxtwo+\ht\scratchboxone\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
+ \setbox\scratchboxone\chem_box_visual_yes{\strut#3}%
+ \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}%
+ \setbox\scratchboxone\chem_box_normal_yes{\lower\dimexpr\dp\scratchboxtwo+\ht\scratchboxone\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}%
\smashbox\scratchboxone
\box\scratchboxone
\box\scratchboxtwo
@@ -346,15 +351,15 @@
\unexpanded\def\chemicalleft#1#2% redundant boxes thanks to visual
{\hbox\bgroup
\setstrut
- \llap{\chem_box_visual{\strut#1}}%
- \chem_box_visual{\strut#2}%
+ \llap{\chem_box_visual_nop{\strut#1}}%
+ \chem_box_visual_nop{\strut#2}%
\egroup}
\unexpanded\def\chemicalright#1#2% redundant boxes thanks to visual
{\hbox\bgroup
\setstrut
- \chem_box_visual{\strut#2}%
- \rlap{\chem_box_visual{\strut#1}}%
+ \chem_box_visual_yes{\strut#2}%
+ \rlap{\chem_box_visual_nop{\strut#1}}%
\egroup}
\unexpanded\def\chemicaltop {\chem_top_construct \hss \hss }
@@ -390,7 +395,7 @@
{\dontleavehmode
\begingroup
\usechemicalstyleandcolor\c!style\c!color
- \chem_box_visual to \fontcharwd\font`C\bgroup
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
\setstrut\strut
#1\molecule{#3}#2%
\egroup
@@ -401,7 +406,7 @@
\begingroup
\scratchcounter\normalmathstyle
\usechemicalstyleandcolor\c!style\c!color
- \chem_box_visual to \fontcharwd\font`C\bgroup
+ \chem_box_visual_yes to \fontcharwd\font`C\bgroup
\setstrut\strut
#1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2%
\egroup
@@ -602,6 +607,9 @@
\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow
\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow
\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow
+\definechemicalsymbol[d:single] [\chemicalbondrule]
+\definechemicalsymbol[d:double] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[d:triple] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok
\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok
@@ -611,6 +619,9 @@
\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}]
\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}]
\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}]
+\definechemicalsymbol[d:SINGLE] [{\chemicalsymbol[d:single]}]
+\definechemicalsymbol[d:DOUBLE] [{\chemicalsymbol[d:double]}]
+\definechemicalsymbol[d:TRIPLE] [{\chemicalsymbol[d:triple]}]
\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}]
\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}]
diff --git a/tex/context/base/cont-log.mkiv b/tex/context/base/cont-log.mkiv
index 5d4133143..99e08450b 100644
--- a/tex/context/base/cont-log.mkiv
+++ b/tex/context/base/cont-log.mkiv
@@ -126,11 +126,16 @@
\setMFPfont META\syst_logos_meta_hyphen FONT%
\endgroup}
+% \unexpanded\def\MetaPost
+% {\dontleavehmode
+% \begingroup
+% \setMFPfont META\syst_logos_meta_hyphen POST%
+% \endgroup}
+%
+% As decided on the ConText Meeting 2013 the logo has been simplified:
+
\unexpanded\def\MetaPost
- {\dontleavehmode
- \begingroup
- \setMFPfont META\syst_logos_meta_hyphen POST%
- \endgroup}
+ {MetaPost}
\unexpanded\def\MetaFun
{MetaFun}
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index c1008d722..d16bba5da 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2013.10.01 20:08}
+\newcontextversion{2013.10.04 23:41}
%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/context-version.pdf b/tex/context/base/context-version.pdf
index e62eb1541..3e1cf4ec0 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 674f8a2bf..78e7c73d3 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2013.10.01 20:08}
+\edef\contextversion{2013.10.04 23:41}
\edef\contextkind {beta}
%D For those who want to use this:
@@ -162,7 +162,7 @@
\loadmarkfile{supp-ran}
\loadmarkfile{supp-mat}
-\loadmarkfile{spac-cha}
+%loadmarkfile{spac-cha} % obsolete
%loadmarkfile{supp-num} % obsolete
\loadmarkfile{typo-ini}
@@ -324,19 +324,6 @@
\loadmarkfile{strc-bkm} % bookmarks
-\loadmarkfile{tabl-com}
-\loadmarkfile{tabl-pln}
-
-\loadmarkfile{tabl-tab} % thrd-tab stripped and merged
-
-\loadmarkfile{tabl-tbl}
-\loadmarkfile{tabl-ntb}
-\loadmarkfile{tabl-nte}
-\loadmarkfile{tabl-ltb}
-\loadmarkfile{tabl-tsp}
-\loadmkvifile{tabl-xtb}
-\loadmarkfile{tabl-mis}
-
\loadmarkfile{java-ini}
\loadmkvifile{scrn-fld}
@@ -364,6 +351,21 @@
\loadmkvifile{font-aux}
\loadmkvifile{font-sel}
+\loadmarkfile{typo-tal}
+
+\loadmarkfile{tabl-com}
+\loadmarkfile{tabl-pln}
+
+\loadmarkfile{tabl-tab} % thrd-tab stripped and merged
+
+\loadmarkfile{tabl-tbl}
+\loadmarkfile{tabl-ntb}
+\loadmarkfile{tabl-nte}
+\loadmarkfile{tabl-ltb}
+\loadmarkfile{tabl-tsp}
+\loadmkvifile{tabl-xtb}
+\loadmarkfile{tabl-mis}
+
\loadmarkfile{typo-lan}
\loadmarkfile{lxml-css}
diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua
index feefac338..6c3402683 100644
--- a/tex/context/base/font-ctx.lua
+++ b/tex/context/base/font-ctx.lua
@@ -34,6 +34,7 @@ local trace_designsize = false trackers.register("fonts.designsize", functio
local trace_usage = false trackers.register("fonts.usage", function(v) trace_usage = v end)
local trace_mapfiles = false trackers.register("fonts.mapfiles", function(v) trace_mapfiles = v end)
local trace_automode = false trackers.register("fonts.automode", function(v) trace_automode = v end)
+local trace_merge = false trackers.register("fonts.merge", function(v) trace_merge = v end)
local report_features = logs.reporter("fonts","features")
local report_cummulative = logs.reporter("fonts","cummulative")
@@ -122,7 +123,11 @@ end
-- this will move elsewhere ...
-utilities.strings.formatters.add(formatters,"font:name", [["'"..file.basename(%s.properties.name).."'"]])
+function fonts.helpers.name(tfmdata)
+ return file.basename(type(tfmdata) == "number" and properties[tfmdata].name or tfmdata.properties.name)
+end
+
+utilities.strings.formatters.add(formatters,"font:name", [["'"..fonts.helpers.name(%s).."'"]])
utilities.strings.formatters.add(formatters,"font:features",[["'"..table.sequenced(%s," ",true).."'"]])
-- ... like font-sfm or so
@@ -165,10 +170,24 @@ commands.resetnullfont = definers.resetnullfont
-- so we never enter the loop then; we can store the defaults in the tma
-- file (features.gpos.mkmk = 1 etc)
-local needsnodemode = {
- gpos_mark2mark = true,
- gpos_mark2base = true,
- gpos_mark2ligature = true,
+local needsnodemode = { -- we will have node mode by default anyway
+ -- gsub_single = true,
+ gsub_multiple = true,
+ -- gsub_alternate = true,
+ -- gsub_ligature = true,
+ gsub_context = true,
+ gsub_contextchain = true,
+ gsub_reversecontextchain = true,
+ -- chainsub = true,
+ -- reversesub = true,
+ gpos_mark2base = true,
+ gpos_mark2ligature = true,
+ gpos_mark2mark = true,
+ gpos_cursive = true,
+ -- gpos_single = true,
+ -- gpos_pair = true,
+ gpos_context = true,
+ gpos_contextchain = true,
}
otftables.scripts.auto = "automatic fallback to latn when no dflt present"
@@ -206,6 +225,8 @@ local function checkedscript(tfmdata,resources,features)
return script
end
+-- basemode combined with dynamics is somewhat tricky
+
local function checkedmode(tfmdata,resources,features)
local sequences = resources.sequences
if sequences and #sequences > 0 then
@@ -248,6 +269,9 @@ local function checkedmode(tfmdata,resources,features)
end
end
end
+ if trace_automode then
+ report_defining("forcing mode base, font %!font:name!",tfmdata)
+ end
features.mode = "base" -- new, or is this wrong?
return "base"
end
@@ -548,6 +572,9 @@ local function mergecontextfeatures(currentname,extraname,how,mergedname) -- str
for k, v in next, extra do
mergedfeatures[k] = v
end
+ if trace_merge then
+ report_features("merge %a, method %a, current %|T, extra %|T, result %|T",mergedname,"add",current or { },extra,mergedfeatures)
+ end
elseif how == "-" then
if current then
for k, v in next, current do
@@ -560,10 +587,16 @@ local function mergecontextfeatures(currentname,extraname,how,mergedname) -- str
mergedfeatures[k] = false
end
end
+ if trace_merge then
+ report_features("merge %a, method %a, current %|T, extra %|T, result %|T",mergedname,"subtract",current or { },extra,mergedfeatures)
+ end
else -- =
for k, v in next, extra do
mergedfeatures[k] = v
end
+ if trace_merge then
+ report_features("merge %a, method %a, result %|T",mergedname,"replace",mergedfeatures)
+ end
end
local number = #numbers + 1
mergedfeatures.number = number
@@ -1001,7 +1034,7 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
-- resolved (when designsize is used):
local size = fontdata[tfmdata].parameters.size or 0
setsomefontsize(size .. "sp")
-texsetcount("scaledfontsize",size)
+ texsetcount("scaledfontsize",size)
lastfontid = tfmdata
else
-- setting the extra characters will move elsewhere
@@ -1028,7 +1061,7 @@ texsetcount("scaledfontsize",size)
-- resolved (when designsize is used):
local size = tfmdata.parameters.size or 655360
setsomefontsize(size .. "sp")
-texsetcount("scaledfontsize",size)
+ texsetcount("scaledfontsize",size)
lastfontid = id
end
if trace_defining then
diff --git a/tex/context/base/font-fea.mkvi b/tex/context/base/font-fea.mkvi
index c1e051621..777c6e3ca 100644
--- a/tex/context/base/font-fea.mkvi
+++ b/tex/context/base/font-fea.mkvi
@@ -164,7 +164,7 @@
\let\doaddfeature \font_feature_add_nop % low level faster ones
\let\dosubtractfeature \font_feature_subtract_nop
\let\doreplacefeature \font_feature_replace_nop
-\let\doreserandaddfeature\font_feature_reset_add_nop
+\let\doresetandaddfeature\font_feature_reset_add_nop
\unexpanded\def\font_feature_add
{\ifnum\c_font_feature_state=\plusone
@@ -330,4 +330,12 @@
\ctxcommand{registerlanguagefeatures()}
+% also new
+
+\unexpanded\def\useaddfontfeatureparameter#1% faster local variant
+ {\edef\m_font_feature_asked{#1\c!features}%
+ \ifx\m_font_feature_asked\empty\else
+ \font_feature_add
+ \fi}
+
\protect \endinput
diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua
index 284714261..7f8bb91d1 100644
--- a/tex/context/base/font-gds.lua
+++ b/tex/context/base/font-gds.lua
@@ -833,28 +833,33 @@ registerotffeature {
}
}
--- kern hackery
+-- kern hackery:
+--
+-- yes : use goodies table
+-- auto : assume features to be set (often ccmp only)
-local function setkeptligatures(tfmdata,scheme)
- local goodies = tfmdata.goodies
- if goodies then
- for i=1,#goodies do
- local g = goodies[i]
- local letterspacing = g.letterspacing
- if letterspacing then
- local keptligatures = letterspacing.keptligatures
- if keptligatures then
- local unicodes = tfmdata.resources.unicodes
- local hash = { }
- for k, v in next, keptligatures do
- local u = unicodes[k]
- if u then
- hash[u] = true
- else
- -- error: unknown name
+local function setkeepligatures(tfmdata,value)
+ if not tfmdata.properties.keptligatures then
+ local goodies = tfmdata.goodies
+ if goodies then
+ for i=1,#goodies do
+ local g = goodies[i]
+ local letterspacing = g.letterspacing
+ if letterspacing then
+ local keptligatures = letterspacing.keptligatures
+ if keptligatures then
+ local unicodes = tfmdata.resources.unicodes
+ local hash = { }
+ for k, v in next, keptligatures do
+ local u = unicodes[k]
+ if u then
+ hash[u] = true
+ else
+ -- error: unknown name
+ end
end
+ tfmdata.properties.keptligatures = hash
end
- tfmdata.properties.keptligatures = hash
end
end
end
@@ -862,11 +867,10 @@ local function setkeptligatures(tfmdata,scheme)
end
registerotffeature {
- name = "keptligatures",
- description = "kept ligatures in letterspacing",
- default = true,
+ name = "keepligatures",
+ description = "keep ligatures in letterspacing",
initializers = {
- base = setkeptligatures,
- node = setkeptligatures,
+ base = setkeepligatures,
+ node = setkeepligatures,
}
}
diff --git a/tex/context/base/font-hsh.lua b/tex/context/base/font-hsh.lua
index a18f78cab..773cc2b69 100644
--- a/tex/context/base/font-hsh.lua
+++ b/tex/context/base/font-hsh.lua
@@ -29,6 +29,7 @@ local spaces = hashes.spaces or allocate()
local quads = hashes.quads or allocate() -- maybe also spacedata
local xheights = hashes.xheights or allocate()
local csnames = hashes.csnames or allocate() -- namedata
+local features = hashes.features or allocate()
local marks = hashes.marks or allocate()
local italics = hashes.italics or allocate()
local lastmathids = hashes.lastmathids or allocate()
@@ -44,6 +45,7 @@ hashes.spaces = spaces
hashes.quads = quads hashes.emwidths = quads
hashes.xheights = xheights hashes.exheights = xheights
hashes.csnames = csnames
+hashes.features = features
hashes.marks = marks
hashes.italics = italics
hashes.lastmathids = lastmathids
@@ -138,6 +140,17 @@ setmetatableindex(resources, function(t,k)
end
end)
+setmetatableindex(features, function(t,k)
+ if k == true then
+ return features[currentfont()]
+ else
+ local shared = identifiers[k].shared
+ local features = shared and shared.features or { }
+ t[k] = features
+ return features
+ end
+end)
+
local nospacing = {
width = 0,
stretch = 0,
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 64323ddcf..3733d51c2 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -20,7 +20,7 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- todo:
--
--- kerning is probably not yet ok for latin around dics nodes
+-- kerning is probably not yet ok for latin around dics nodes (interesting challenge)
-- extension infrastructure (for usage out of context)
-- sorting features according to vendors/renderers
-- alternative loop quitters
@@ -31,7 +31,8 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
-- remove some optimizations (when I have a faster machine)
-
+--
+-- maybe redo the lot some way (more context specific)
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
@@ -187,6 +188,7 @@ local default = "dflt"
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
local glyphcodes = nodes.glyphcodes
+local disccodes = nodes.disccodes
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
@@ -197,6 +199,8 @@ local math_code = nodecodes.math
local dir_code = whatcodes.dir
local localpar_code = whatcodes.localpar
+local discretionary_code = disccodes.discretionary
+
local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
@@ -502,13 +506,18 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
-local function multiple_glyphs(head,start,multiple) -- marks ?
+local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples = #multiple
if nofmultiples > 0 then
start.char = multiple[1]
if nofmultiples > 1 then
local sn = start.next
for k=2,nofmultiples do -- todo: use insert_node
+-- untested:
+--
+-- while ignoremarks and marks[sn.char] then
+-- local sn = sn.next
+-- end
local n = copy_node(start) -- ignore components
n.char = multiple[k]
n.next = sn
@@ -545,11 +554,11 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
return head, start, true
end
-function handlers.gsub_multiple(head,start,kind,lookupname,multiple)
+function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple))
end
- return multiple_glyphs(head,start,multiple)
+ return multiple_glyphs(head,start,multiple,sequence.flags[1])
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
@@ -905,7 +914,6 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
prev = snext
snext = snext.next
else
- local krn = kerns[nextchar]
if not krn then
-- skip
elseif type(krn) == "table" then
@@ -1026,35 +1034,35 @@ single lookup case. The efficiency of the replacements can be improved by deleti
as less as needed but that would also make the code even more messy.</p>
--ldx]]--
-local function delete_till_stop(start,stop,ignoremarks) -- keeps start
- local n = 1
- if start == stop then
- -- done
- elseif ignoremarks then
- repeat -- start x x m x x stop => start m
- local next = start.next
- if not marks[next.char] then
- local components = next.components
- if components then -- probably not needed
- flush_node_list(components)
- end
- delete_node(start,next)
- end
- n = n + 1
- until next == stop
- else -- start x x x stop => start
- repeat
- local next = start.next
- local components = next.components
- if components then -- probably not needed
- flush_node_list(components)
- end
- delete_node(start,next)
- n = n + 1
- until next == stop
- end
- return n
-end
+-- local function delete_till_stop(head,start,stop,ignoremarks) -- keeps start
+-- local n = 1
+-- if start == stop then
+-- -- done
+-- elseif ignoremarks then
+-- repeat -- start x x m x x stop => start m
+-- local next = start.next
+-- if not marks[next.char] then
+-- local components = next.components
+-- if components then -- probably not needed
+-- flush_node_list(components)
+-- end
+-- head = delete_node(head,next)
+-- end
+-- n = n + 1
+-- until next == stop
+-- else -- start x x x stop => start
+-- repeat
+-- local next = start.next
+-- local components = next.components
+-- if components then -- probably not needed
+-- flush_node_list(components)
+-- end
+-- head = delete_node(head,next)
+-- n = n + 1
+-- until next == stop
+-- end
+-- return head, n
+-- end
--[[ldx--
<p>Here we replace start by a single variant, First we delete the rest of the
@@ -1108,7 +1116,7 @@ the match.</p>
--ldx]]--
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- delete_till_stop(start,stop) -- we could pass ignoremarks as #3 ..
+ -- local head, n = delete_till_stop(head,start,stop)
local startchar = start.char
local subtables = currentlookup.subtables
local lookupname = subtables[1]
@@ -1127,7 +1135,7 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements))
end
- return multiple_glyphs(head,start,replacements)
+ return multiple_glyphs(head,start,replacements,currentlookup.flags[1])
end
end
return head, start, false
@@ -1550,10 +1558,11 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
return head, start, false
end
+chainmores.gpos_single = chainprocs.gpos_single -- okay?
+
-- when machines become faster i will make a shared function
function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
--- logwarning("%s: gpos_pair not yet supported",cref(kind,chainname,chainlookupname))
local snext = start.next
if snext then
local startchar = start.char
@@ -1623,6 +1632,8 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
return head, start, false
end
+chainmores.gpos_pair = chainprocs.gpos_pair -- okay?
+
-- what pointer to return, spec says stop
-- to be discussed ... is bidi changer a space?
-- elseif char == zwnj and sequence[n][32] then -- brrr
@@ -1865,7 +1876,11 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if chainlookup then
local cp = chainprocs[chainlookup.type]
if cp then
- head, start, done = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ local ok
+ head, start, ok = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if ok then
+ done = true
+ end
else
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
end
@@ -1892,22 +1907,28 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
local chainlookupname = chainlookups[i]
- local chainlookup = lookuptable[chainlookupname] -- can be false (n matches, <n replacement)
- local cp = chainlookup and chainmores[chainlookup.type]
- if cp then
- local ok, n
- head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
- -- messy since last can be changed !
- if ok then
- done = true
- -- skip next one(s) if ligature
- i = i + (n or 1)
- else
+ local chainlookup = lookuptable[chainlookupname]
+ if not chainlookup then
+ -- okay, n matches, < n replacements
+ i = i + 1
+ else
+ local cp = chainmores[chainlookup.type]
+ if not cp then
+ -- actually an error
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i = i + 1
+ else
+ local ok, n
+ head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ -- messy since last can be changed !
+ if ok then
+ done = true
+ -- skip next one(s) if ligature
+ i = i + (n or 1)
+ else
+ i = i + 1
+ end
end
- else
- -- is valid
- i = i + 1
end
if start then
start = start.next
@@ -2081,6 +2102,15 @@ end
-- there will be a new direction parser (pre-parsed etc)
+-- less bytecode: 290 -> 254
+--
+-- attr = attr or false
+--
+-- local a = getattr(start,0)
+-- if (a == attr and (not attribute or getattr(start,a_state) == attribute)) or (not attribute or getattr(start,a_state) == attribute) then
+-- -- the action
+-- end
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -2185,6 +2215,44 @@ local function featuresprocessor(head,font,attr)
if not lookupcache then -- also check for empty cache
report_missing_cache(typ,lookupname)
else
+
+ local function subrun(start)
+ -- mostly for gsub, gpos would demand a more clever approach
+ local head = start
+ local done = false
+ while start do
+ local id = start.id
+ if id == glyph_code and start.font == font and start.subtype <256 then
+ local a = start[0]
+ if a then
+ a = (a == attr) and (not attribute or start[a_state] == attribute)
+ else
+ a = not attribute or start[a_state] == attribute
+ end
+ if a then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done = true
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ else
+ start = start.next
+ end
+ end
+ if done then
+ success = true
+ return head
+ end
+ end
+
while start do
local id = start.id
if id == glyph_code then
@@ -2212,6 +2280,26 @@ local function featuresprocessor(head,font,attr)
else
start = start.next
end
+ elseif id == disc_code then
+ -- mostly for gsub
+ if start.subtype == discretionary_code then
+ local pre = start.pre
+ if pre then
+ local new = subrun(pre)
+ if new then start.pre = new end
+ end
+ local post = start.post
+ if post then
+ local new = subrun(post)
+ if new then start.post = new end
+ end
+ local replace = start.replace
+ if replace then
+ local new = subrun(replace)
+ if new then start.replace = new end
+ end
+ end
+ start = start.next
elseif id == whatsit_code then -- will be function
local subtype = start.subtype
if subtype == dir_code then
@@ -2242,6 +2330,7 @@ local function featuresprocessor(head,font,attr)
else
rlparmode = 0
end
+ -- one might wonder if the par dir should be looked at, so we might as well drop the next line
rlmode = rlparmode
if trace_directions then
report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
@@ -2256,6 +2345,56 @@ local function featuresprocessor(head,font,attr)
end
end
else
+
+ local function subrun(start)
+ -- mostly for gsub, gpos would demand a more clever approach
+ local head = start
+ local done = false
+ while start do
+ local id = start.id
+ if id == glyph_code and start.id == font and start.subtype <256 then
+ local a = start[0]
+ if a then
+ a = (a == attr) and (not attribute or start[a_state] == attribute)
+ else
+ a = not attribute or start[a_state] == attribute
+ end
+ if a then
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ else
+ start = start.next
+ end
+ end
+ if done then
+ success = true
+ return head
+ end
+ end
+
while start do
local id = start.id
if id == glyph_code then
@@ -2295,6 +2434,26 @@ local function featuresprocessor(head,font,attr)
else
start = start.next
end
+ elseif id == disc_code then
+ -- mostly for gsub
+ if start.subtype == discretionary_code then
+ local pre = start.pre
+ if pre then
+ local new = subrun(pre)
+ if new then start.pre = new end
+ end
+ local post = start.post
+ if post then
+ local new = subrun(post)
+ if new then start.post = new end
+ end
+ local replace = start.replace
+ if replace then
+ local new = subrun(replace)
+ if new then start.replace = new end
+ end
+ end
+ start = start.next
elseif id == whatsit_code then
local subtype = start.subtype
if subtype == dir_code then
diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv
index 63c0858d4..75f42f8f5 100644
--- a/tex/context/base/font-pre.mkiv
+++ b/tex/context/base/font-pre.mkiv
@@ -17,13 +17,15 @@
%D A basic set of features is defined here.
+% beware, base mode + dynamics can give weird effects
+
% rlig ccmp
\definefontfeature
[always]
- [mode=auto,
- script=auto,
- kern=yes,
+ [mode=node, % we had 'auto', but let's try 'node' for a while and see what the impact is
+ script=auto, % on speed; 'base' just doesn't play well with dynamics; some day we can even
+ kern=yes, % consider skipping the base passes when no base mode is used
mark=yes,
mkmk=yes,
curs=yes]
@@ -61,6 +63,15 @@
tlig=yes,
trep=yes]
+\definefontfeature
+ [letterspacing]
+ [liga=no,
+ rlig=no,
+ clig=no,
+ dlig=no,
+ ccmp=yes,
+ keepligatures=auto]
+
\definefontfeature % can be used for type1 fonts
[complete]
[always]
diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv
index fc17ee475..0c52d5a92 100644
--- a/tex/context/base/mult-def.mkiv
+++ b/tex/context/base/mult-def.mkiv
@@ -99,6 +99,7 @@
\def\c!NL {NL}
\ifdefined\v!kerncharacters\else \def\v!kerncharacters{kerncharacters} \fi % no time now for translations should be a e! actually
+\ifdefined\v!letterspacing \else \def\v!letterspacing {letterspacing} \fi % no time now for translations should be a e! actually
\ifdefined\v!stretched \else \def\v!stretched {stretched} \fi
\ifdefined\v!vulgarfraction\else \def\v!vulgarfraction{vulgarfraction} \fi
\ifdefined\v!block \else \def\v!block {block} \fi
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index f74f27e7c..2f59d513c 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -30,6 +30,7 @@ local nodecodes = nodes.nodecodes
local handlers = nodes.handlers
local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
local setmetatableindex = table.setmetatableindex
@@ -91,11 +92,18 @@ end)
fonts.hashes.setdynamics = setfontdynamics
fonts.hashes.processes = fontprocesses
+-- if we forget about basemode we don't need to test too much here and we can consider running
+-- over sub-ranges .. this involves a bit more initializations but who cares .. in that case we
+-- also need to use the stop criterium (we already use head too) ... we cannot use traverse
+-- then, so i'll test it on some local clone first ... the only pitfall is changed directions
+-- inside a run which means that we need to keep track of this which in turn complicates matters
+-- in a way i don't like
+
function handlers.characters(head)
-- either next or not, but definitely no already processed list
starttiming(nodes)
- local usedfonts, attrfonts = { }, { }
- local a, u, prevfont, prevattr, done = 0, 0, nil, 0, false
+ local usedfonts, attrfonts = { }, { }
+ local a, u, prevfont, prevattr, done = 0, 0, nil, 0, false
if trace_fontrun then
run = run + 1
report_fonts()
@@ -107,9 +115,11 @@ function handlers.characters(head)
if id == glyph_code then
local font = n.font
local attr = n[0] or 0
- report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char))
+ report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,n.char)
+ elseif id == disc_code then
+ report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n))
else
- report_fonts("[%s]",nodecodes[n.id])
+ report_fonts("[%s]",nodecodes[id])
end
n = n.next
end
@@ -209,7 +219,6 @@ function handlers.characters(head)
return head, true
end
-
-- local formatters = string.formatters
-- local function make(processors,font,attribute)
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 4cefc1906..9fe979e93 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -18,8 +18,6 @@ local clock = os.gettimeofday or os.clock -- should go in environment
local report_nodes = logs.reporter("nodes","tracing")
-nodes = nodes or { }
-
local nodes, node, context = nodes, node, context
local texgetattribute = tex.getattribute
@@ -53,7 +51,7 @@ local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
local rule_code = nodecodes.rule
local whatsit_code = nodecodes.whatsit
-local spec_code = nodecodes.glue_spec
+local gluespec_code = nodecodes.gluespec
local localpar_code = whatcodes.localpar
local dir_code = whatcodes.dir
@@ -260,16 +258,19 @@ local function listtoutf(h,joiner,textonly,last)
while h do
local id = h.id
if id == glyph_code then -- always true
- w[#w+1] = utfchar(h.char)
+ local c = h.char
+ w[#w+1] = c >= 0 and utfchar(c) or formatters["<%i>"](c)
if joiner then
w[#w+1] = joiner
end
elseif id == disc_code then
- local pre, rep, pos = h.pre, h.replace, h.post
+ local pre = h.pre
+ local pos = h.post
+ local rep = h.replace
w[#w+1] = formatters["[%s|%s|%s]"] (
pre and listtoutf(pre,joiner,textonly) or "",
- rep and listtoutf(rep,joiner,textonly) or "",
- mid and listtoutf(mid,joiner,textonly) or ""
+ pos and listtoutf(pos,joiner,textonly) or "",
+ rep and listtoutf(rep,joiner,textonly) or ""
)
elseif textonly then
if id == glue_code and h.spec and h.spec.width > 0 then
@@ -353,7 +354,7 @@ local function numbertodimen(d,unit,fmt,strip)
if id == glue_code then
d = d.spec
end
- if not d or not d.id == spec_code then
+ if not d or not d.id == gluespec_code then
local str = formatters[fmt](0,unit)
return strip and lpegmatch(stripper,str) or str
end
diff --git a/tex/context/base/phys-dim.lua b/tex/context/base/phys-dim.lua
index 24d0b9231..e40d1eabb 100644
--- a/tex/context/base/phys-dim.lua
+++ b/tex/context/base/phys-dim.lua
@@ -384,13 +384,15 @@ local long_operators = {
local long_suffixes = {
- Linear = "linear",
- Square = "square",
- Cubic = "cubic",
- Inverse = "inverse",
- ILinear = "ilinear",
- ISquare = "isquare",
- ICubic = "icubic",
+ Linear = "linear",
+ Square = "square",
+ Cubic = "cubic",
+ Quadratic = "quadratic",
+ Inverse = "inverse",
+ ILinear = "ilinear",
+ ISquare = "isquare",
+ ICubic = "icubic",
+ IQuadratic = "iquadratic",
}
@@ -457,23 +459,29 @@ local short_suffixes = { -- maybe just raw digit match
["1"] = "linear",
["2"] = "square",
["3"] = "cubic",
+ ["4"] = "quadratic",
["+1"] = "linear",
["+2"] = "square",
["+3"] = "cubic",
+ ["+4"] = "quadratic",
["-1"] = "inverse",
["-1"] = "ilinear",
["-2"] = "isquare",
["-3"] = "icubic",
+ ["-4"] = "iquadratic",
["^1"] = "linear",
["^2"] = "square",
["^3"] = "cubic",
+ ["^4"] = "quadratic",
["^+1"] = "linear",
["^+2"] = "square",
["^+3"] = "cubic",
+ ["^+4"] = "quadratic",
["^-1"] = "inverse",
["^-1"] = "ilinear",
["^-2"] = "isquare",
["^-3"] = "icubic",
+ ["^-4"] = "iquadratic",
}
local symbol_units = {
@@ -638,13 +646,15 @@ labels.operators = allocate {
}
labels.suffixes = allocate {
- linear = { labels = { en = [[1]] } },
- square = { labels = { en = [[2]] } },
- cubic = { labels = { en = [[3]] } },
- inverse = { labels = { en = [[-1]] } },
- ilinear = { labels = { en = [[-1]] } },
- isquare = { labels = { en = [[-2]] } },
- icubic = { labels = { en = [[-3]] } },
+ linear = { labels = { en = [[1]] } },
+ square = { labels = { en = [[2]] } },
+ cubic = { labels = { en = [[3]] } },
+ quadratic = { labels = { en = [[4]] } },
+ inverse = { labels = { en = [[-1]] } },
+ ilinear = { labels = { en = [[-1]] } },
+ isquare = { labels = { en = [[-2]] } },
+ icubic = { labels = { en = [[-3]] } },
+ iquadratic = { labels = { en = [[-4]] } },
}
local function dimpus(p,u,s)
diff --git a/tex/context/base/s-fonts-vectors.lua b/tex/context/base/s-fonts-vectors.lua
index 1bac0ae8b..af8042f84 100644
--- a/tex/context/base/s-fonts-vectors.lua
+++ b/tex/context/base/s-fonts-vectors.lua
@@ -20,7 +20,7 @@ function moduledata.fonts.protrusions.showvector(specification)
local vector = vectors[specification.name or "?"]
if vector then
context.blank()
- context.startcolumns { n = specification.columns or 3 }
+ context.startcolumns { n = specification.columns or 3, balance="yes" }
context.starttabulate { "|T||cw(.5em)||" }
for unicode, values in table.sortedhash(vector) do
NC() context("%U",unicode)
@@ -65,7 +65,7 @@ function moduledata.fonts.expansions.showvector(specification)
local vector = vectors[specification.name or "?"]
if vector then
context.blank()
- context.startcolumns { n = specification.columns or 3 }
+ context.startcolumns { n = specification.columns or 3, balance="yes" }
context.starttabulate { "|T|cw(.5em)||" }
for unicode, value in table.sortedhash(vector) do
NC() context("%U",unicode)
diff --git a/tex/context/base/spac-cha.mkiv b/tex/context/base/spac-cha.mkiv
deleted file mode 100644
index a07c8f198..000000000
--- a/tex/context/base/spac-cha.mkiv
+++ /dev/null
@@ -1,191 +0,0 @@
-%D \module
-%D [ file=spac-cha, % was supp-ali,
-%D version=2012.06.08, % 2000.04.17,
-%D title=\CONTEXT\ Spacing Macros,
-%D subtitle=Character Alignment,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%D Yet undocumented but nevertheless used.
-
-% 0 = centered
-% 1 = left in before
-% 2 = right in before
-% 3 = left in after
-% 4 = right in after
-
-\unprotect
-
-% \starttabulate[|cg{.}|cg{,}|cg{,}|]
-% \NC period \NC comma \NC comma \NC\NR
-% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
-% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
-% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
-% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
-% \NG 10\\ \NG 10\\ \NG 0,00 \NC\NR
-% \NG 10 \NG 10 \NG 0,00 \NC\NR
-% \NG 10 \NG 10 \NG 0,00 \NC\NR
-% \stoptabulate
-
-% We gain not much by luafication and actually make things worse.
-
-\chardef\characteralignmentmode\plusfour
-\chardef\characteralignmentslot\plusone
-
-\let\afterassignwidth \!!zeropoint
-\let\beforeassignwidth\!!zeropoint
-
-\def\alignmentcharacter{.}
-
-\newdimen\d_supp_charalign_width
-\newtoks \t_supp_charalign_list
-
-\let\alignmentclass\s!default % can be used to handle multiple mixed ones
-
-\installcorenamespace{characteralign}
-
-\unexpanded\def\supp_charalign_push
- {\ifcsname\??characteralign\alignmentclass\endcsname\else
- \normalexpanded{\global\t_supp_charalign_list{\the\t_supp_charalign_list\supp_charalign_do{\alignmentclass}}}%
- \fi
- \setxvalue{\??characteralign\alignmentclass}{\supp_charalign_do
- {\afterassignwidth}{\beforeassignwidth}{\alignmentcharacter}}}
-
-\unexpanded\def\supp_charalign_pop_do#1#2#3%
- {\def\afterassignwidth {#1}%
- \def\beforeassignwidth {#2}%
- \def\alignmentcharacter{#3}}
-
-\unexpanded\def\supp_charalign_pop
- {\let\supp_charalign_do\supp_charalign_pop_do
- \executeifdefined{\??characteralign\alignmentclass}\donothing}
-
-\unexpanded\def\supp_charalign_reset_do#1%
- {\global\letbeundefined{\??characteralign#1}} % global !
-
-\unexpanded\def\resetcharacteralign
- {\let\supp_charalign_do\supp_charalign_reset_do
- \the\t_supp_charalign_list
- \global\t_supp_charalign_list\emptytoks}
-
-\unexpanded\def\supp_charalign_firstpass_one#1#2%
- {\supp_charalign_pop
- \let\\\empty
- \setbox\scratchbox\hbox{#1}%
- \d_supp_charalign_width\wd\scratchbox
- \setbox\scratchbox\emptyhbox
- \supp_charalign_check#2#1\relax\relax
- \scratchdimen-\wd\scratchbox
- \setbox\scratchbox\hbox{\ignorespaces#2\unskip}%
- \advance\scratchdimen \wd\scratchbox
- \ifdim\scratchdimen>\beforeassignwidth\relax
- \edef\beforeassignwidth{\the\scratchdimen}%
- \fi
- \ifdim\scratchdimen=\zeropoint
- \setbox\scratchbox\hbox{\ignorespaces#2\unskip}%
- \scratchdimen\wd\scratchbox
- \ifcase\characteralignmentmode
- % do nothing
- \else\ifnum\characteralignmentmode<\plusthree
- \advance\scratchdimen\d_supp_charalign_width\relax
- \ifdim\scratchdimen>\beforeassignwidth\relax
- \edef\beforeassignwidth{\the\scratchdimen}%
- \fi
- \else
- \ifdim\scratchdimen>\afterassignwidth\relax
- \edef\afterassignwidth{\the\scratchdimen}%
- \fi
- \fi\fi
- \fi
- \supp_charalign_push}
-
-\unexpanded\def\supp_charalign_firstpass_two#1#2#3%
- {\ifx#2\relax
- \setbox\scratchbox\hbox{\ignorespaces#1\unskip}%
- \ifdim\wd\scratchbox>\afterassignwidth
- \edef\afterassignwidth{\the\wd\scratchbox}%
- \fi
- \else
- \supp_charalign_check#2#3\relax\relax
- \fi}
-
-\unexpanded\def\supp_charalign_secondpass_one#1#2%
- {\supp_charalign_pop
- \let\\\empty % beware, no grouping
- \setbox\scratchbox\hbox{#1}%
- \d_supp_charalign_width\wd\scratchbox
- \setbox\scratchbox\emptyhbox
- % new 12,34 vs 10\\ where 10 aligns on 12 if #1 = ,
- \ifcase\characteralignmentslot
- \supp_charalign_check#2#1\relax\relax
- \scratchdimen\wd\scratchbox
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \else
- \def\\{#1}%
- \normalexpanded{\supp_charalign_check#2#1\relax\relax}%
- \scratchdimen\wd\scratchbox
- \setbox\scratchbox\hbox{\def\\{\hphantom{#1}}\ignorespaces#2\unskip}%
- \fi
- \noindent
- \ifdim\scratchdimen=\wd\scratchbox
- \ifcase\characteralignmentmode
- \box\scratchbox
- \else
- \hbox
- {\dontcomplain
- \hbox to \beforeassignwidth
- {\ifcase\characteralignmentmode\or
- \box\scratchbox\hss
- \or
- \hss\box\scratchbox\hskip\d_supp_charalign_width
- \or
- \hss\rlap{\box\scratchbox}%
- \or
- \hss\rlap{\hbox to \afterassignwidth{\hss\box\scratchbox}}%
- \fi}%
- \hskip\afterassignwidth}%
- \fi
- \else
- \hbox
- {\hbox to \beforeassignwidth
- {\hss\box\scratchbox\hskip-\scratchdimen}%
- \hskip\afterassignwidth}%
- \fi}
-
-\unexpanded\def\supp_charalign_secondpass_two#1#2#3%
- {\ifx#2\relax
- \setbox\scratchbox\hbox{\ignorespaces#1\unskip}%
- \else
- \supp_charalign_check#2#3\relax\relax
- \fi}
-
-\unexpanded\def\supp_charalign_firstpass#1%
- {\unexpanded\def\checkalignment ##1{\supp_charalign_firstpass_one{#1}{##1}}%
- \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_firstpass_two{##1}{##2}{##3}}}
-
-\unexpanded\def\supp_charalign_secondpass#1%
- {\unexpanded\def\checkalignment ##1{\supp_charalign_secondpass_one{#1}{##1}}%
- \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_secondpass_two{##1}{##2}{##3}}}
-
-\unexpanded\def\setfirstpasscharacteralign
- {\supp_charalign_pop
- \normalexpanded{\supp_charalign_firstpass{\alignmentcharacter}}}
-
-\unexpanded\def\setsecondpasscharacteralign
- {\supp_charalign_pop
- \normalexpanded{\supp_charalign_secondpass{\alignmentcharacter}}}
-
-\unexpanded\def\startcharacteralign#1\stopcharacteralign
- {\bgroup
- \setfirstpasscharacteralign #1%
- \setsecondpasscharacteralign#1%
- \egroup}
-
-\let\stopcharacteralign\relax
-
-\protect \endinput
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 2f5997597..9a9480dcf 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.log b/tex/context/base/status-lua.log
index f2a3738c2..0e63fe31a 100644
--- a/tex/context/base/status-lua.log
+++ b/tex/context/base/status-lua.log
@@ -1,6 +1,6 @@
(cont-yes.mkiv
-ConTeXt ver: 2013.10.01 20:08 MKIV beta fmt: 2013.10.1 int: english/english
+ConTeXt ver: 2013.10.04 23:41 MKIV beta fmt: 2013.10.4 int: english/english
system > 'cont-new.mkiv' loaded
(cont-new.mkiv)
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index 349c34cdc..caa7dc16c 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -1261,6 +1261,12 @@ return {
},
{
category = "mkiv",
+ filename = "typo-tal",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
comment = "somewhat weird",
filename = "tabl-com",
loading = "always",
@@ -1492,12 +1498,6 @@ return {
},
{
category = "mkiv",
- filename = "spac-cha",
- loading = "always",
- status = "okay",
- },
- {
- category = "mkiv",
comment = "work in progress",
filename = "blob-ini",
loading = "always",
@@ -4805,6 +4805,12 @@ return {
status = "todo",
},
{
+ category = "mkiv",
+ filename = "typo-tal",
+ loading = "typo-tal",
+ status = "okay",
+ },
+ {
category = "lua",
filename = "typo-itc",
status = "todo",
diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv
index 57134cb53..242c3d6fe 100644
--- a/tex/context/base/tabl-ntb.mkiv
+++ b/tex/context/base/tabl-ntb.mkiv
@@ -1517,18 +1517,29 @@
{\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
[\recurselevel:\the\scratchdimen]}}}
+% \def\tabl_ntb_char_align
+% {\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes
+% \tabl_ntb_char_align_indeed\gobbletwoarguments}
+
+% \def\tabl_ntb_char_align_indeed#1#2#3% row column data
+% {\edef\alignmentclass{#2}%
+% \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}%
+% \ifcase\c_tabl_tbl_pass\or
+% \setfirstpasscharacteralign\checkalignment{#3}% {\strut#2\unskip}%
+% \fi % force hsize, so always a second
+% \setsecondpasscharacteralign \checkalignment{#3}% {\strut#2\unskip}%
+% \ignorespaces}
+
\def\tabl_ntb_char_align
{\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes
- \tabl_ntb_char_align_indeed\gobbleoneargument}
+ \tabl_ntb_char_align_indeed
+ \gobbletwoarguments}
-\def\tabl_ntb_char_align_indeed#1#2% column data
- {\edef\alignmentclass{#1}%
- \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}%
- \ifcase\c_tabl_tbl_pass\or
- \setfirstpasscharacteralign\checkalignment{#2}% {\strut#2\unskip}%
- \fi % force hsize, so always a second
- \setsecondpasscharacteralign \checkalignment{#2}% {\strut#2\unskip}%
- \ignorespaces}
+\def\tabl_ntb_char_align_indeed#1#2% row column
+ {\ifcase\c_tabl_tbl_pass \or
+ \setcharacteralign{#2}{\naturaltablelocalparameter\c!alignmentcharacter}%
+ \fi
+ \signalcharacteralign{#2}{#1}}
\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
{\bgroup
@@ -1539,7 +1550,7 @@
\tabl_ntb_set_dis{#2}{\the\scratchdimen}%
\fi
\setupcurrentnaturaltablelocal[#3,\c!background=,\c!frame=\v!off]% 25% faster
- \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}}%
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}}%
\scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
\ifdim\wd\scratchbox>\scratchdimen
\ifsqueezeTBLspan
@@ -1625,7 +1636,7 @@
\fi
\fi
\normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
- {#1}{#2}[#3]{\tabl_ntb_char_align{#2}{#4}}}
+ {#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}}
\unexpanded\def\tabl_ntb_cell_process_c
{\tabl_ntb_cell_process_b_c{}}
@@ -1634,7 +1645,7 @@
{\tabl_ntb_setup_cell{#1}{#2}%
\bgroup
\setupcurrentnaturaltablelocal[#3,\c!width=\d_tabl_ntb_width,\c!background=,\c!frame=\v!off]% 25% faster
- \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_ntb_cell_stop}%
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
\egroup}
\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4%
@@ -1647,7 +1658,7 @@
\else
\setupcurrentnaturaltablelocal[\c!color=,\c!width=\d_tabl_ntb_width,\c!height=\d_tabl_ntb_height]%
\fi
- \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_ntb_cell_stop}}%
+ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}}%
\hskip\tabl_ntb_get_dis{#2}}
\setupTABLE
diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv
index f04c45e18..fa2417712 100644
--- a/tex/context/base/tabl-tbl.mkiv
+++ b/tex/context/base/tabl-tbl.mkiv
@@ -232,7 +232,6 @@
\unexpanded\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
-\installcorenamespace{tabulatealign}
\installcorenamespace{tabulatebox}
\installcorenamespace{tabulatesetup}
\installcorenamespace{tabulatehook}
@@ -297,14 +296,6 @@
% [|lg{.}|] => \NG 12.34 \NC
-\def\tabl_tabulate_charalign#1 % space delimited ! (will be redone in lua)
- {\edef\alignmentclass{\the\c_tabl_tabulate_column}%
- \edef\alignmentcharacter{\csname\??tabulatealign\the\c_tabl_tabulate_column\endcsname}%
- \ifcase\c_tabl_tabulate_pass\or
- \setfirstpasscharacteralign\checkalignment{#1}%
- \fi % force hsize
- \setsecondpasscharacteralign\checkalignment{#1}}
-
\def\tabl_tabulate_nobreak_inject_tracer
{\red % maybe use the fast color switcher here
\hrule\s!height.5\linewidth\s!depth.5\linewidth
@@ -425,6 +416,8 @@
\let\tabl_tabulate_hook_b\donothing
\let\tabl_tabulate_hook_e\donothing
+\let\tabl_tabulate_hook_g\donothing
+
\def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
{\normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
\tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
@@ -440,6 +433,7 @@
\tabl_tabulate_color_side_both
\global\c_tabl_tabulate_colorspan\zerocount
\global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
+ \tabl_tabulate_hook_g
\tabl_tabulate_setups_check % unexpandable
\tabl_tabulate_hook_check % unexpandable
\ifzeropt\d_tabl_tabulate_width
@@ -624,10 +618,22 @@
{\setvalue{\??tabulatehook\the\c_tabl_tabulate_columns}{#1}%
\tabl_tabulate_set_preamble}
+% begin of character align plugin
+
+\newconditional\c_tabl_auto_align_mode % reset later
+
+\def\tabl_tabulate_hook_g % partly expanded
+ {\ifconditional\c_tabl_auto_align_mode
+ \signalcharacteralign\c_tabl_tabulate_column{\c_tabl_tabulate_noflines+\plusone}%
+ \fi}
+
\def\tabl_tabulate_set_align#1%
- {\setvalue{\??tabulatealign\the\c_tabl_tabulate_columns}{#1}%
+ {\global\settrue\c_tabl_auto_align_mode
+ \setcharacteralign\c_tabl_tabulate_columns{#1}%
\tabl_tabulate_set_preamble}
+% end of character align plugin
+
\def\tabl_tabulate_set_before#1%
{\t_tabl_tabulate_before{#1}%
\tabl_tabulate_set_preamble}
@@ -759,6 +765,7 @@
\global\let\m_tabl_tabulate_text_color\empty
\global\let\m_tabl_tabulate_vrule_color\empty
\global\c_tabl_tabulate_colorspan\zerocount
+ \global\setfalse\c_tabl_auto_align_mode
\global\advance\c_tabl_tabulate_columns\plusone
\expandafter\let\csname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ?
\edef\currenttabulationtrulespec{#1}%
@@ -768,7 +775,7 @@
\global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
\rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
\fi
- \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
+ \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
\ifcase\c_tabl_tabulate_modus\relax
\tabl_tabulate_set_width_normal
\or % fixed width
@@ -845,8 +852,7 @@
\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
-\def\tabl_tabulate_hook_yes {\csname\??tabulatehook \the\c_tabl_tabulate_column\endcsname}
-\def\tabl_tabulate_align_yes{\csname\??tabulatealign\the\c_tabl_tabulate_column\endcsname} % to be used
+\def\tabl_tabulate_hook_yes{\csname\??tabulatehook\the\c_tabl_tabulate_column\endcsname}
\def\tabl_tabulate_pheight_reset
{\global\c_tabl_tabulate_plines_min\plusone
@@ -1696,7 +1702,8 @@
\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \plusone}
\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \plustwo}
-\unexpanded\def\tabl_tabulate_NG_first{\NC\tabl_tabulate_charalign}
+%unexpanded\def\tabl_tabulate_NG_first{\NC\tabl_tabulate_charalign}
+\unexpanded\def\tabl_tabulate_NG_first{\NC}
\unexpanded\def\tabl_tabulate_NN_first{\NC\tabl_tabulate_digits} % new, undocumented, test first
\unexpanded\def\tabl_tabulate_ND_first{\NC\tabl_tabulate_digits} % same, for old times sake
diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua
index 9c7e7ce63..51aa550cb 100644
--- a/tex/context/base/task-ini.lua
+++ b/tex/context/base/task-ini.lua
@@ -27,6 +27,7 @@ appendaction("processors", "normalizers", "typesetters.characters.handler")
appendaction("processors", "normalizers", "fonts.collections.process") -- disabled
appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled
+appendaction("processors", "characters", "typesetters.characteralign.handler") -- disabled
appendaction("processors", "characters", "scripts.autofontfeature.handler")
appendaction("processors", "characters", "scripts.splitters.handler") -- disabled
appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled
@@ -119,6 +120,7 @@ appendaction("vboxbuilders","normalizers","typesetters.checkers.handler")
-- speedup: only kick in when used
+disableaction("processors", "typesetters.characteralign.handler")
disableaction("processors", "scripts.autofontfeature.handler")
disableaction("processors", "scripts.splitters.handler")
disableaction("processors", "scripts.injectors.handler") -- was enabled
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua
index 20d08fcce..dc8bcc5e7 100644
--- a/tex/context/base/trac-vis.lua
+++ b/tex/context/base/trac-vis.lua
@@ -34,10 +34,8 @@ local formatters = string.formatters
-- todo: inline concat (more efficient)
local nodecodes = nodes.nodecodes
-local disc_code = nodecodes.disc
local kern_code = nodecodes.kern
local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local glue_code = nodecodes.glue
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index 2fc3ff13e..cd531f108 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -57,8 +57,14 @@ local quaddata = fonthashes.quads
local markdata = fonthashes.marks
local fontproperties = fonthashes.properties
local fontdescriptions = fonthashes.descriptions
+local fontfeatures = fonthashes.features
+
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local resetcolor = tracers.colors.reset
local v_max = interfaces.variables.max
+local v_auto = interfaces.variables.auto
typesetters = typesetters or { }
local typesetters = typesetters
@@ -67,13 +73,15 @@ typesetters.kerns = typesetters.kerns or { }
local kerns = typesetters.kerns
local report = logs.reporter("kerns")
-local trace_ligatures = trackers.register("typesetters.kerns.ligatures",function(v) trace_ligatures = v end)
+local trace_ligatures = false trackers.register("typesetters.kerns.ligatures",function(v) trace_ligatures = v end)
kerns.mapping = kerns.mapping or { }
kerns.factors = kerns.factors or { }
local a_kerns = attributes.private("kern")
local a_fontkern = attributes.private('fontkern')
+local contextsetups = fonts.specifiers.contextsetups
+
storage.register("typesetters/kerns/mapping", kerns.mapping, "typesetters.kerns.mapping")
storage.register("typesetters/kerns/factors", kerns.factors, "typesetters.kerns.factors")
@@ -92,20 +100,62 @@ local gluefactor = 4 -- assumes quad = .5 enspace
kerns.keepligature = false -- just for fun (todo: control setting with key/value)
kerns.keeptogether = false -- just for fun (todo: control setting with key/value)
+-- red : kept by dynamic feature
+-- green : kept by static feature
+-- blue : keep by goodie
+
function kerns.keepligature(n) -- might become default
local f = n.font
- local c = n.char
- local k = fontproperties[f].keptligatures
+ local a = n[0] or 0
if trace_ligatures then
- -- mostly for identifying names as they get reported
+ local c = n.char
local d = fontdescriptions[f][c].name
+ if a > 0 and contextsetups[a].keepligatures == v_auto then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"kept","dynamic","keepligatures")
+ setcolor(n,"darkred")
+ return true
+ end
+ local k = fontfeatures[f].keepligatures
+ if k == v_auto then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"kept","static","keepligatures")
+ setcolor(n,"darkgreen")
+ return true
+ end
+ if not k then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"split","static","keepligatures")
+ resetcolor(n)
+ return false
+ end
+ local k = fontproperties[f].keptligatures
+ if not k then
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"split","no")
+ resetcolor(n)
+ return false
+ end
if k and k[c] then
- report("font %s, glyph %a, slot %X -> kept ligature",f,d,c)
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"kept","by")
+ setcolor(n,"darkblue")
return true
else
- report("font %s, glyph %a, slot %X -> split ligature",f,d,c)
+ report("font %!font:name!, glyph %a, slot %X -> ligature %s, %s goodie specification",f,d,c,"split","by")
+ resetcolor(n)
+ return false
end
else
+ if a > 0 and contextsetups[a].keepligatures == v_auto then
+ return true
+ end
+ local k = fontfeatures[f].keepligatures
+ if k == v_auto then
+ return true
+ end
+ if not k then
+ return false
+ end
+ local k = fontproperties[f].keptligatures
+ if not k then
+ return false
+ end
if k and k[c] then
return true
end
@@ -136,7 +186,7 @@ local function spec_injector(fillup,width,stretch,shrink)
end
end
--- needs checking ... base mode / node mode
+-- needs checking ... base mode / node mode -- also use insert_before/after etc
local function do_process(head,force) -- todo: glue so that we can fully stretch
local start, done, lastfont = head, false, nil
diff --git a/tex/context/base/typo-krn.mkiv b/tex/context/base/typo-krn.mkiv
index a47bd2ac5..3522c02fc 100644
--- a/tex/context/base/typo-krn.mkiv
+++ b/tex/context/base/typo-krn.mkiv
@@ -40,6 +40,7 @@
\def\typo_kerning_set
{\usecharacterkerningstyleandcolor\c!style\c!color % goodie, maybe also strut
+ \useaddfontfeatureparameter\characterkerningparameter
\ctxcommand{setcharacterkerning("\characterkerningparameter\c!factor")}}
\unexpanded\def\resetcharacterkerning % fast one
@@ -62,29 +63,55 @@
%D then we always would get a command defined which is not beforehand
%D a good idea.
-\definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
-
% Here we need to keep the groupedcommand solution as it is
% used as modifier.
-\unexpanded\def\kerncharacters
- {\doifnextoptionalelse\typo_kerning_apply_yes\typo_kerning_apply_nop}
+% \definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
+% \definecharacterkerning [\v!letterspacing ] [\v!kerncharacters] [\c!features=letterspacing]
+%
+% \unexpanded\def\kerncharacters
+% {\doifnextoptionalelse\typo_kerning_apply_yes\typo_kerning_apply_nop}
+%
+% \def\typo_kerning_apply_yes[#1]%
+% {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}}\donothing}
+%
+% \def\typo_kerning_apply_nop
+% {\groupedcommand\typo_kerning_apply_nop_indeed\donothing}
+%
+% \def\typo_kerning_apply_yes_indeed#1%
+% {\let\currentcharacterkerning\v!kerncharacters
+% \setupcurrentcharacterkerning[\c!factor=#1]%
+% \typo_kerning_set}
+%
+% \def\typo_kerning_apply_nop_indeed
+% {\let\currentcharacterkerning\v!kerncharacters
+% \typo_kerning_set}
-\def\typo_kerning_apply_yes[#1]%
- {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}}\donothing}
+\appendtoks
+ \setuevalue{\currentcharacterkerning}%
+ {\doifnextoptionalelse
+ {\typo_kerning_apply_yes{\currentcharacterkerning}}%
+ {\typo_kerning_apply_nop{\currentcharacterkerning}}}
+\to \everydefinecharacterkerning
+
+\unexpanded\def\typo_kerning_apply_yes#1[#2]%
+ {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}{#2}}\donothing}
-\def\typo_kerning_apply_nop
- {\groupedcommand\typo_kerning_apply_nop_indeed\donothing}
+\unexpanded\def\typo_kerning_apply_nop#1%
+ {\groupedcommand{\typo_kerning_apply_nop_indeed{#1}}\donothing}
-\def\typo_kerning_apply_yes_indeed#1%
- {\let\currentcharacterkerning\v!kerncharacters
- \setupcurrentcharacterkerning[\c!factor=#1]%
+\def\typo_kerning_apply_yes_indeed#1#2%
+ {\edef\currentcharacterkerning{#1}%
+ \setupcurrentcharacterkerning[\c!factor=#2]%
\typo_kerning_set}
-\def\typo_kerning_apply_nop_indeed
- {\let\currentcharacterkerning\v!kerncharacters
+\def\typo_kerning_apply_nop_indeed#1%
+ {\edef\currentcharacterkerning{#1}%
\typo_kerning_set}
+\definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
+\definecharacterkerning [\v!letterspacing ] [\v!kerncharacters] [\c!features=letterspacing]
+
%D \macros
%D {stretched}
%D
@@ -133,6 +160,7 @@
\fi
\bgroup
\usecharacterkerningstyleandcolor\c!style\c!color
+ \useaddfontfeatureparameter\characterkerningparameter
\typo_kerning_set
#2%
\egroup
diff --git a/tex/context/base/typo-tal.lua b/tex/context/base/typo-tal.lua
new file mode 100644
index 000000000..3df8dd00a
--- /dev/null
+++ b/tex/context/base/typo-tal.lua
@@ -0,0 +1,265 @@
+if not modules then modules = { } end modules ['typo-tal'] = {
+ version = 1.001,
+ comment = "companion to typo-tal.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- I'll make it a bit more efficient and provide named instances too.
+
+local next, type = next, type
+local div = math.div
+local utfbyte = utf.byte
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+
+local fontcharacters = fonts.hashes.characters
+local categories = characters.categories -- nd
+
+local insert_node_before = nodes.insert_before
+local insert_node_after = nodes.insert_after
+local traverse_list_by_id = nodes.traverse_id
+local dimensions_of_list = nodes.dimensions
+local first_glyph = nodes.first_glyph
+
+local nodepool = nodes.pool
+local new_kern = nodepool.kern
+local new_gluespec = nodepool.gluespec
+
+local tracers = nodes.tracers
+local setcolor = tracers.colors.set
+local tracedrule = tracers.pool.nodes.rule
+
+local characteralign = { }
+typesetters.characteralign = characteralign
+
+local trace_split = false trackers.register("typesetters.characteralign", function(v) trace_split = true end)
+local report = logs.reporter("aligning")
+
+local a_characteralign = attributes.private("characteralign")
+local a_character = attributes.private("characters")
+
+local enabled = false
+
+local datasets = false
+
+local comma = 0x002C
+local period = 0x002E
+local punctuationspace = 0x2008
+
+local validseparators = {
+ [comma] = true,
+ [period] = true,
+ [punctuationspace] = true,
+}
+
+local validsigns = {
+ [0x002B] = 0x002B, -- plus
+ [0x002D] = 0x2212, -- hyphen
+ [0x00B1] = 0x00B1, -- plusminus
+ [0x2212] = 0x2212, -- minus
+ [0x2213] = 0x2213, -- minusplus
+}
+
+local function traced_kern(w)
+ return tracedrule(w,nil,nil,"darkgray")
+end
+
+function characteralign.handler(head,where)
+ if not datasets then
+ return head, false
+ end
+ local first = first_glyph(head) -- we could do that once
+ if not first then
+ return head, false
+ end
+ local a = first[a_characteralign]
+ if not a or a == 0 then
+ return head, false
+ end
+ local column = div(a,100)
+ local row = a % 100
+ local dataset = datasets and datasets[column] or setcharacteralign(column)
+ local separator = dataset.separator
+ local list = dataset.list
+ local b_start = nil
+ local b_stop = nil
+ local a_start = nil
+ local a_stop = nil
+ local c = nil
+ local current = first
+ local sign = nil
+ -- we can think of constraints
+ while current do
+ local id = current.id
+ if id == glyph_code then
+ local char = current.char
+ if char == separator then
+ c = current
+ if trace_split then
+ setcolor(current,"darkred")
+ end
+ elseif categories[char] == "nd" or validseparators[char] then
+ if c then
+ if not a_start then
+ a_start = current
+ end
+ a_stop = current
+ if trace_split then
+ setcolor(current,"darkgreen")
+ end
+ else
+ if not b_start then
+ if sign then
+ b_start = sign
+ local new = validsigns[sign.char]
+ if char == new or not fontcharacters[sign.font][new] then
+ if trace_split then
+ setcolor(sign,"darkyellow")
+ end
+ else
+ sign.char = new
+ if trace_split then
+ setcolor(sign,"darkmagenta")
+ end
+ end
+ sign = nil
+ else
+ b_start = current
+ end
+ end
+ b_stop = current
+ if trace_split then
+ setcolor(current,"darkblue")
+ end
+ end
+ elseif not b_start then
+ sign = validsigns[char] and current
+ end
+ elseif (b_start or a_start) and id == glue_code then
+ -- somewhat inefficient
+ local next = current.next
+ local prev = current.prev
+ if next and prev and next.id == glyph_code and prev.id == glyph_code then -- too much checking
+ local width = fontcharacters[b_start.font][period].width
+ -- local spec = current.spec
+ -- nodes.free(spec) -- hm, we leak but not that many specs
+ current.spec = new_gluespec(width)
+ current[a_character] = punctuationspace
+ end
+ end
+ current = current.next
+ end
+ local entry = list[row]
+ if entry then
+ if not dataset.collected then
+ -- print("[maxbefore] [maxafter]")
+ local maxbefore = 0
+ local maxafter = 0
+ for k, v in next, list do
+ local before = v.before
+ local after = v.after
+ if before and before > maxbefore then
+ maxbefore = before
+ end
+ if after and after > maxafter then
+ maxafter = after
+ end
+ end
+ dataset.maxafter = maxafter
+ dataset.maxbefore = maxbefore
+ dataset.collected = true
+ end
+ local maxafter = dataset.maxafter
+ local maxbefore = dataset.maxbefore
+ local before = entry.before or 0
+ local after = entry.after or 0
+ local new_kern = trace_split and traced_kern or new_kern
+ if b_start then
+ if before < maxbefore then
+ head = insert_node_before(head,b_start,new_kern(maxbefore-before))
+ end
+ if not c then
+ -- print("[before]")
+ local width = fontcharacters[b_stop.font][separator].width
+ insert_node_after(head,b_stop,new_kern(maxafter+width))
+ elseif a_start then
+ -- print("[before] [separator] [after]")
+ if after < maxafter then
+ insert_node_after(head,a_stop,new_kern(maxafter-after))
+ end
+ else
+ -- print("[before] [separator]")
+ if maxafter > 0 then
+ insert_node_after(head,c,new_kern(maxafter))
+ end
+ end
+ elseif a_start then
+ if c then
+ -- print("[separator] [after]")
+ if maxbefore > 0 then
+ head = insert_node_before(head,c,new_kern(maxbefore))
+ end
+ else
+ -- print("[after]")
+ local width = fontcharacters[b_stop.font][separator].width
+ head = insert_node_before(head,a_start,new_kern(maxbefore+width))
+ end
+ if after < maxafter then
+ insert_node_after(head,a_stop,new_kern(maxafter-after))
+ end
+ elseif c then
+ -- print("[separator]")
+ if maxbefore > 0 then
+ head = insert_node_before(head,c,new_kern(maxbefore))
+ end
+ if maxafter > 0 then
+ insert_node_after(head,c,new_kern(maxafter))
+ end
+ end
+ else
+ entry = {
+ before = b_start and dimensions_of_list(b_start,b_stop.next) or 0,
+ after = a_start and dimensions_of_list(a_start,a_stop.next) or 0,
+ }
+ list[row] = entry
+ end
+ return head, true
+end
+
+function setcharacteralign(column,separator)
+ if not enabled then
+ nodes.tasks.enableaction("processors","typesetters.characteralign.handler")
+ enabled = true
+ end
+ if not datasets then
+ datasets = { }
+ end
+ local dataset = datasets[column] -- we can use a metatable
+ if not dataset then
+ dataset = {
+ separator = separator and utfbyte(separator) or comma,
+ list = { },
+ maxafter = 0,
+ maxbefore = 0,
+ collected = false,
+ }
+ datasets[column] = dataset
+ used = true
+ end
+ return dataset
+end
+
+local function resetcharacteralign()
+ datasets = false
+end
+
+characteralign.setcharacteralign = setcharacteralign
+characteralign.resetcharacteralign = resetcharacteralign
+
+commands.setcharacteralign = setcharacteralign
+commands.resetcharacteralign = resetcharacteralign
+
diff --git a/tex/context/base/typo-tal.mkiv b/tex/context/base/typo-tal.mkiv
new file mode 100644
index 000000000..f67eadc49
--- /dev/null
+++ b/tex/context/base/typo-tal.mkiv
@@ -0,0 +1,112 @@
+%D \module
+%D [ file=typo-tal, % spac-cha (2012.06.08) supp-ali (2000.04.17)
+%D version=2013.10.04,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Character Alignment,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Typesetting Macros / Character Alignment}
+
+%D This module replaces the \MKII\ character alignment code which hooked into
+%D table mechanisms but used parsing. In fact, this might be one of these cases
+%D where a \TEX\ based solution is faster, but a \LUA\ one a bit more robust.
+%D Anyway, as I had to fix something (to fit the newer table mechanisms) I
+%D decided to go the mixed route, a rather easy going effort in the aftermath of
+%D the 2013 \CONTEXT\ meeting.
+
+\unprotect
+
+\registerctxluafile{typo-tal}{1.001}
+
+\definesystemattribute[characteralign][public]
+
+%D This mechanism is mostly meant for tables:
+%D
+%D \startbuffer
+%D \starttabulate[|l|g{,}|r|]
+%D \NC test \NC 1.234.456,99 \NC \NC test \NR
+%D \NC test \NC 234.456,9 \NC \NC test \NR
+%D \NC test \NC 234.456 \NC \NC test \NR
+%D \NC test \NC 456 \NC \NC test \NR
+%D \NC test \NC \bf whatever \NC \NC test \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+%D \startbuffer
+%D \bTABLE
+%D \bTR \bTD[aligncharacter=yes] € 1,1 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 11,11 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 12\punctuationspace111,11 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 12 111,11 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 1.234.451,22222 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 234.451,2 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 234.451 \eTD \eTR
+%D \bTR \bTD[aligncharacter=yes] € 451 \eTD \eTR
+%D \bTR \bTD \bf some text \eTD \eTR
+%D \eTABLE
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\unexpanded\def\signalcharacteralign#1#2{\attribute\characteralignattribute=\numexpr#1*\plushundred+#2\relax}
+\unexpanded\def\setcharacteralign #1#2{\ctxcommand{setcharacteralign(\number#1,"#2")}}
+\unexpanded\def\resetcharacteralign {\ctxcommand{resetcharacteralign()}}
+
+%D Mostly downward compatible:
+%D
+%D \startbuffer
+%D \startcharacteralign
+%D \checkcharacteralign{123.456,78}
+%D \checkcharacteralign{456}
+%D \checkcharacteralign{23.456}
+%D \checkcharacteralign{78,9}
+%D \stopcharacteralign
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\def\alignmentcharacter{,}
+
+\unexpanded\def\typo_charalign_pass_one
+ {\advance\scratchcounter\plusone
+ \setbox\scratchbox\typo_charalign_pass}
+
+\unexpanded\def\typo_charalign_pass_two
+ {\advance\scratchcounter\plusone
+ \typo_charalign_pass}
+
+\def\typo_charalign_pass
+ {\hbox\bgroup\signalcharacteralign\plusone\scratchcounter\let\next}
+
+\unexpanded\def\startcharacteralign#1\stopcharacteralign
+ {\bgroup
+ \setcharacteralign\plusone\alignmentcharacter
+ \begingroup
+ \scratchcounter\zerocount
+ \let\checkcharacteralign\typo_charalign_pass_one
+ \settrialtypesetting
+ #1\relax
+ \endgroup
+ \begingroup
+ \scratchcounter\zerocount
+ \let\checkcharacteralign\typo_charalign_pass_two
+ #1\relax
+ \endgroup
+ \resetcharacteralign
+ \egroup}
+
+\let\stopcharacteralign \relax
+\let\checkcharacteralign\gobbleoneargument
+
+\def\setfirstpasscharacteralign {\let\checkcharacteralign\gobbleoneargument}
+\def\setsecondpasscharacteralign{\let\checkcharacteralign\firstofoneargument}
+
+\endinput
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index ef78f0ef8..2912a1c31 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 : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 10/01/13 20:08:43
+-- merge date : 10/04/13 23:41:38
do -- begin closure to overcome local limits and interference
@@ -9666,6 +9666,7 @@ local default="dflt"
local nodecodes=nodes.nodecodes
local whatcodes=nodes.whatcodes
local glyphcodes=nodes.glyphcodes
+local disccodes=nodes.disccodes
local glyph_code=nodecodes.glyph
local glue_code=nodecodes.glue
local disc_code=nodecodes.disc
@@ -9673,6 +9674,7 @@ local whatsit_code=nodecodes.whatsit
local math_code=nodecodes.math
local dir_code=whatcodes.dir
local localpar_code=whatcodes.localpar
+local discretionary_code=disccodes.discretionary
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
@@ -9920,13 +9922,13 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
end
end
end
-local function multiple_glyphs(head,start,multiple)
+local function multiple_glyphs(head,start,multiple,ignoremarks)
local nofmultiples=#multiple
if nofmultiples>0 then
setfield(start,"char",multiple[1])
if nofmultiples>1 then
local sn=getnext(start)
- for k=2,nofmultiples do
+ for k=2,nofmultiples do
local n=copy_node(start)
setfield(n,"char",multiple[k])
setfield(n,"next",sn)
@@ -9961,11 +9963,11 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
end
return head,start,true
end
-function handlers.gsub_multiple(head,start,kind,lookupname,multiple)
+function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
end
- return multiple_glyphs(head,start,multiple)
+ return multiple_glyphs(head,start,multiple,sequence.flags[1])
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
local s,stop,discfound=getnext(start),nil,false
@@ -10299,7 +10301,6 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
prev=snext
snext=getnext(snext)
else
- local krn=kerns[nextchar]
if not krn then
elseif type(krn)=="table" then
if lookuptype=="pair" then
@@ -10372,34 +10373,6 @@ function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,loo
return head,start,false
end
end
-local function delete_till_stop(start,stop,ignoremarks)
- local n=1
- if start==stop then
- elseif ignoremarks then
- repeat
- local next=getnext(start)
- if not marks[getchar(next)] then
- local components=getfield(next,"components")
- if components then
- flush_node_list(components)
- end
- delete_node(start,next)
- end
- n=n+1
- until next==stop
- else
- repeat
- local next=getnext(start)
- local components=getfield(next,"components")
- if components then
- flush_node_list(components)
- end
- delete_node(start,next)
- n=n+1
- until next==stop
- end
- return n
-end
function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
local current=start
local subtables=currentlookup.subtables
@@ -10439,7 +10412,6 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
end
chainmores.gsub_single=chainprocs.gsub_single
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- delete_till_stop(start,stop)
local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -10458,7 +10430,7 @@ function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements))
end
- return multiple_glyphs(head,start,replacements)
+ return multiple_glyphs(head,start,replacements,currentlookup.flags[1])
end
end
return head,start,false
@@ -10842,6 +10814,7 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
end
return head,start,false
end
+chainmores.gpos_single=chainprocs.gpos_single
function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
local snext=getnext(start)
if snext then
@@ -10910,6 +10883,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
end
return head,start,false
end
+chainmores.gpos_pair=chainprocs.gpos_pair
local function show_skip(kind,chainname,char,ck,class)
if ck[9] then
logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
@@ -11126,7 +11100,11 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if chainlookup then
local cp=chainprocs[chainlookup.type]
if cp then
- head,start,done=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ local ok
+ head,start,ok=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ if ok then
+ done=true
+ end
else
logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
end
@@ -11153,19 +11131,24 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
local chainlookupname=chainlookups[i]
- local chainlookup=lookuptable[chainlookupname]
- local cp=chainlookup and chainmores[chainlookup.type]
- if cp then
- local ok,n
- head,start,ok,n=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
- if ok then
- done=true
- i=i+(n or 1)
- else
+ local chainlookup=lookuptable[chainlookupname]
+ if not chainlookup then
+ i=i+1
+ else
+ local cp=chainmores[chainlookup.type]
+ if not cp then
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
i=i+1
+ else
+ local ok,n
+ head,start,ok,n=cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
+ if ok then
+ done=true
+ i=i+(n or 1)
+ else
+ i=i+1
+ end
end
- else
- i=i+1
end
if start then
start=getnext(start)
@@ -11375,6 +11358,40 @@ local function featuresprocessor(head,font,attr)
if not lookupcache then
report_missing_cache(typ,lookupname)
else
+ local function subrun(start)
+ local head=start
+ local done=false
+ while start do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
+ else
+ a=not attribute or getattr(start,a_state)==attribute
+ end
+ if a then
+ local lookupmatch=lookupcache[getchar(start)]
+ if lookupmatch then
+ local ok
+ head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ done=true
+ end
+ end
+ if start then start=getnext(start) end
+ else
+ start=getnext(start)
+ end
+ else
+ start=getnext(start)
+ end
+ end
+ if done then
+ success=true
+ return head
+ end
+ end
while start do
local id=getid(start)
if id==glyph_code then
@@ -11401,6 +11418,25 @@ local function featuresprocessor(head,font,attr)
else
start=getnext(start)
end
+ elseif id==disc_code then
+ if getsubtype(start)==discretionary_code then
+ local pre=getfield(start,"pre")
+ if pre then
+ local new=subrun(pre)
+ if new then setfield(start,"pre",new) end
+ end
+ local post=getfield(start,"post")
+ if post then
+ local new=subrun(post)
+ if new then setfield(start,"post",new) end
+ end
+ local replace=getfield(start,"replace")
+ if replace then
+ local new=subrun(replace)
+ if new then setfield(start,"replace",new) end
+ end
+ end
+ start=getnext(start)
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then
@@ -11445,6 +11481,51 @@ local function featuresprocessor(head,font,attr)
end
end
else
+ local function subrun(start)
+ local head=start
+ local done=false
+ while start do
+ local id=getid(start)
+ if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
+ if a then
+ a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
+ else
+ a=not attribute or getattr(start,a_state)==attribute
+ end
+ if a then
+ for i=1,ns do
+ local lookupname=subtables[i]
+ local lookupcache=lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch=lookupcache[getchar(start)]
+ if lookupmatch then
+ local ok
+ head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ done=true
+ break
+ elseif not start then
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
+ end
+ end
+ if start then start=getnext(start) end
+ else
+ start=getnext(start)
+ end
+ else
+ start=getnext(start)
+ end
+ end
+ if done then
+ success=true
+ return head
+ end
+ end
while start do
local id=getid(start)
if id==glyph_code then
@@ -11482,6 +11563,25 @@ local function featuresprocessor(head,font,attr)
else
start=getnext(start)
end
+ elseif id==disc_code then
+ if getsubtype(start)==discretionary_code then
+ local pre=getfield(start,"pre")
+ if pre then
+ local new=subrun(pre)
+ if new then setfield(start,"pre",new) end
+ end
+ local post=getfield(start,"post")
+ if post then
+ local new=subrun(post)
+ if new then setfield(start,"post",new) end
+ end
+ local replace=getfield(start,"replace")
+ if replace then
+ local new=subrun(replace)
+ if new then setfield(start,"replace",new) end
+ end
+ end
+ start=getnext(start)
elseif id==whatsit_code then
local subtype=getsubtype(start)
if subtype==dir_code then