Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ConTeXt Lua code directly #71

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
8 changes: 4 additions & 4 deletions optex/base/f-lmfonts.opm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
\_famdecl [Latin Modern] \LMfonts {TeX Gyre fonts based on Coputer Modern}
{\roman \sans \quotset \ttset \ttprop \ttlight \ttcond \upital
\dunhill submods:\caps \slant \nbold \bolder} {\rm \bf \it \bi \tt} {LM}
{[lmroman10-regular]}
{\_def\_fontnamegen {[\_optname{lm\_subfamV.\_currV}]:\_fontfeatures}}
{lmroman10-regular}
{\_def\_fontnamegen {\_optname{lm\_subfamV.\_currV}:\_fontfeatures}}

\_wlog{\_detokenize{%
Modifiers (selects subfamily):^^J
Expand Down Expand Up @@ -106,12 +106,12 @@ Note: Text fonts support optical sizes, but LatinModern-Math only for scripts.^^
\_onlyif subfam=tt: {\_fvars r b isl bisl }}
\_moddef \caps {\_onlyif subfam=rm,tt: {\_fvars rc . ic . }}

\_def \_tryloadtt {\_fontdef\_tentt{\_LMfonts \_addto\_fontfeatures{-tlig;}\_ttset \_rm}}
\_def \_tryloadtt {\_fontdef\_tentt{\_LMfonts \_addto\_fontfeatures{tlig=no;}\_ttset \_rm}}
\_private \LMfonts \ttset ; % used in \_tryloadtt

\_initfontfamily % new font family must be initialized

\_loadmath {[latinmodern-math]}
\_loadmath {latinmodern-math}

\_endcode

Expand Down
4 changes: 2 additions & 2 deletions optex/base/f-technika.opm
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

\_famdecl [Technika] \Technika {Fonts from visual style of CTU in Prague}
{\caps \light \book} {\rm \bf \it \bi \stencil} {}
{[Technika-Regular]}
{\_def\_fontnamegen {[Technika\_stencilV-\_currV]:\_capsV\_fontfeatures}}
{Technika-Regular}
{\_def\_fontnamegen {Technika\_stencilV-\_currV:\_capsV\_fontfeatures}}

\_wlog{\_detokenize{%
Modifiers:^^J
Expand Down
109 changes: 24 additions & 85 deletions optex/base/fonts-select.opm
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
The \`\_tryloadtt` is implemented differently because we want to keep
family independence for `\tt` macro, see section~\ref[tt].
So, `\_tryloadtt` is defined constantly as \"loading `\tt` font" and it is
not re-defined to `\relax`. On the other hand, `\_tryloadtt` is
re-defined in the \^`\initunifonts` macro or when
\~`\famvardef``\tt` is used.
not re-defined to `\relax`. \`\_ttunifont` is default font for `\tt`
variant. User can re-define it or use \^`\famvardef``\tt`.
\_cod -----------------------------

\_def\_reloading{\_loadf{rm}\_tenrm \_loadf{bf}\_tenbf \_loadf{it}\_tenit \_loadf{bi}\_tenbi}
\_def\_loadf#1#2{\_sdef{_tryload#1}{\_ifmmode \_else \_resizefont{#1}#2\_fi}}
\_def\_tryloadtt{\_resizefont{tt}\_tentt} % only in TFM mode
\_def\_tryloadtt {\_begingroup \_let\_fontnamegen\_ttunifont % \tt uses \_ttunifont
\_resizefont{tt}\_tentt\_relax \_ea\_endgroup \_ea\_let \_ea\_tentt \_the\_tentt}%
\_def\_ttunifont{lmmono10-regular:\_fontfeatures-tlig;}

\_let\_tryloadrm=\_relax
\_let\_tryloadbf=\_relax
Expand Down Expand Up @@ -66,48 +67,37 @@
The <variant-name> is `rm` or `bf` or `it` or `bi` or `tt`.
The new <font-switch> is declared (roughly speaking) by:
\begtt \catcode`<=13
\_font <font switch> = <fontname of>\_ten<variant-name> \_sizespec % in TFM mode
\_font <font switch> = {\_fontnamegen} \_sizespec % in OTF mode
\_font <font switch> = <fontname of>\_ten<variant-name> \_sizespec
% or if "\_fontnamegen" is defined:
\_font <font switch> = {\_fontnamegen} \_sizespec
\endtt
The font is loaded by \`\_doresizefont``<font switch>`. This macro has
meaning \`\_doresizetfmfont` in TFM mode (default in format) and it
switches to \^`\_doresizeunifont` when \^`\initunifonts` is used.\nl
I.e. there is a fallback to TFM mode if \^`\_fontnamegen` is not defined.
The font is loaded by \`\_doresizefont``<font switch>`.\nl
The `<fontname of>` is generated by the `\fontname` \TeX/ primitive where
\`\_rfontskipat` removes the `at<dimen>` part of the `\fontname` output.\nl
The \`\_whatresize` is defined as `<variant-name>`.\nl
The \^`\_fontloaded``<font switch>` is a macro which can be used for
post-processing when a font is loaded.
The \^`\_fontnamegen` expands to the font name/file:font-features
depending on the current font context.
\_cod -----------------------------

\_def\_resizefont#1#2{%
\_edef\_whatresize{#1}\_doresizefont#2\_relax \_fontloaded #2%
\_lastmagsize=\_zo
\_if t\_ignoresecond#1\_else \_slet{_tryload#1}{_relax}\_fi
}
\_def\_doresizetfmfont#1{\_logfont{#1}%
\_ea\_font\_ea#1\_ea\_rfontskipat
\_fontname \_cs{_ten\_whatresize} \_relax\_space \_sizespec \_relax
}
\_let\_doresizefont=\_doresizetfmfont
\_def\_logfont#1{} % default is no logging of used fonts

\_def\_rfontskipat#1{\_ifx#1"\_ea\_rfskipatX \_else\_ea\_rfskipatN\_ea#1\_fi}
\_def\_rfskipatX #1" #2\_relax{"\_whichtfm{#1}"}
\_def\_rfskipatN #1 #2\_relax{\_whichtfm{#1}}

\_doc -----------------------------
\`\_doresizeunifont``<font-switch>` implements the OTF mode of
loading fonts \^`\_doresizefont`.
There is a fallback to TFM mode if \^`\_fontnamegen` is not defined.\nl
The \^`\_fontnamegen` expands to the font name/file:font-features
depending on the current font context.
\_cod -----------------------------

\_def\_doresizeunifont #1{\_logfont{#1}%
\_ifx\_fontnamegen\_undefined \_doresizetfmfont#1\_else
\_def\_doresizefont #1{\_logfont{#1}%
\_ifx\_fontnamegen\_undefined
\_ea\_font\_ea#1\_ea\_rfontskipat
\_fontname \_cs{_ten\_whatresize} \_relax\_space \_sizespec \_relax
\_else
\_font#1={\_fontnamegen} \_sizespec \_relax \_setwsp#1\_relax
\_fi
}
\_def\_logfont#1{} % default is no logging of used fonts

\_def\_rfontskipat #1 #2\_relax{\_whichtfm{#1}}

\_doc -----------------------------
If a font is loaded by \^`\_resizefont` or \^`\resizethefont` then the
Expand All @@ -128,34 +118,11 @@
\_def\_newfontloaded #1{}

\_doc -----------------------------
\`\initunifonts` macro extends \LuaTeX's font capabalities,
in order to be able to load Unicode fonts. Unfortunately, this part of
\OpTeX/ depends on the `luaotfload` package, which adapts Con\TeX/t's generic
font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions
from \LaTeX's `luatexbase` namespace, we provide our own replacements.
Moreover, `\initunifont` switches with
the \^`\_doresizefont` macro to OTF mode which is represented by the
macro \^`\_doresizeunifont`.
Finally, \^`\initunifonts` sets itself to relax because we don't want to do
this work twice.\nl
\`\_ttunifont` is default font for `\tt` variant.
User can re-define it or use \^`\famvardef``\tt`.
For backwards compatibility we define `\initunifonts` as `\relax` (it is
done automatically now).
\_cod -----------------------------

\_def\_initunifonts {%
\_directlua{%
require('luaotfload-main')
luaotfload.main()
optex_hook_into_luaotfload()
}%
\_gdef\_rfskipatX ##1" ##2\_relax{"##1"}%
\_global\_let \_doresizefont=\_doresizeunifont
\_gdef\_tryloadtt {\_begingroup \_let\_fontnamegen\_ttunifont % \tt uses \_ttunifont
\_resizefont{tt}\_tentt\_relax \_ea\_endgroup \_ea\_let \_ea\_tentt \_the\_tentt}%
\_global\_let \_initunifonts=\_relax % we need not to do this work twice
\_global\_let \initunifonts=\_relax
}
\_def\_ttunifont{[lmmono10-regular]:\_fontfeatures-tlig;}
\_let\_initunifonts \_relax

\_public \initunifonts ;

Expand Down Expand Up @@ -503,7 +470,7 @@
special font features provided by \LuaTeX/ (and by \XeTeX/ too but it is not
our business). The \`\setwordspace` recalculates the `\fontdimen2,3,4`
of the font using the \`\setwsp` macro which is used by the
\^`\_doresizeunifont` macro. It activates a dummy font feature `+Ws` too in
\^`\_doresizefont` macro. It activates a dummy font feature `+Ws` too in
order the font is reloded by the `\font` primitive (with independent
`\fontdimen` registers).
\_cod -----------------------------
Expand Down Expand Up @@ -981,34 +948,6 @@ with Unicode fonts loaded by \^`\fontfam`.

\printdoctail fams-ini.opm

\secc[exfont] Notices about extension of `\font` primitive
%---------------------------------------------------------

Unicode fonts are loaded by extended `\font` primitive. This extension is
not activated in \OpTeX/ by default, \^`\initunifonts` macro activates it.
You need not use \^`\initunifonts` explicitly if \^`\fontfam` macro is
used because \^`\fontfam` runs it internally.

The \^`\initunifonts` loads the Lua code from the Luaotfload package which
implements the `\font` primitive extension. See its
documentation `luaotfload-latex.pdf` for information about
all possibilities of extended `\font` primitive.

The \OpTeX/ format is initialized by `luatex` engine by default but
you can initialize it by `luahbtex` engine too. Then the harfbuzz library is
ready to use for font rendering as an alternative to built-in font renderer
from Luaotfload. The harfbuzz library gives more features for rendering
Indic and Arabic scripts. But it is not used as default, you need to specify
`mode=harf` in the fontfeatures field when `\font` is used. Moreover, when
`mode=harf` is used, then you must specify `script` too. For example

\begtt
\font\devafont=[NotoSansDevanagari-Regular]:mode=harf;script=dev2
\endtt
%
If the `luahbtex` engine is not used then `mode=harf` is ignored. See
Luaotfload documentation for more information.

\endinput

2021-07-16 \initunifonts: optex_hook_into_luaotfload added.
Expand Down
14 changes: 7 additions & 7 deletions optex/base/math-unicode.opm
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,23 @@
\_cod -----------------------------

\_def\_normalunimath{%
\_loadumathfamily 1 {\_unimathfont}{} % Base font
\_loadumathfamily 0 {\_unimathfont}{} % Base font
\_loadmathfamily 4 rsfs % script
\_setunimathdimens
}%
\_def\_boldunimath{%
\_ifx\_unimathboldfont \_undefined
\_loadumathfamily 1 {\_unimathfont}{embolden=1.7;} % Base faked bold
\_loadumathfamily 0 {\_unimathfont}{embolden=1.7;} % Base faked bold
\_else
\_loadumathfamily 1 {\_unimathboldfont}{} % Base real bold font
\_loadumathfamily 0 {\_unimathboldfont}{} % Base real bold font
\_fi
\_loadmathfamily 4 rsfs % script
\_setunimathdimens
}%
\_def\_setunimathdimens{% PlainTeX sets these dimens for 10pt size only:
\_delimitershortfall=0.5\_fontdimen6\_textfont1
\_nulldelimiterspace=0.12\_fontdimen6\_textfont1
\_setbox0=\_hbox{\_everymath{}$\_fam1\_displaystyle{0\_atop0}$}%
\_delimitershortfall=0.5\_fontdimen6\_textfont0
\_nulldelimiterspace=0.12\_fontdimen6\_textfont0
\_setbox0=\_hbox{\_everymath{}$\_displaystyle{0\_atop0}$}%
\_Umathfractiondelsize\_displaystyle = \_dimexpr(\_ht0-\_Umathaxis\_displaystyle)*2\_relax
\_setbox0=\_box\_voidbox
}
Expand All @@ -101,7 +101,7 @@
\begtt
\loadmath{[xitsmath-regular]}
\def\_boldmath{%
\_loadumathfamily 1 {[xitsmath-bold]}{} % Base font
\_loadumathfamily 0 {[xitsmath-bold]}{} % Base font
\_loadmathfamily 4 rsfs % script
\_loadumathfamily 5 {[xitsmath-regular]}{}
\_def\|{\_Udelimiter 0 5 "02016 }% % norm delimiter from family 5
Expand Down
1 change: 1 addition & 0 deletions optex/base/optex.ini
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
\_directlua{
% preload OpTeX's Lua code into format as bytecode
lua.bytecode[1] = assert(loadfile(kpse.find_file("optex", "lua")))
lua.bytecode[2] = assert(loadfile(kpse.find_file("luatex-fonts-merged", "lua")))
}

\_everyjob = {%
Expand Down
81 changes: 56 additions & 25 deletions optex/base/optex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ function callback.add_to_callback(name, fn, description)
return call_callback(name, ...)
end)
else
err("cannot add to callback '"..name.."' - no such callback exists")
err("cannot add to callback '"..name.."' - it doesn't exist or is disabled")
end

-- add function to callback list for this callback
Expand Down Expand Up @@ -264,6 +264,13 @@ function callback.remove_from_callback(name, description)
return fn, description
end
--
-- Disable a callback completely.
function callback.disable_callback(name)
callback_register(name, false)
-- don't allow adding functions from now on
callback_types[name] = nil
end
--
-- helper iterator generator for iterating over reverselist callback functions
local function reverse_ipairs(t)
local i, n = #t + 1, 1
Expand Down Expand Up @@ -396,6 +403,7 @@ luatexbase = {
create_callback = callback.create_callback,
add_to_callback = callback.add_to_callback,
remove_from_callback = callback.remove_from_callback,
disable_callback = callback.disable_callback,
call_callback = callback.call_callback,
callbacktypes = {}
}
Expand Down Expand Up @@ -573,31 +581,54 @@ callback.add_to_callback("pre_shipout_filter", function(list)
return tonode(list)
end, "_colors")
--
-- We also hook into `luaotfload`'s handling of color. Instead of the default
-- behavior (inserting colorstack whatsits) we set our own attribute. The hook
-- has to be registered {\em after} `luaotfload` is loaded.
function optex_hook_into_luaotfload()
if not luaotfload.set_colorhandler then
return -- old luaotfload, colored fonts will be broken
end
local setattribute = direct.set_attribute
local token_setmacro = token.set_macro
local color_count = registernumber("_colorcnt")
local tex_getcount, tex_setcount = tex.getcount, tex.setcount
luaotfload.set_colorhandler(function(head, n, rgbcolor) -- rgbcolor = "1 0 0 rg"
local attr = tonumber(token_getmacro("_color::"..rgbcolor))
if not attr then
attr = tex_getcount(color_count)
tex_setcount(color_count, attr + 1)
local strattr = tostring(attr)
token_setmacro("_color::"..rgbcolor, strattr)
token_setmacro("_color:"..strattr, rgbcolor)
-- no stroke color set
end
setattribute(n, color_attribute, attr)
return head, n
end)
-- Load ConTeXt font loading code with some preparations
logs = logs or {}
function texio.reporter(...)
if trace_context then
texio.write_nl(...)
end
end
--
-- Attribute 0 must be 0 for ConTeXt
tex.setattribute(0, 0)
--
local attrs = {}
attributes = attributes or {}
function attributes.private(name)
local num = attrs[name]
if not num then
num = alloc.new_attribute(name)
attrs[name] = num
end
return num
end
--
local saved = callback.register
function callback.register(cb, fn)
if fn == false then
callback.disable_callback(cb)
else
callback.add_to_callback(cb, fn, "context")
end
end
--
utf = unicode.utf8
--
-- load the bulk of the ConTeXt code
lua.bytecode[2]()
--
-- Register callbacks
callback.disable_callback("ligaturing")
callback.disable_callback("kerning")
callback.add_to_callback("pre_linebreak_filter", nodes.simple_font_handler, "context")
callback.add_to_callback("hpack_filter", nodes.simple_font_handler, "context")
callback.add_to_callback("define_font", fonts.definers.read, "context")
--
callback.register = saved

-- "\font=name" is a font name lookup with fallback to file name, we don't
-- support font name, yet
fonts.names.resolve = function() end

-- History:
-- 2021-07-16 support for colors via attributes added
Expand Down
Loading