diff options
Diffstat (limited to 'tex')
29 files changed, 1102 insertions, 447 deletions
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 Binary files differindex e62eb1541..3e1cf4ec0 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf 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 Binary files differindex 2f5997597..9a9480dcf 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf 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 |