diff options
| author | Hans Hagen <pragma@wxs.nl> | 2021-01-11 18:09:53 +0100 | 
|---|---|---|
| committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2021-01-11 18:09:53 +0100 | 
| commit | 980ad5b78d69aa8abfb093c7e6729b0024ce0b49 (patch) | |
| tree | cc3ff7b95fe9e334f11dc97f04587914321fca6d | |
| parent | 3a048d406386e8b8eb5c1315e57d271237da89be (diff) | |
| download | context-980ad5b78d69aa8abfb093c7e6729b0024ce0b49.tar.gz | |
2021-01-11 16:30:00
25 files changed, 1574 insertions, 471 deletions
diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf Binary files differindex 52c93219f..635e56000 100644 --- a/doc/context/documents/general/manuals/luametatex.pdf +++ b/doc/context/documents/general/manuals/luametatex.pdf diff --git a/doc/context/sources/general/manuals/followingup/followingup-fonts.tex b/doc/context/sources/general/manuals/followingup/followingup-fonts.tex index a3059847e..2f7320b12 100644 --- a/doc/context/sources/general/manuals/followingup/followingup-fonts.tex +++ b/doc/context/sources/general/manuals/followingup/followingup-fonts.tex @@ -6,104 +6,376 @@  \startchapter[title={Scaled fonts}] -Although \CONTEXT\ is quite efficient with fonts there is always room for -improvement. However, after years of fine tuning the font mechanisms there was -not that much room left. On the average, given that \TEX\ is mostly about fonts, -what we have is quite okay, but for some scripts, like \CJK\ the demands on -resources can be rather high. This made me think of a different approach to -scaling. Nowadays fonts seldom come in design sizes. Also, in \CONTEXT\ \MKIV\ -and therefore \LMTX\ we always had so called dynamic features: apply additional -features locally, although that comes with a small penalty in performance, it -saves additional font instances. It is a good approach for the occasional small -stretch of glyphs, like small capped logos and such. - -Using a font at a larger size means that we need to provide \TEX\ with the right -dimensions: it needs them for instance for for braking paragraph into lines or -wrapping text in boxes. The amount of information that \TEX\ needs is small: only -dimensions. Of course there are ligatures and kerns but in so called base mode we -seldom have many. The data needed for node mode (used for more complex \OPENTYPE\ -fonts) can be shared and lives at the \LUA\ end. But even then the character -table is copied and scaled. Actually, we seldom need that information but it is -good to have it and in the case of virtual fonts it is needed. But, when a font -is used at a different size, and al the features are the same, we can think of -a different approach. - -That approach is tagged as \quote {dynamic font scaling}, which means that we -don't need to define a new font instance when the same feature set is used. Or -course in addition to this features one can still use the dynamic features. This -means that for instance chapter titling can use the bodyfont instance and just -apply additional scaling. Although for a normal run the number of loaded fonts is -normally small, and the number of instances also isn't that impressive it can -happen in a large document that you end up with a few dozen. That number can now -be reduced to half a dozen. - -Of course there can be side effects, which is why it's currently tagged as -experimental. There is also a small performance hit because we now need to track -it but that is gained back because we load less fonts and have less glyph runs. - -So how does it work? Here is an example: +\startsection[title={History}] + +The infrastructure for fonts makes for a large part of the code of any \TEX\ +macro package. We have to go back in time to understand why. When \TEX\ showed +up, fonts were collections of bitmaps and measures. There were at most 256 glyphs +in a font and in order to do its job, \TEX\ needed to know (and still needs to +know) the width, height and depth of glyphs. If you want ligatures it also needs +to know how to construct them from the input and when you want kerning there has +to be additional information about what neighboring glyphs need a kern in +between. Math is yet another subtask that demands extra information, like chains +of glyphs that grow in size and if needed even recipes of how to construct large +shapes from smaller ones. + +Fonts come in sizes, and for instance Latin Modern has quite a few variants where +the shapes are adapted to the size. This means that when you need a 9pt regular +shape alongside a 12pt one, two fonts have to be loaded. This is quite visible in +math where we have three related sizes: text, script and scriptscript, grouped in +so called families. + +Plenty has been written (in various documents that come with \CONTEXT) about how +this all works together and how it impacts the design of the system, so here I +just give a short summary of what a font system has to deal with. + +\startitemize +\startitem +    In a bodyfont setup different sizes (9pt, 10pt, 12pt) can have their own +    specific set of fonts. This can result in quite some definitions that relate +    to the style, like regular, bold, italic, bolditalic, slanted and +    boldslanted, etc. When possible loading the fonts is delayed. +\stopitem +\startitem +    Some font designs have different shapes per bodyfont size. A minor +    complication is that when one is missing some heuristic best match choice +    might be needed. +\stopitem +\startitem +    Within a bodyfont size we distinguish size variants. We can go smaller (x and +    xx), for instance when we use sub- and superscripts in text, or we can go +    larger, for instance in titling (a, b, c, d, \unknown). Fortunately most of +    the loading of these can be delayed too. +\stopitem +\startitem +    When instances are not available, scaling can be used, as happens for +    instance with 11pt in Computer Modern. Actually, this is why in \CONTEXT\ we +    default to 12pt, because the scaled versions didn't look as nice as the +    others. +\stopitem +\startitem +    Special features, like smallcaps or oldstyle numerals, can demand their own +    definitions. More loading and automatic definitions can be triggered by sizes +    needed in for instance scripts and titling. +\stopitem +\startitem +    A document can have a mixed setup, that is: use different font designs in one +    document, so some kind of namespace subsystem is needed. +\stopitem +\startitem +    In traditional eight bit engine the dependency of hyphenation on the encoding +    of a font can result in the necessity to load a font multiple times in +    different encodings, something that depends on the language mix used. +\stopitem +\startitem +    In the more modern \OPENTYPE\ fonts combinations of features can demand +    additional instances (one can thing of language|/|script combinations, +    substitutions in base mode, special effects like boldening, color fonts, +    etc.). +\stopitem +\startitem +    Math is complicated by the fact that alphabets come from different fonts +    (sometimes a font has several alphabets which means that some mapping can be +    needed). Operating on the size, shape, encoding and style axes puts some +    demands on the font system. Add to this (often) partial (due to lack of +    fonts) bold support and it gets even more complicated. +\stopitem +\startitem +    There is additional math auto|-|definition and loading code for the sizes +    used in text scripts and titling. +\stopitem +\stopitemize + +All this has resulted in a pretty complex subsystem. Although going \OPENTYPE\ +(and emulated \OPENTYPE\ with \TYPEONE\ fonts as we do in \MKIV) removes some +complications, like encodings, it does also add complexity because of the many +possible font features, either or not dependent on script and language. + +Also, in order to let a font subsystem not impact performance to much, let alone +extensive memory usage, the \CONTEXT\ font subsystem is rather optimized. The +biggest burden comes from fonts that have a dynamic (adaptive) definition because +then we need to do quite a bit of testing per font switch, but even that has +always been rather fast. + +\stopsection + +\startsection[title={Reality}] + +In \MKIV\ and therefore also in \LMTX\ more font magic happens. The initial node +lists that makes up a box or paragraph can get manipulated in several ways and +often fonts are involved. The mentioned font features can be defines static (as +part of the definition) or dynamic (resolved on the spot at the cost of some +overhead). Characters can be remapped, fonts can be replaced. The math subsystem +in \MKIV\ was different right from the start: we use a limited number of families +(regular, bold, l2r and r2l), and stay abstract till the moment we need to deal +with the specific alphabets. But still, in \MKIV, we have the families with three +fonts. + +In the \LUAMETATEX\ manual we show some math magic and we do so for different +fonts. As a side effect, we set up half a dozen bodyfont collections. Even with +delayed and shared font loading, we end up with 158 instances but quite a bit of +them are math fonts, at least six per bodyfont size: regular and bold (boldened) +text, script and scriptscript. Of course most are just copies with different +scaling that reuse already loaded resources. + +If we look at the math fonts that we use today, there is however quite some +overlap. It starts with a text font. From that script and scriptscript variants +are derived, but often these variants use many text size related shapes too. Some +shapes get alternatives (from the \type {ssty} feature), and the whole clone get +scaled. But, much of the logic of for instance extensibles is the same. + +A similar situation happens with for instance large \CJK\ fonts: there are hardly +any advanced features involved there, so any size is basically a copy with scaled +dimensions, and these fonts can be real huge! + +Actually, when we talk about features, in many cases in \CONTEXT\ you don't +define them as part of the font. For instance small caps can best be triggered by +using a dynamic feature: applied to a specific stretch of text. When the font +handler does its work there are actually four cases: no features get applied, +something that for instance happens with most monospaced fonts, base mode is +used, which means that the \TEX\ machinery takes care of constructing ligatures +and injecting kerns, and node mode, where \LUA\ handles the features. The fourth +case is a special case of node mode where a different features set is applied. +\footnote {We also have so called plug mode where an external rendered can do the +work but that one is only around for some experiments during Idris' font +development.} At the cost of some extra overhead (for each node mode run) dynamic +features are quite powerful and save quite some memory and definitions. The +overhead comes from much more testing regarding the font we deal with because +suddenly the same font can demand different treatments, depending on what dynamic +features is active. + +Although the font handling is responsible for much of the time spent in \LUA, it is +still reasonable given what has to be done. Actually, because we have an extensible +system, it's often the extensions that takes additional runtime. Flexibility comes +at a price. + +\stopsection + +\startsection[title={Progress}] + +At some point I started playing with realtime glyph scaling. Here realtime means that +it doesn't depend on the font definition. To get an idea, here is an example:  \startbuffer -\definescaledfont[MyLargerFontA][scale=2000,style=bold] - -test {\MyLargerFontA test} test +test {\glyphxscale 2500 test} test  \stopbuffer  \typebuffer -This gives: -  \getbuffer -You can also say: +The glyphs in the current font get scaled horizontally without the need for an extra +font instance. Now, this kind of trickery puts some constraints on the font handling, +as is demonstrated in the next example. We use Latin Modern because that font has +all these ligatures:  \startbuffer -\definescaledfont[MyLargerFontB][xscale=1200,yscale=2000,style=bold] - -test {\MyLargerFontB test} test +\definedfont[lmroman-regular*default]% +e{\glyphxscale 2500 ff}icient +ef{\glyphxscale 2500 f}icient +ef{\glyphxscale 2500 fi}cient +e{\glyphxscale 2500 ffi}cient  \stopbuffer  \typebuffer -Which scaled the over two axis: +{\getbuffer} + +So, in order to deal with this kind of scaling, we now operate not only on the +font (id) and dynamic feature axes, but also on the scales of which we have three +variants: glyph scale, glyph xscale and glyph y scale). There is actually also a +state dimension but we leave that for now. Think of flagging glyphs as initial or +final. This brings the number of axis to six. It is important to stress that in +these examples the same font instance is used! + +Just for the record: there are several approaches to switching fonts possible but +for now we stick to a simple font id switch plus glyph scale settings at the +\TEX\ end. A variant would be to introduce a new mechanism where id's and scales +go together but for now I see no real gain in that. + +\stopsection + +\startsection[title={Math}] + +Given what is written in the previous sections, a logical question is if we can +apply scaling to math and the answer is \quotation {yes, we can}. But we actually +go a bit further and that is partly due to some other properties of the engine. + +From \PDFTEX\ the \LUATEX\ engines inherited character protrusion and glyph +expansions, aka hz. However, where in \PDFTEX\ copies of the font are made that +carry the expanded dimensions, in \LUATEX\ at some point this was replaced by an +expansion field in the glyph and kern nodes. So, instead of changing the font id +of expanded glyphs, the same id is used but with the applied expansion factor set +in the glyph. A side effect was that in places where dimensions are needed, calls +to functions that calculate the expanded widths on request (as these can change +during linebreak calculations) in combination with accessing font dimensions +directly, we now always use accessor functions. This level of abstraction is even +more present in \LUAMETATEX. This means that we have an uniform interface to +fonts and as a side effect scaling is to be dealt with in only a few places in +the code. + +Now, in math we have a few more complications. First of all, we have three sizes +to consider and we also have lots of parameters that depend on the size. But, as +I wanted to be able to apply scaling to math, the whole machinery was also +abstracted in a way that, at the cost of some extra overhead, made it easier to +work with scaled glyph properties. This means that we can stick to loading only +one bodyfont size of math (note that each math family has three sizes, where the +script and script sizes can have different, fine tuned, shapes) and just scale +that on demand. + +Once all that was in place it was a logical next step to see if we could actually +stick to one instance. Because in \LUAMETATEX\ we try to load fonts efficiently +we store only the minimally needed information at the \TEX\ end. A font with no +math therefore has less data per glyph. Again, this brings some abstraction that +actually helped to implement the one instance mechanism. A math glyph has +optional lists of increasing sizes and vertical or horizontal extensibles. So +what got added was an optional chain of smaller sizes. If a character has 3 +different glyphs for the three sizes, the text glyph has a pointer to the script +glyph which in turn has a pointer to the scriptscript glyph. This means that when +the math engine needs a specific character at a given size (text, script, +scriptscript) we just follow that chain. + +In an \OPENTYPE\ math font the script and scriptscript sizes are specified as +percentages of the text size. So, when the dimensions of a glyph are needed, we +just scale on the fly. Again this adds some overhead but I'm pretty sure that no +user will notice this. + +So, to summarize: if we need a character at scriptscript size, we access the text +size glyph, check for a pointer to a script size, go there, and again check for a +smaller size. We just use what fits the bill. And, when we need dimensions we +just scale. In order to scale we need the relative size, so we need to set that +up when we load the font. Because in \CONTEXT\ we also can assemble a virtual +\OPENTYPE\ font from \TYPEONE\ fonts, it was actually that (old) compatibility +feature that took most time to adapt, not so much because it is complicates but +because in \LMTX\ we have to bypass some advanced loading mechanisms. + +The end result is that for math we now only need to define two fonts per bodyfont +setup: regular and bold at the natural scale (normally 10pt) and we share these +for all sizes. It is because of this and what we describe in the next section +that the 158 instances for the \LUAMETATEX\ manual can now be brought down to 30. + +\stopsection + +\startsection[title={Text}] + +Sharing instances in text mode is relatively simple, although we do have to keep +in mind that these are extra axis when dealing with font features: two +neighboring glyphs with the same font id and dynamics but with different scales +are effectively from different fonts. + +Another complication is that when we use font fallbacks (read: take missing +glyphs from another font) we no longer have a dedicated instance but use a shared +one. This in itself if not a problem but we do need to handle specified relative +scales. This was not that hard to patch in \CONTEXT\ \LMTX. + +We can enforce aggressive font sharing with: -\getbuffer +\starttyping +\enableexperiments[fonts.compact] +\stoptyping + +After that we often use less instances. Just to give an idea, on the \LUAMETATEX\ +manual we get these stats: + +\starttyping +290 pages, 10.8 sec, 292M lua, 99M tex, 158 instances +290 pages,  9.5 sec, 149M lua, 35M tex,  30 instances +\stoptyping -The low level implementation uses the two variables \type {\glyphxscale} and -\type {\glyphyscale} that take a number. As with other \TEX\ scaling related -variables, a value of 1000 represents 1.0 so we have three digits precision. +So, we win on all fronts when we use this glyph scale mechanism. The magic +primitive that deals with this is \type {\glyphscale} which accepts a number, +where \type {1200} and \type {1.2} both mean scaling to 20\percent\ more than +normal. But one can best not use this primitive directly. -Because we just scale, the next also works: +A specific font can be defined using the \type {\definefont} command. In \LMTX\ a +regular scaler can be followed by two scale factors. The nest example +demonstrates this:  \startbuffer -test {\MyLargerFontB test {\em test} test} test +\definefont[FooA][Serif*default @ 12pt 1800 500] +\definefont[FooB][Serif*default @ 12pt 0.85 0.4] +\definefont[FooC][Serif*default @ 12pt] + +\definetweakedfont[runwider] [xscale=1.5] +\definetweakedfont[runtaller][yscale=2.5,xscale=.8,yoffset=-.2ex] + +{\FooA test test \runwider test test \runtaller test test}\par +{\FooB test test \runwider test test \runtaller test test}\par +{\FooC test test \runwider test test \runtaller test test}\par  \stopbuffer  \typebuffer -The nested emphasis still works: +We also use the new \type {\definetweakedfont} command here. This example not +only shows the two scales but also introduces the offset.  \getbuffer -For now we only have a simple user interface but it might eventually be more -integrated. For instance, we can consider defining \type {\tfa} and friends this -way. +Here is another one: + +\startbuffer +\definetweakedfont[squeezed] [xscale=0.9] +\definetweakedfont[squeezed] [xscale=0.9] + +\startlines +$a = b^2 + \sqrt{c}$ +{\squeezed $a = b^2 + \sqrt{c}$} +\stoplines +\stopbuffer + +\typebuffer + +\getbuffer -In order to make it useful, math is also supported: +Watch this:  \startbuffer -\definescaledfont[MyLargerFontC][xscale=1200,yscale=2000] +\startcombination[4*1] +    {\bTABLE +        \bTR \bTD foo \eTD \bTD[style=\squeezed] $x = 1$ \eTD \eTR +        \bTR \bTD oof \eTD \bTD[style=\squeezed] $x = 2$ \eTD \eTR +     \eTABLE} +    {local} +    {\bTABLE[style=squeezed] +        \bTR \bTD $x = 1$ \eTD \bTD  $x = 3$ \eTD \eTR +        \bTR \bTD $x = 2$ \eTD \bTD  $x = 4$ \eTD \eTR +     \eTABLE} +    {global} +    {\bTABLE[style=\squeezed\squeezed] +        \bTR \bTD $x = 1$ \eTD \bTD  $x = 3$ \eTD \eTR +        \bTR \bTD $x = 2$ \eTD \bTD  $x = 4$ \eTD \eTR +     \eTABLE} +    {multiple} +\stopcombination +\stopbuffer -test {\MyLargerFontC test $\sqrt{x}$ test} test +\typebuffer + +\startlinecorrection +\getbuffer +\stoplinecorrection + +An additional style parameter is also honored: + +\startbuffer +\definetweakedfont[MyLargerFontA][scale=2000,style=bold] +test {\MyLargerFontA test} test  \stopbuffer  \typebuffer -gives: +This gives:  \getbuffer -You can actually use negative values, as is demonstrated in the following +Just for the record: the Latin Modern fonts, when set up to use design sizes, will +still use the specific size related files. + +\stopsection + +\startsection[title={Hackery}] + +You can actually use negative scale values, as is demonstrated in the following  code:  \startbuffer @@ -131,45 +403,8 @@ gives:  \getbuffer  \stoplinecorrection -Because loading and switching fonts in \CONTEXT\ is rather efficient, the gain in -performance is less than you expect. After all, not all time is spent on fonts. Of -course for huge \CJK\ fonts it does make a difference. But, when we do a massive switch -to a different body font, we can save a little more. Think of definitions like: - -\starttyping -\definescaledfontbody[BigBodyFont]     [1.200] -\definescaledfontbody[VeryBigBodyFont] [1.440] -\definescaledfont    [MyLargerFont]    [xscale=1.200,yscale=2.000] -\stoptyping - -And then: - -\starttyping -\setuphead[title][style=\MyLargerFont\bf] -\stoptyping - -The savings in runtime can be quite noticeable now, for instance this: - -\starttyping -\dorecurse {100} { -    \starttitle[title={Test #1] -        \samplefile{ward}\par -        \start \bf -            \samplefile{ward}\par -        \stop -        \start \BigBodyFont \bf -            \samplefile{ward}\par -        \stop -    \stoptitle -} -\stoptyping - -Speeds up a bit for Pagella and even more when we use Cambria. Keep in mind that -that a body font switch also involves setting up some math. Anyway, as a proof of -concept it worked out well. - -Glyphs can have offsets and these are used for implementing \OPENTYPE\ features. However, -they are also available at the \TEX\ end. Take this +Glyphs can have offsets and these are used for implementing \OPENTYPE\ features. +However, they are also available at the \TEX\ end. Take this  \startbuffer  \ruledhbox{ @@ -225,57 +460,136 @@ Both these lines produce the same integer:  \getbuffer  \stoplines -When there is a fraction, the value is multiplied by 1000. - -So how should this be further integrated? If we drop design sizes at the file -definition level the whole font mechanism could be simplified a lot, but we cannot -do that. Another approach is to let users use the previously mentioned more low -level commands. A but of help can be provided with a command like - -\starttyping -\enableautoglyphscaling -\stoptyping - -which pays of when it is issues before \type {\starttext} and before a body fonts -gets defined because it does some overloading of defining commands. At the brink -of 2021 I'm not sure yet what is best. One reason is that a compatibility layer -is not really compatible because glyph scaling gives slightly different scaled in -practice (which relates to some old time accuracy hackery). This sounds worse -that it is because in practice scaling is done for sections heads and so, which -are less present and don't interfere with the running text. - -Let me stress once more: if you need this kind of scaling it pays off. If you -load multiple instances of large (e.g.\ \CJK) fonts, it makes sense too. But, for -instance on a document like the \LUAMETATEX\ manual it only saves 2 instances on -158, and those are the few bold fonts used for titling. - -That said, here is another example: +You can do strange things with these primitives but keep in mind that you can +also waste the defaults. -\startbuffer +\startbuffer[definition]  \def\UnKernedTeX    {T%     {\glyph xoffset -.2ex yoffset -.4ex `E}%     {\glyph xoffset -.4ex options "60 `X}} +\stopbuffer +\startbuffer[example]  We use \UnKernedTeX\ and {\bf \UnKernedTeX} and {\bs \UnKernedTeX}:  the slanted version could use some more left shifting of the E.  \stopbuffer -\typebuffer +\typebuffer[definition,example]  This gives is the \TEX\ logos (but of course we normally use the real ones  instead). -\getbuffer +\startnarrower +    \darkred \getbuffer[definition,example] +\stopnarrower + +Because offsets are (also) used for handling font features like mark and cursive +placement as well as special inter|-|character positioning, the above is +suboptimal. Here is a better alternative: + +\startbuffer[definition] +\def\UnKernedTeX +  {T\glyph left .2ex raise -.4ex `E\glyph left .4ex `X\relax} +\stopbuffer + +\typebuffer[definition] + +The result is the same: + +\startnarrower +    \darkgreen \getbuffer[definition,example] +\stopnarrower + +But anyway: don't over|-|do it. We could deal with such cases for decades without +these fancy new features. The next example show margins in action: + +\startlinecorrection +\bTABLE[align=middle,width=.33\textwidth] +    \bTR +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph                      `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph raise 3pt            `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph raise -3pt           `M}>\eTD +    \eTR +    \bTR[frame=off] +        \bTD \tttf            \eTD +        \bTD \tttf raise  3pt \eTD +        \bTD \tttf raise -3pt \eTD +    \eTR +    \bTR +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left  3pt            `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph           right  2pt `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left  3pt right  2pt `M}>\eTD +    \eTR +    \bTR[frame=off] +        \bTD \tttf left  3pt           \eTD +        \bTD \tttf           right  2pt\eTD +        \bTD \tttf left  3pt right  2pt\eTD +    \eTR +    \bTR +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left -3pt            `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph           right -2pt `M}>\eTD +        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left -3pt right -2pt `M}>\eTD +    \eTR +    \bTR[frame=off] +        \bTD \tttf left -3pt            \eTD +        \bTD \tttf           right -2pt \eTD +        \bTD \tttf left -3pt right -2pt \eTD +    \eTR +\eTABLE +\stoplinecorrection + +Here is another way of looking at it: + +\startbuffer +\glyphscale 4000 +\vl\glyph                        `M\vl\quad +\vl\glyph raise  .2em            `M\vl\quad +\vl\glyph left   .3em            `M\vl\quad +\vl\glyph             right  .2em`M\vl\quad +\vl\glyph left  -.2em right -.2em`M\vl\quad +\vl\glyph raise -.2em right  .4em`M\vl +\stopbuffer + +\typebuffer + +The raise as well as left and right margins are taken into account when calculating the +dimensions of a glyph. + +{\getbuffer} + + +\stopsection + +\startsection[title={Implementation}] + +Discussing the implementation in the engine makes no sense here, also because +details might change. However, it is good to know that quite some properties +travel with the glyph nodes, for instance the scales and offsets. The dimensions +(width, height and depth) are not stored in the glyph node but calculated from +the font, scales and optionally the offsets and expansion factor. One problem is +that the more clever (and nice) solutions we cook up, the more it might impact +performance. So, I will delay some experiments till I have a more powerful +machine. + +One reason for {\em not} storing the dimensions in a glyph node is that we often +copy those nodes or change character fields in the font handler and we definitely +don't want the wrong dimensions there. At that moment, offsets and margin fields +don't reflect features yet, so copying them is no big deal. However, dimensions +are rather character bound so every time a character is set, we also would have +to set the dimensions. Even worse, when we can set them, the question arises if +they actually were already set explicitly. So, this is a can of worms we're not +going to open: the basic width, height and depth of the glyph as specified in the +font is used and combines with actual dimensions (likely already scaled according +the glyph scales) in offset and margin fields. + +Now, I have to admit that especially playing with using margins to glyphs instead +of font kerns is more of an experiment to see what the consequences are than a +necessity, but what would be the joy of \TEX\ without such experiments. And as +usual, in \CONTEXT\ these will become options in the font handler that one can +either or not enable. -After doing this with text, I wondered if we can avoid multiple sizes of an -otherwise same math font. Currently text, script and script script styles all use -the same font, but scaled. And, indeed, experiments show that this can be done, -although the math renderer had to be adapted to it. So, for now it's an -experiment. Users have to check if things are okay. Also, we have slightly -different rounding than with normal scaling. Of course the big advantage is that -we have less instances (math can add up more than text as every size has in fact -three instances). +\stopsection  \stopchapter @@ -294,7 +608,7 @@ three instances).  \starttext  \startbuffer -\definescaledfont[bfe][xscale=2000,yscale=6000,style=bf] +\definetweakedfont[bfe][xscale=2000,yscale=6000,style=bf]  \setuphead[chapter][style=\bfe] @@ -332,3 +646,8 @@ three instances).  % anything) on YT. Both examples of where (imo extensive) practicing real  % instruments can bring you with todays diverse equipment. These are interesting  % times (it's now last days of 2020). +% +% The initial \definescaledfont was replaced by \definetweakedfont in the first +% week of Januari 2021, when I watched the joyful covers of Peter Gabriels +% "Steam" by Yoyoka which shows that the future belongs to the real young kids +% (so much explosive creativity!) and not to the old folks. diff --git a/doc/context/sources/general/manuals/followingup/followingup-style.tex b/doc/context/sources/general/manuals/followingup/followingup-style.tex index 68b52043c..51519f137 100644 --- a/doc/context/sources/general/manuals/followingup/followingup-style.tex +++ b/doc/context/sources/general/manuals/followingup/followingup-style.tex @@ -3,6 +3,8 @@  \startenvironment followingup-style +\enableexperiments[fonts.compact] % needed for font chapter +  \usemodule[abbreviations-smallcaps]  \logo [LUAMETATEX] {LuaMeta\TeXsuffix} diff --git a/doc/context/sources/general/manuals/luametatex/luametatex.tex b/doc/context/sources/general/manuals/luametatex/luametatex.tex index 588cc8952..1327ea3a1 100644 --- a/doc/context/sources/general/manuals/luametatex/luametatex.tex +++ b/doc/context/sources/general/manuals/luametatex/luametatex.tex @@ -79,7 +79,7 @@  % 290 pages,  9.5 sec, 149M lua, 35M tex,  30 instances  \enableexperiments[fonts.compact] -\enabledirectives[fonts.injections.method=advance] +% \enabledirectives[fonts.injections.method=advance] % tricky ... not all xoffsets are advance robust  \pushoverloadmode \unprotect      % test code diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index ea233b8d2..d06fbe463 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@  %C therefore copyrighted by \PRAGMA. See mreadme.pdf for  %C details. -\newcontextversion{2021.01.08 11:44} +\newcontextversion{2021.01.11 16:28}  %D This file is loaded at runtime, thereby providing an  %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index ea64e263e..c36274955 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@  %D your styles an modules.  \edef\contextformat {\jobname} -\edef\contextversion{2021.01.08 11:44} +\edef\contextversion{2021.01.11 16:28}  %D For those who want to use this: diff --git a/tex/context/base/mkii/mult-cs.mkii b/tex/context/base/mkii/mult-cs.mkii index d2a51a8ab..d4b39ad3b 100644 --- a/tex/context/base/mkii/mult-cs.mkii +++ b/tex/context/base/mkii/mult-cs.mkii @@ -1131,6 +1131,7 @@  \setinterfaceconstant{reference}{odkaz}  \setinterfaceconstant{referencemethod}{referencemethod}  \setinterfaceconstant{referenceprefix}{referenceprefix} +\setinterfaceconstant{referencetext}{referencetext}  \setinterfaceconstant{referencing}{odkazujici}  \setinterfaceconstant{region}{region}  \setinterfaceconstant{regionin}{oblastuvnitr} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index da0388cf0..49c850c9b 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@  % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.01.08 11:44} +\newcontextversion{2021.01.11 16:28}  %D This file is loaded at runtime, thereby providing an excellent place for hacks,  %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 23eabed71..93744dfda 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@  %D {YYYY.MM.DD HH:MM} format.  \edef\contextformat {\jobname} -\edef\contextversion{2021.01.08 11:44} +\edef\contextversion{2021.01.11 16:28}  %D Kind of special: diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 74deffd1f..d55bfa411 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 27cd2367e..78ade839c 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 376101d29..31dbd327a 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@  % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.01.08 11:44} +\newcontextversion{2021.01.11 16:28}  %D This file is loaded at runtime, thereby providing an excellent place for hacks,  %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 10674b4ee..751712225 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@  %D {YYYY.MM.DD HH:MM} format.  \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.01.08 11:44} +\immutable\edef\contextversion{2021.01.11 16:28}  %overloadmode 1 % check frozen / warning  %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt index 57ac9e294..9747ba82d 100644 --- a/tex/context/base/mkxl/driv-shp.lmt +++ b/tex/context/base/mkxl/driv-shp.lmt @@ -627,7 +627,7 @@ local hlist_out, vlist_out  do          for current, id, subtype in nextnode, current do              if id == glyph_code then                  local char, font = isglyph(current) -                local x_offset, y_offset = getoffsets(current) -- todo: also get scales here +                local x_offset, y_offset, left, right, raise = getoffsets(current)                  if x_offset ~= 0 or y_offset ~= 0 then                      if pos_r == righttoleft_code then                          pos_h = ref_h - (cur_h + x_offset) @@ -637,8 +637,10 @@ local hlist_out, vlist_out  do                      pos_v = ref_v - (cur_v - y_offset)                      -- synced                  end +                pos_v = pos_v + raise +                pos_h = pos_h - left                  local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) -                cur_h = cur_h + wd +                cur_h = cur_h + wd - right              elseif id == glue_code then                  local gluewidth = effectiveglue(current,this_box)                  if gluewidth ~= 0 then @@ -834,8 +836,8 @@ local hlist_out, vlist_out  do                      if total > 0 then                          local xoffset, yoffset, left, right = getoffsets(current) -- top bottom                          if left ~= 0 then -                            pos_v  = pos_v + left -                            total  = total - left +                            pos_v = pos_v + left +                            total = total - left                          end                          if right ~= 0 then                              depth = depth - right @@ -995,8 +997,7 @@ local hlist_out, vlist_out  do                              local total = height + depth                              if getid(leader) == rule_code then                                  depth = 0 -- hm --- forgotten ... needs testing -total = glueheight +                                total = glueheight -- forgotten ... needs testing                                  if total > 0 then                                      if width == running then                                          width = boxwidth diff --git a/tex/context/base/mkxl/font-col.lmt b/tex/context/base/mkxl/font-col.lmt index 200551099..21c731946 100644 --- a/tex/context/base/mkxl/font-col.lmt +++ b/tex/context/base/mkxl/font-col.lmt @@ -33,6 +33,8 @@ local trace_collecting   = false  trackers.register("fonts.collecting", function  local report_fonts       = logs.reporter("fonts","collections") +local texconditionals    = tex.conditionals +  local enableaction       = nodes.tasks.enableaction  local disableaction      = nodes.tasks.disableaction @@ -236,7 +238,7 @@ function collections.clonevector(name)          if factor then              vector.factor = factor          end -if tex.conditionals["c_font_compact"] then +if texconditionals["c_font_compact"] then          if rscale then              vector.rscale = rscale          end @@ -342,7 +344,7 @@ function collections.prepare(name) -- we can do this in lua now .. todo              local f = d[i]              local name = f.font              local scale = f.rscale or 1 -if tex.conditionals["c_font_compact"] then +if texconditionals["c_font_compact"] then      scale = 1  end              if fontpatternhassize(name) then diff --git a/tex/context/base/mkxl/font-ctx.lmt b/tex/context/base/mkxl/font-ctx.lmt index 3dbf7bbbd..b307f8f5d 100644 --- a/tex/context/base/mkxl/font-ctx.lmt +++ b/tex/context/base/mkxl/font-ctx.lmt @@ -1095,13 +1095,14 @@ local specifiers = { }  do  -- else too many locals -    local starttiming = statistics.starttiming -    local stoptiming  = statistics.stoptiming +    local starttiming     = statistics.starttiming +    local stoptiming      = statistics.stoptiming -    local setmacro    = tokens.setters.macro -    local ctxcatcodes = tex.ctxcatcodes +    local setmacro        = tokens.setters.macro +    local ctxcatcodes     = tex.ctxcatcodes +    local texconditionals = tex.conditionals -    local reported    = setmetatableindex(function(t,k) +    local reported = setmetatableindex(function(t,k)          local v = setmetatableindex(function(t,k)              t[k] = true              return false @@ -1226,6 +1227,9 @@ do  -- else too many locals                  name = o_name                  sub = o_sub              end +if texconditionals["c_font_compact"] then +    size = 655360 +end              -- so far              -- some settings can have been overloaded              if lookup and lookup ~= "" then diff --git a/tex/context/base/mkxl/font-glf.mklx b/tex/context/base/mkxl/font-glf.mklx index 023c632dc..2c23f226e 100644 --- a/tex/context/base/mkxl/font-glf.mklx +++ b/tex/context/base/mkxl/font-glf.mklx @@ -25,8 +25,8 @@      % we can optimize for zero and 1000 .. maybe also options?      \overloaded\frozen\protected\edefcsname\currenttweakedfont\endcsname        {\begincsname\tweakedfontparameter\c!style\endcsname -       \glyphxscale \numexpr\glyphxscale *\numericscale\tweakedfontparameter\c!xscale /\plusthousand\relax -       \glyphyscale \numexpr\glyphyscale *\numericscale\tweakedfontparameter\c!yscale /\plusthousand\relax +       \glyphxscale \numexpr\numericscale\tweakedfontparameter\c!xscale*\glyphxscale/\plusthousand\relax +       \glyphyscale \numexpr\numericscale\tweakedfontparameter\c!yscale*\glyphyscale/\plusthousand\relax         \glyphxoffset\dimexpr\glyphxoffset+\tweakedfontparameter\c!xoffset\relax         \glyphyoffset\dimexpr\glyphyoffset+\tweakedfontparameter\c!yoffset\relax}%  \to \everydefinetweakedfont diff --git a/tex/context/base/mkxl/font-imp-math.lmt b/tex/context/base/mkxl/font-imp-math.lmt index 47fcf344c..079c867e2 100644 --- a/tex/context/base/mkxl/font-imp-math.lmt +++ b/tex/context/base/mkxl/font-imp-math.lmt @@ -14,6 +14,8 @@ local registerotffeature = fonts.handlers.otf.features.register  local setmetatableindex  = table.setmetatableindex +local texconditionals    = tex.conditionals +  -- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0  local splitter  = lpeg.splitat(",",tonumber) @@ -69,7 +71,7 @@ registerotffeature {  -- A quick and dirty and low level implementation but okay for testing:  local function manipulate(tfmdata,key,value) -    if tex.conditionals["c_font_compact"] then +    if texconditionals["c_font_compact"] then          local rawdata           = tfmdata.shared.rawdata          local rawresources      = rawdata and rawdata.resources          local rawfeatures       = rawresources and rawresources.features @@ -110,7 +112,7 @@ local function manipulate(tfmdata,key,value)  end  local function initialize(tfmdata,key,value) -    if tex.conditionals["c_font_compact"] then +    if texconditionals["c_font_compact"] then          local rawdata       = tfmdata.shared.rawdata          local rawresources  = rawdata and rawdata.resources          local mathconstants = rawresources.mathconstants diff --git a/tex/context/base/mkxl/font-ini.mklx b/tex/context/base/mkxl/font-ini.mklx index 764fbfdab..0a158e69d 100644 --- a/tex/context/base/mkxl/font-ini.mklx +++ b/tex/context/base/mkxl/font-ini.mklx @@ -884,9 +884,8 @@     \fi     \c_font_future_glyph_scale\numexpr\plushundred*\d_font_scaled_font_size/\maxcard\relax     \glyphscale\numexpr\plushundred*\d_font_scaled_font_size/\maxcard\relax % needed ? for math i guess -% \glyphscale\plusthousand -   \d_font_scaled_font_size\d_font_scaled_default -   \d_font_scaled_text_face\d_font_scaled_default + % \d_font_scaled_font_size\d_font_scaled_default + % \d_font_scaled_text_face\d_font_scaled_default     %     \edef\somefontspec{at \number\d_font_scaled_font_size sp}%     % this has to happen at the tex end ... @@ -898,23 +897,6 @@     \font_helpers_update_font_class_parameters     % ... till here    %\writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}% -%    \clf_definefont_two -%       \ifempty\fontclass\s!false\else\s!true\fi -%       {#csname}% -%       {\somefontfile}% -%       \d_font_scaled_font_size -%       \c_font_feature_inheritance_mode -%       {\m_font_class_features}% -%       {\m_font_features}% -%       {\m_font_class_fallbacks}% -%       {\m_font_fallbacks}% -%       \fontface -%       \d_font_scaled_text_face -%       {\m_font_class_goodies}% -%       {\m_font_goodies}% -%       {\m_font_class_designsize}% -%       {\m_font_designsize}% -%       \scaledfontmode     \clf_definefont_two        \ifempty\fontclass\s!false\else\s!true\fi        {#csname}% @@ -926,7 +908,7 @@        \m_font_class_fallbacks        \m_font_fallbacks        \fontface -      \d_font_scaled_text_face +      \d_font_scaled_default        \m_font_class_goodies        \m_font_goodies        \m_font_class_designsize @@ -943,7 +925,7 @@       %       \glyphscale         \ifnum\c_font_scaled_font_mode_saved>\plusfour -         \numexpr\plusthousand*\dimexpr\d_font_scaled_font_size\relax/\c_font_scaled_points\relax +         \numexpr\plusthousand*\dimexpr\d_font_scaled_default\relax/\c_font_scaled_points\relax         \else           \c_font_future_glyph_scale         \fi diff --git a/tex/context/base/mkxl/font-otj.lmt b/tex/context/base/mkxl/font-otj.lmt index 15a78d122..e9e9d524e 100644 --- a/tex/context/base/mkxl/font-otj.lmt +++ b/tex/context/base/mkxl/font-otj.lmt @@ -25,11 +25,13 @@ if not modules then modules = { } end modules ['font-otj'] = {  -- An alternative is to have a list per base of all marks and then do a run over the node  -- list that resolves the accumulated l/r/x/y and then do an inject pass. --- if needed we can flag a kern node as immutable -  -- The thing with these positioning options is that it is not clear what Uniscribe does with  -- the 2rl flag and we keep oscillating a between experiments. +-- Beware: combining advance with cursive and marks can be a problem because marks have no +-- dimensions .. maybe we need a special field for that ... the advance also sets the apply +-- x offset flag! +  if not nodes.properties then return end  local next, rawget, tonumber = next, rawget, tonumber @@ -80,19 +82,26 @@ local nodepool           = nuts.pool  local tonode             = nuts.tonode  local tonut              = nuts.tonut -local setfield           = nuts.setfield  local getnext            = nuts.getnext  local getprev            = nuts.getprev  local getid              = nuts.getid  local getfont            = nuts.getfont  local getchar            = nuts.getchar +local setchar            = nuts.setchar +----- getxoffset         = nuts.getxoffset +----- getyoffset         = nuts.getyoffset  local getoffsets         = nuts.getoffsets  local getxscale          = nuts.getxscale  local getyscale          = nuts.getyscale +local getxyscales        = nuts.getxyscales +local xscaled            = nuts.xscaled +local yscaled            = nuts.yscaled  local getboth            = nuts.getboth  local getdisc            = nuts.getdisc  local setdisc            = nuts.setdisc  local setoffsets         = nuts.setoffsets +local addxoffset         = nuts.addxoffset +local addyoffset         = nuts.addyoffset  local ischar             = nuts.ischar  local isnextchar         = nuts.isnextchar  local getkern            = nuts.getkern @@ -100,7 +109,8 @@ local setkern            = nuts.setkern  local setlink            = nuts.setlink  local setwidth           = nuts.setwidth  local getwidth           = nuts.getwidth -local setadvance         = nuts.setadvance +local addxymargins       = nuts.addxymargins -- we delegate scaling +local copynode           = nuts.copy  local nextchar           = nuts.traversers.char  local nextglue           = nuts.traversers.glue @@ -113,8 +123,9 @@ local properties         = nodes.properties.data  local fontkern           = nuts.pool and nuts.pool.fontkern  local italickern         = nuts.pool and nuts.pool.italickern -local useitalickerns     = false -- context only +local useitalickerns     = false  local useadvance         = false +local usezwjkerns        = true  -- when useadvance  directives.register("fonts.injections.useitalics", function(v)      if v then @@ -618,21 +629,206 @@ end  --     D-post      +D-post  --    +D-replace   +D-replace -local function inject_kerns_only(head,where) +-- Beware! pre/post/replace can have non glyphs too + +-- local function inject_kerns_only(head,where) +--     if trace_injections then +--         trace(head,"kerns") +--     end +--     local current        = head +--     local prev        -- = nil +--     local prevdisc    -- = nil +--     local pre         -- = nil -- saves a lookup +--     local post        -- = nil -- saves a lookup +--     local replace     -- = nil -- saves a lookup +--     local pretail     -- = nil -- saves a lookup +--     local posttail    -- = nil -- saves a lookup +--     local replacetail -- = nil -- saves a lookup +--     while current do +--         local next, char, id = isnextchar(current) +--         if char then +--             local p = rawget(properties,current) +--             if p then +--                 local i = p.injections +--                 if i then +--                     -- left|glyph|right +--                     local leftkern = i.leftkern +--                     if leftkern and leftkern ~= 0 then +--                         leftkern = xscaled(current,leftkern) +--                         if useadvance then +--                             addmargins(current,-leftkern) +--                         elseif prev and getid(prev) == glue_code then +--                             if useitalickerns then +--                                 head = insert_node_before(head,current,italickern(leftkern)) +--                             else +--                                 setwidth(prev, getwidth(prev) + leftkern) +--                             end +--                         else +--                             head = insert_node_before(head,current,fontkern(leftkern)) +--                         end +--                     end +--                 end +--                 if prevdisc then +--                     local done = false +--                     if post then +--                         local i = p.postinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(current,leftkern) +--                                 if useadvance then +--                                     addmargins(posttail,false,-leftkern) +--                                 else +--                                     setlink(posttail,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                     if replace then +--                         local i = p.replaceinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(current,leftkern) +--                                 if useadvance then +--                                     addmargins(replacetail,false,-leftkern) +--                                 else +--                                     setlink(replacetail,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     else +--                         local i = p.emptyinjections +--                         if i then +--                             -- glyph|disc|glyph (special case) +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(current,leftkern) +--                              -- if useadvance then +--                              --     add zwj with offset +--                              -- else +--                                     replace = fontkern(leftkern) +--                                     done    = true +--                              -- end +--                             end +--                         end +--                     end +--                     if done then +--                         setdisc(prevdisc,pre,post,replace) +--                     end +--                 end +--             end +--             prevdisc  = nil +--         -- prevglyph = current +--         elseif char == false then +--             -- other font +--             prevdisc  = nil +--         -- prevglyph = current +--         elseif id == disc_code then +--             pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) +--             local done = false +--             if pre then +--                 -- left|pre glyphs|right +--                 for n in nextchar, pre do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.preinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                                 if useadvance then +--                                     addmargins(n,-leftkern) +--                                 else +--                                     pre  = insert_node_before(pre,n,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if post then +--                 -- left|post glyphs|right +--                 for n in nextchar, post do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.postinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                                 if useadvance then +--                                     addmargins(n,-leftkern) +--                                 else +--                                     post = insert_node_before(post,n,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if replace then +--                 -- left|replace glyphs|right +--                 for n in nextchar, replace do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.replaceinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                                 if useadvance then +--                                     addmargins(n,-leftkern) +--                                 else +--                                     replace = insert_node_before(replace,n,fontkern(leftkern)) +--                                     done    = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if done then +--                 setdisc(current,pre,post,replace) +--             end +--          -- prevglyph = nil +--             prevdisc  = current +--         else +--          -- prevglyph = nil +--             prevdisc  = nil +--         end +--         prev    = current +--         current = next +--     end +--     -- +--     if keepregisteredcounts then +--         keepregisteredcounts = false +--     else +--         nofregisteredkerns   = 0 +--     end +--     if trace_injections then +--         show_result(head) +--     end +--     return head +-- end + +local function inject_kerns_only_kerns(head,where)      if trace_injections then          trace(head,"kerns")      end -    local current     = head -    local prev        = nil -    local next        = nil -    local prevdisc    = nil --- local prevglyph   = nil -    local pre         = nil -- saves a lookup -    local post        = nil -- saves a lookup -    local replace     = nil -- saves a lookup -    local pretail     = nil -- saves a lookup -    local posttail    = nil -- saves a lookup -    local replacetail = nil -- saves a lookup +    local current        = head +    local prev        -- = nil +    local prevdisc    -- = nil +    local pre         -- = nil -- saves a lookup +    local post        -- = nil -- saves a lookup +    local replace     -- = nil -- saves a lookup +    local pretail     -- = nil -- saves a lookup +    local posttail    -- = nil -- saves a lookup +    local replacetail -- = nil -- saves a lookup      while current do          local next, char, id = isnextchar(current)          if char then @@ -643,19 +839,15 @@ local function inject_kerns_only(head,where)                      -- left|glyph|right                      local leftkern = i.leftkern                      if leftkern and leftkern ~= 0 then -                        if useadvance then -                            setadvance(current,leftkern,0) -                        else -                            leftkern = leftkern * getxscale(current) -                            if prev and getid(prev) == glue_code then -                                if useitalickerns then -                                    head = insert_node_before(head,current,italickern(leftkern)) -                                else -                                    setwidth(prev, getwidth(prev) + leftkern) -                                end +                        leftkern = xscaled(current,leftkern) +                        if prev and getid(prev) == glue_code then +                            if useitalickerns then +                                head = insert_node_before(head,current,italickern(leftkern))                              else -                                head = insert_node_before(head,current,fontkern(leftkern)) +                                setwidth(prev,getwidth(prev) + leftkern)                              end +                        else +                            head = insert_node_before(head,current,fontkern(leftkern))                          end                      end                  end @@ -666,13 +858,8 @@ local function inject_kerns_only(head,where)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                                if useadvance then -                                    setadvance(posttail,0,leftkern) -                                else -                                    leftkern = leftkern * getxscale(current) -                                    setlink(posttail,fontkern(leftkern)) -                                    done = true -                                end +                                setlink(posttail,fontkern(xscaled(current,leftkern))) +                                done = true                              end                          end                      end @@ -681,13 +868,8 @@ local function inject_kerns_only(head,where)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                                if useadvance then -                                    setadvance(replacetail,0,leftkern) -                                else -                                    leftkern = leftkern * getxscale(current) -                                    setlink(replacetail,fontkern(leftkern)) -                                    done = true -                                end +                                setlink(replacetail,fontkern(xscaled(current,leftkern))) +                                done = true                              end                          end                      else @@ -696,13 +878,8 @@ local function inject_kerns_only(head,where)                              -- glyph|disc|glyph (special case)                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                             -- if useadvance then -                             --     add zwj with offset -                             -- else -                                    leftkern = leftkern * getxscale(current) -                                    replace = fontkern(leftkern) -                                    done    = true -                             -- end +                                replace = fontkern(xscaled(current,leftkern)) +                                done    = true                              end                          end                      end @@ -712,11 +889,11 @@ local function inject_kerns_only(head,where)                  end              end              prevdisc  = nil -        -- prevglyph = current +         -- prevglyph = current          elseif char == false then              -- other font              prevdisc  = nil -        -- prevglyph = current +         -- prevglyph = current          elseif id == disc_code then              pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)              local done = false @@ -729,13 +906,8 @@ local function inject_kerns_only(head,where)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                                if useadvance then -                                    setadvance(n,leftkern,0) -                                else -                                    leftkern = leftkern * getxscale(n) -                                    pre  = insert_node_before(pre,n,fontkern(leftkern)) -                                    done = true -                                end +                                pre  = insert_node_before(pre,n,fontkern(xscaled(n,leftkern))) +                                done = true                              end                          end                      end @@ -750,13 +922,8 @@ local function inject_kerns_only(head,where)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                                if useadvance then -                                    setadvance(n,leftkern,0) -                                else -                                    leftkern = leftkern * getxscale(n) -                                    post = insert_node_before(post,n,fontkern(leftkern)) -                                    done = true -                                end +                                post = insert_node_before(post,n,fontkern(xscaled(n,leftkern))) +                                done = true                              end                          end                      end @@ -771,13 +938,8 @@ local function inject_kerns_only(head,where)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -                                if useadvance then -                                    setadvance(n,leftkern,0) -                                else -                                    leftkern = leftkern * getxscale(n) -                                    replace = insert_node_before(replace,n,fontkern(leftkern)) -                                    done    = true -                                end +                                replace = insert_node_before(replace,n,fontkern(xscaled(n,leftkern))) +                                done    = true                              end                          end                      end @@ -786,10 +948,10 @@ local function inject_kerns_only(head,where)              if done then                  setdisc(current,pre,post,replace)              end -        -- prevglyph = nil +         -- prevglyph = nil              prevdisc  = current          else -        -- prevglyph = nil +         -- prevglyph = nil              prevdisc  = nil          end          prev    = current @@ -807,7 +969,450 @@ local function inject_kerns_only(head,where)      return head  end -local function inject_positions_only(head,where) +local function inject_kerns_only_margins(head,where) +    if trace_injections then +        trace(head,"kerns") +    end +    local current        = head +    local prevdisc    -- = nil +    local pre         -- = nil -- saves a lookup +    local post        -- = nil -- saves a lookup +    local replace     -- = nil -- saves a lookup +    local pretail     -- = nil -- saves a lookup +    local posttail    -- = nil -- saves a lookup +    local replacetail -- = nil -- saves a lookup +    while current do +        local next, char, id = isnextchar(current) +        if char then +            local p = rawget(properties,current) +            if p then +                if prevdisc then +                    if post then +                        local i = p.postinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(posttail,false,-leftkern) +                            end +                        end +                    end +                    if replace then +                        local i = p.replaceinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(replacetail,false,-leftkern) +                            end +                        end +                    else +                        local i = p.emptyinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                if usezwjkerns then +                                    replace = copynode(current) +                                    setchar(replace,0x200D) -- zwj +                                    addxymargins(replace,-leftkern) +                                else +                                    replace = fontkern(xscaled(current,leftkern)) +                                end +                                setdisc(prevdisc,pre,post,replace) -- setreplace +                            end +                        end +                    end +                end +                -- moved down so we can copy zwj +                local i = p.injections +                if i then +                    local leftkern = i.leftkern +                    if leftkern and leftkern ~= 0 then +                        addxymargins(current,-leftkern) +                    end +                end +            end +            prevdisc = nil +        elseif char == false then +            prevdisc = nil +        elseif id == disc_code then +            pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) +            if pre then +                for n in nextchar, pre do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.preinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(n,-leftkern) +                            end +                        end +                    end +                end +            end +            if post then +                for n in nextchar, post do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.postinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(n,-leftkern) +                            end +                        end +                    end +                end +            end +            if replace then +                for n in nextchar, replace do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.replaceinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(n,-leftkern) +                            end +                        end +                    end +                end +            end +            prevdisc = current +        else +            prevdisc = nil +        end +        current = next +    end +    if keepregisteredcounts then +        keepregisteredcounts = false +    else +        nofregisteredkerns   = 0 +    end +    if trace_injections then +        show_result(head) +    end +    return head +end + +-- local function inject_positions_only(head,where) +--     if trace_injections then +--         trace(head,"positions") +--     end +--     local current     = head +--     local prev        = nil +--     local next        = nil +--     local prevdisc    = nil +--     local prevglyph   = nil +--     local pre         = nil -- saves a lookup +--     local post        = nil -- saves a lookup +--     local replace     = nil -- saves a lookup +--     local pretail     = nil -- saves a lookup +--     local posttail    = nil -- saves a lookup +--     local replacetail = nil -- saves a lookup +--     while current do +--         local next, char, id = isnextchar(current) +--         if char then +--             local p = rawget(properties,current) +--             if p then +--                 local i = p.injections +--                 if i then +--                     -- left|glyph|right +--                     local yoffset = i.yoffset +--                     if yoffset and yoffset ~= 0 then +--                         -- use raise when advance +--                         addyoffset(current,yscaled(current,yoffset)) +--                     end +--                     local leftkern  = i.leftkern or 0 +--                     local rightkern = i.rightkern or 0 +--                     if leftkern ~= 0 then +--                         leftkern = xscaled(current,leftkern) +--                     end +--                     if rightkern ~= 0 then +--                         rightkern = xscaled(current,rightkern) +--                     end +--                     if useadvance then +--                         if leftkern ~= 0 or rightkern ~= 0 then +--                             addmargins(current,-leftkern,-rightkern) +--                         end +--                     else +--                         if leftkern ~= 0 then +--                             if leftkern == -rightkern then +--                                 addxoffset(current,leftkern) +--                                 rightkern = 0 +--                             elseif prev and getid(prev) == glue_code then +--                                 if useitalickerns then +--                                     head = insert_node_before(head,current,italickern(leftkern)) +--                                 else +--                                     setwidth(prev,getwidth(prev)+leftkern) +--                                 end +--                             else +--                                 head = insert_node_before(head,current,fontkern(leftkern)) +--                             end +--                         end +--                         if rightkern ~= 0 then +--                             if next and getid(next) == glue_code then +--                                 if useitalickerns then +--                                     insert_node_after(head,current,italickern(rightkern)) +--                                 else +--                                     setwidth(next, getwidth(next)+rightkern) +--                                 end +--                             else +--                                 insert_node_after(head,current,fontkern(rightkern)) +--                             end +--                         end +--                     end +--                 else +--                     local i = p.emptyinjections +--                     if i then +--                         -- glyph|disc|glyph (special case) +--                         local rightkern = i.rightkern +--                         if rightkern and rightkern ~= 0 then +--                             if next and getid(next) == disc_code then +--                                 if replace then +--                                     -- error, we expect an empty one +--                                 else +--                                     rightkern = xscaled(current,rightkern) +--                                     replace = fontkern(rightkern) -- maybe also leftkern +--                                     done = true	--KE +--                                 end +--                             end +--                         end +--                     end +--                 end +--                 if prevdisc then +--                     local done = false +--                     if post then +--                         local i = p.postinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(current,leftkern) +--                                 if useadvance then +--                                     addmargins(posttail,-leftkern) +--                                 else +--                                     setlink(posttail,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                     if replace then +--                         local i = p.replaceinjections +--                         if i then +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 leftkern = xscaled(current,leftkern) +--                                 if useadvance then +--                                     addmargins(replacetail,-leftkern) +--                                 else +--                                     setlink(replacetail,fontkern(leftkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     else +--                         local i = p.emptyinjections +--                         if i then +--                             -- new .. okay? +--                             local leftkern = i.leftkern +--                             if leftkern and leftkern ~= 0 then +--                                 replace = fontkern(xscaled(current,leftkern)) +--                                 done = true +--                             end +--                         end +--                     end +--                     if done then +--                         setdisc(prevdisc,pre,post,replace) +--                     end +--                 end +--             end +--             prevdisc  = nil +--             prevglyph = current +--         elseif char == false then +--             prevdisc  = nil +--             prevglyph = current +--         elseif id == disc_code then +--             pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) +--             local done = false +--             if pre then +--                 -- left|pre glyphs|right +--                 for n in nextchar, pre do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.preinjections +--                         if i then +--                             local yoffset   = i.yoffset +--                             local leftkern  = i.leftkern or 0 +--                             local rightkern = i.rightkern or 0 +--                             if yoffset and yoffset ~= 0 then +--                                 -- use raise when advance +--                                 addyoffset(n,yscaled(n,yoffset)) +--                             end +--                             if leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                             end +--                             if rightkern ~= 0 then +--                                 rightkern = xscaled(n,rightkern) +--                             end +--                             if useadvance then +--                                 if leftkern ~= 0 or rightkern ~= 0 then +--                                     addmargins(pre,-leftkern,-rightkern) +--                                 end +--                             else +--                                 if leftkern ~= 0 then +--                                     pre  = insert_node_before(pre,n,fontkern(leftkern)) +--                                     done = true +--                                 end +--                                 if rightkern ~= 0 then +--                                     insert_node_after(pre,n,fontkern(rightkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if post then +--                 -- left|post glyphs|right +--                 for n in nextchar, post do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.postinjections +--                         if i then +--                             local yoffset   = i.yoffset +--                             local leftkern  = i.leftkern or 0 +--                             local rightkern = i.rightkern or 0 +--                             if yoffset and yoffset ~= 0 then +--                                 -- use raise when advance +--                                 addyoffset(n,yscaled(n,yoffset)) +--                             end +--                             if leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                             end +--                             if rightkern ~= 0 then +--                                 rightkern = xscaled(n,rightkern) +--                             end +--                             if useadvance then +--                                 if leftkern ~= 0 or rightkern ~= 0 then +--                                     addmargins(post,-leftkern,-rightkern) +--                                 end +--                             else +--                                 if leftkern ~= 0 then +--                                     post = insert_node_before(post,n,fontkern(leftkern)) +--                                     done = true +--                                 end +--                                 if rightkern ~= 0 then +--                                     insert_node_after(post,n,fontkern(rightkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if replace then +--                 -- left|replace glyphs|right +--                 for n in nextchar, replace do +--                     local p = rawget(properties,n) +--                     if p then +--                         local i = p.injections or p.replaceinjections +--                         if i then +--                             local yoffset   = i.yoffset +--                             local leftkern  = i.leftkern or 0 +--                             local rightkern = i.rightkern or 0 +--                             if yoffset and yoffset ~= 0 then +--                                 -- use raise when advance +--                                 addyoffset(n,yscaled(n,yoffset)) +--                             end +--                             if leftkern ~= 0 then +--                                 leftkern = xscaled(n,leftkern) +--                             end +--                             if rightkern ~= 0 then +--                                 rightkern = xscaled(n,rightkern) +--                             end +--                             if useadvance then +--                                 if leftkern ~= 0 or rightkern ~= 0 then +--                                     addmargins(replace,-leftkern,-rightkern) +--                                 end +--                             else +--                                 if leftkern ~= 0 then +--                                     replace = insert_node_before(replace,n,fontkern(leftkern)) +--                                     done    = true +--                                 end +--                                 if rightkern ~= 0 then +--                                     insert_node_after(replace,n,fontkern(rightkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if prevglyph then +--                 if pre then +--                     local p = rawget(properties,prevglyph) +--                     if p then +--                         local i = p.preinjections +--                         if i then +--                             -- glyph|pre glyphs +--                             local rightkern = i.rightkern +--                             if rightkern and rightkern ~= 0 then +--                                 rightkern = xscaled(prevglyph,rightkern) +--                                 if useadvance then +--                                     addmargins(pre,-rightkern) +--                                 else +--                                     pre  = insert_node_before(pre,pre,fontkern(rightkern)) +--                                     done = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--                 if replace then +--                     local p = rawget(properties,prevglyph) +--                     if p then +--                         local i = p.replaceinjections +--                         if i then +--                             -- glyph|replace glyphs +--                             local rightkern = i.rightkern +--                             if rightkern and rightkern ~= 0 then +--                                 rightkern = xscaled(prevglyph,rightkern) +--                                 if useadvance then +--                                     addmargins(replace,-rightkern) +--                                 else +--                                     replace = insert_node_before(replace,replace,fontkern(rightkern)) +--                                     done    = true +--                                 end +--                             end +--                         end +--                     end +--                 end +--             end +--             if done then +--                 setdisc(current,pre,post,replace) +--             end +--             prevglyph = nil +--             prevdisc  = current +--         else +--             prevglyph = nil +--             prevdisc  = nil +--         end +--         prev    = current +--         current = next +--     end +--     -- +--     if keepregisteredcounts then +--         keepregisteredcounts = false +--     else +--         nofregisteredpositions = 0 +--     end +--     if trace_injections then +--         show_result(head) +--     end +--     return head +-- end + +local function inject_positions_only_kerns(head,where)      if trace_injections then          trace(head,"positions")      end @@ -832,33 +1437,37 @@ local function inject_positions_only(head,where)                      -- left|glyph|right                      local yoffset = i.yoffset                      if yoffset and yoffset ~= 0 then -yoffset = yoffset * getxscale(current) -                        setoffsets(current,false,yoffset) +                        -- use raise when advance +                        addyoffset(current,yscaled(current,yoffset))                      end -                    local leftkern  = i.leftkern -                    local rightkern = i.rightkern -                    if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                        if rightkern and leftkern == -rightkern then -                            setoffsets(current,leftkern,false) +                    local leftkern  = i.leftkern or 0 +                    local rightkern = i.rightkern or 0 +                    if leftkern ~= 0 then +                        leftkern = xscaled(current,leftkern) +                    end +                    if rightkern ~= 0 then +                        rightkern = xscaled(current,rightkern) +                    end +                    if leftkern ~= 0 then +                        if leftkern == -rightkern then +                            addxoffset(current,leftkern)                              rightkern = 0                          elseif prev and getid(prev) == glue_code then                              if useitalickerns then                                  head = insert_node_before(head,current,italickern(leftkern))                              else -                                setwidth(prev, getwidth(prev) + leftkern) +                                setwidth(prev,getwidth(prev)+leftkern)                              end                          else                              head = insert_node_before(head,current,fontkern(leftkern))                          end                      end -                    if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(current) +                    if rightkern ~= 0 then                          if next and getid(next) == glue_code then                              if useitalickerns then                                  insert_node_after(head,current,italickern(rightkern))                              else -                                setwidth(next, getwidth(next) + rightkern) +                                setwidth(next, getwidth(next)+rightkern)                              end                          else                              insert_node_after(head,current,fontkern(rightkern)) @@ -874,10 +1483,8 @@ rightkern = rightkern * getxscale(current)                                  if replace then                                      -- error, we expect an empty one                                  else -                              -- KE setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern -rightkern = rightkern * getxscale(current) -                                    replace = fontkern(rightkern) -- maybe also leftkern -                                    done = true	--KE +                                    replace = fontkern(xscaled(current,rightkern)) -- maybe also leftkern +                                    done    = true	--KE                                  end                              end                          end @@ -890,8 +1497,7 @@ rightkern = rightkern * getxscale(current)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                setlink(posttail,fontkern(leftkern)) +                                setlink(posttail,fontkern(xscaled(current,leftkern)))                                  done = true                              end                          end @@ -901,8 +1507,7 @@ leftkern = leftkern * getxscale(current)                          if i then                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                setlink(replacetail,fontkern(leftkern)) +                                setlink(replacetail,fontkern(xscaled(current,leftkern)))                                  done = true                              end                          end @@ -912,8 +1517,7 @@ leftkern = leftkern * getxscale(current)                              -- new .. okay?                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                replace = fontkern(leftkern) +                                replace = fontkern(xscaled(current,leftkern))                                  done = true                              end                          end @@ -942,17 +1546,14 @@ leftkern = leftkern * getxscale(current)                              local leftkern  = i.leftkern                              local rightkern = i.rightkern                              if yoffset and yoffset ~= 0 then -yoffset = yoffset * getyscale(current) -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(n) -                                pre  = insert_node_before(pre,n,fontkern(leftkern)) +                                pre  = insert_node_before(pre,n,fontkern(xscaled(n,leftkern)))                                  done = true                              end                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(n) -                                insert_node_after(pre,n,fontkern(rightkern)) +                                insert_node_after(pre,n,fontkern(xscaled(n,rightkern)))                                  done = true                              end                          end @@ -970,17 +1571,14 @@ rightkern = rightkern * getxscale(n)                              local leftkern  = i.leftkern                              local rightkern = i.rightkern                              if yoffset and yoffset ~= 0 then -yoffset = yoffset * getyscale(current) -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(n) -                                post = insert_node_before(post,n,fontkern(leftkern)) +                                post = insert_node_before(post,n,fontkern(xscaled(n,leftkern)))                                  done = true                              end                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(n) -                                insert_node_after(post,n,fontkern(rightkern)) +                                insert_node_after(post,n,fontkern(xscaled(n,rightkern)))                                  done = true                              end                          end @@ -998,17 +1596,14 @@ rightkern = rightkern * getxscale(n)                              local leftkern  = i.leftkern                              local rightkern = i.rightkern                              if yoffset and yoffset ~= 0 then -yoffset = yoffset * getyscale(current) -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(n) -                                replace = insert_node_before(replace,n,fontkern(leftkern)) +                                replace = insert_node_before(replace,n,fontkern(xscaled(n,leftkern)))                                  done    = true                              end                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(n) -                                insert_node_after(replace,n,fontkern(rightkern)) +                                insert_node_after(replace,n,fontkern(xscaled(n,rightkern)))                                  done = true                              end                          end @@ -1016,6 +1611,7 @@ rightkern = rightkern * getxscale(n)                  end              end              if prevglyph then +                -- there can only be useful properties when pre/replace start with a glyph                  if pre then                      local p = rawget(properties,prevglyph)                      if p then @@ -1024,8 +1620,7 @@ rightkern = rightkern * getxscale(n)                              -- glyph|pre glyphs                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(prevglyph) -                                pre  = insert_node_before(pre,pre,fontkern(rightkern)) +                                pre  = insert_node_before(pre,pre,fontkern(xscaled(prevglyph,rightkern)))                                  done = true                              end                          end @@ -1039,8 +1634,7 @@ rightkern = rightkern * getxscale(prevglyph)                              -- glyph|replace glyphs                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(prevglyph) -                                replace = insert_node_before(replace,replace,fontkern(rightkern)) +                                replace = insert_node_before(replace,replace,fontkern(xscaled(prevglyph,rightkern)))                                  done    = true                              end                          end @@ -1071,6 +1665,202 @@ rightkern = rightkern * getxscale(prevglyph)      return head  end +local function inject_positions_only_margins(head,where) +    if trace_injections then +        trace(head,"positions") +    end +    local current     = head +    local prev        = nil +    local next        = nil +    local prevdisc    = nil +    local prevglyph   = nil +    local pre         = nil -- saves a lookup +    local post        = nil -- saves a lookup +    local replace     = nil -- saves a lookup +    local pretail     = nil -- saves a lookup +    local posttail    = nil -- saves a lookup +    local replacetail = nil -- saves a lookup +    while current do +        local next, char, id = isnextchar(current) +        if char then +            local p = rawget(properties,current) +            if p then +                local i = p.injections +                if i then +                    -- left|glyph|right +                    local yoffset   = i.yoffset or 0 +                    local leftkern  = i.leftkern or 0 +                    local rightkern = i.rightkern or 0 +                    if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then +                        addxymargins(n,-leftkern,-rightkern,yoffset) -- also scales +                    end +                else +                    local i = p.emptyinjections +                    if i then +                        -- glyph|disc|glyph (special case) +                        local rightkern = i.rightkern +                        if rightkern and rightkern ~= 0 then +                            if next and getid(next) == disc_code then +                                if replace then +                                    -- error, we expect an empty one +                                else +                                    if usezwjkerns then +                                        replace = copynode(current) +                                        setchar(replace,0x200D) -- zwj +                                        addxymargins(replace,false,-rightkern) +                                    else +                                        replace = fontkern(xscaled(current,rightkern)) -- maybe also leftkern +                                    end +                                    done = true	--KE +                                end +                            end +                        end +                    end +                end +                if prevdisc then +                    if post then +                        local i = p.postinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(posttail,-leftkern) +                            end +                        end +                    end +                    if replace then +                        local i = p.replaceinjections +                        if i then +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                addxymargins(replacetail,-leftkern) +                            end +                        end +                    else +                        local i = p.emptyinjections +                        if i then +                            -- new .. okay? +                            local leftkern = i.leftkern +                            if leftkern and leftkern ~= 0 then +                                if usezwjkerns then +                                    replace = copynode(current) +                                    setchar(replace,0x200D) -- zwj +                                    addxymargins(replace,-leftkern) +                                else +                                    replace = fontkern(xscaled(current,leftkern)) +                                end +                                setdisc(prevdisc,pre,post,replace) +                            end +                        end +                    end +                end +            end +            prevdisc  = nil +            prevglyph = current +        elseif char == false then +            prevdisc  = nil +            prevglyph = current +        elseif id == disc_code then +            pre, post, replace, pretail, posttail, replacetail = getdisc(current,true) +            if pre then +                -- left|pre glyphs|right +                for n in nextchar, pre do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.preinjections +                        if i then +                            local yoffset   = i.yoffset or 0 +                            local leftkern  = i.leftkern or 0 +                            local rightkern = i.rightkern or 0 +                            if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then +                                addxymargins(n,-leftkern,-rightkern,yoffset) -- also scales +                            end +                        end +                    end +                end +            end +            if post then +                -- left|post glyphs|right +                for n in nextchar, post do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.postinjections +                        if i then +                            local yoffset   = i.yoffset or 0 +                            local leftkern  = i.leftkern or 0 +                            local rightkern = i.rightkern or 0 +                            if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then +                                addxymargins(n,-leftkern,-rightkern,yoffset) -- also scales +                            end +                        end +                    end +                end +            end +            if replace then +                -- left|replace glyphs|right +                for n in nextchar, replace do +                    local p = rawget(properties,n) +                    if p then +                        local i = p.injections or p.replaceinjections +                        if i then +                            local yoffset   = i.yoffset or 0 +                            local leftkern  = i.leftkern or 0 +                            local rightkern = i.rightkern or 0 +                            if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then +                                addxymargins(n,-leftkern,-rightkern,yoffset) -- also scales +                            end +                        end +                    end +                end +            end +            if prevglyph then +                if pre then +                    local p = rawget(properties,prevglyph) +                    if p then +                        local i = p.preinjections +                        if i then +                            -- glyph|pre glyphs +                            local rightkern = i.rightkern +                            if rightkern and rightkern ~= 0 then +                                addxymargins(pre,-rightkern,0,0) +                            end +                        end +                    end +                end +                if replace then +                    local p = rawget(properties,prevglyph) +                    if p then +                        local i = p.replaceinjections +                        if i then +                            -- glyph|replace glyphs +                            local rightkern = i.rightkern +                            if rightkern and rightkern ~= 0 then +                                addxymargins(replace,-rightkern,0,0) +                            end +                        end +                    end +                end +            end +            prevglyph = nil +            prevdisc  = current +        else +            prevglyph = nil +            prevdisc  = nil +        end +        prev    = current +        current = next +    end +    -- +    if keepregisteredcounts then +        keepregisteredcounts = false +    else +        nofregisteredpositions = 0 +    end +    if trace_injections then +        show_result(head) +    end +    return head +end +  local function showoffset(n,flag)      local x, y = getoffsets(n)      if x ~= 0 or y ~= 0 then @@ -1078,6 +1868,90 @@ local function showoffset(n,flag)      end  end +local function processmark(p,n,pn) -- p = basenode +    local px, py = getoffsets(p) +    local nx, ny = getoffsets(n) +    local sx, sy = getxyscales(n) -- we assume n and p to have equal scales +    local ox = 0 +    local rightkern = nil +    local pp = rawget(properties,p) +    if pp then +        pp = pp.injections +        if pp then +            rightkern = pp.rightkern +        end +    end +    local markdir = pn.markdir +    if rightkern then -- x and w ~= 0 +        ox = px - sx * (pn.markx or 0) - rightkern +        if markdir and markdir < 0 then +            -- kern(w-x) glyph(p) kern(x) mark(n) +            if not pn.markmark then +                ox = ox + sx * (pn.leftkern or 0) +            end +        else +            -- kern(x) glyph(p) kern(w-x) mark(n) +            -- +            -- According to Kai we don't need to handle leftkern here but I'm +            -- pretty sure I've run into a case where it was needed so maybe +            -- some day we need something more clever here. +            -- +            -- maybe we need to apply both then +            -- +            if false then +                -- a mark with kerning (maybe husayni needs it ) +                local leftkern = pp.leftkern +                if leftkern then +                    ox = ox - sx * leftkern +                end +            end +        end +    else +        ox = px - sx * (pn.markx or 0) +        if markdir and markdir < 0 then +            if not pn.markmark then +                local leftkern = pn.leftkern +                if leftkern then +                    ox = ox + sx * leftkern -- husayni needs it +                end +            end +        end +        if pn.checkmark then +            local wn = getwidth(n) -- in arial marks have widths +            if wn and wn ~= 0 then +                wn = wn/2 +                if trace_injections then +                    report_injections("correcting non zero width mark %C",getchar(n)) +                end +                -- -- bad: we should center +                -- +                -- pn.leftkern  = -wn +                -- pn.rightkern = -wn +                -- +                -- -- we're too late anyway as kerns are already injected so we do it the +                -- -- ugly way (no checking if the previous is already a kern) .. maybe we +                -- -- should fix the font instead +                -- +                -- todo: head and check for prev / next kern +                -- +                insert_node_before(n,n,fontkern(-wn)) +                insert_node_after(n,n,fontkern(-wn)) +            end +        end +    end +    local oy = ny + py + sy * (pn.marky or 0) +    if not pn.markmark then +        local yoffset = pn.yoffset +        if yoffset then +            oy = oy + sy * yoffset -- husayni needs it +        end +    end +    setoffsets(n,ox,oy) +    if trace_marks then +        showoffset(n,true) +    end +end +  local function inject_everything(head,where)      if trace_injections then          trace(head,"everything") @@ -1105,92 +1979,6 @@ local function inject_everything(head,where)      local marks         = { }      local nofmarks      = 0      -- -    -- move out -    -- -    local function processmark(p,n,pn) -- p = basenode -        local px, py = getoffsets(p) -        local nx, ny = getoffsets(n) -        local ox = 0 -        local rightkern = nil -        local pp = rawget(properties,p) -        if pp then -            pp = pp.injections -            if pp then -                rightkern = pp.rightkern -            end -        end -        local markdir = pn.markdir -        if rightkern then -- x and w ~= 0 -            ox = px - (pn.markx or 0) - rightkern -            if markdir and markdir < 0 then -                -- kern(w-x) glyph(p) kern(x) mark(n) -                if not pn.markmark then -                    ox = ox + (pn.leftkern or 0) -                end -            else -                -- kern(x) glyph(p) kern(w-x) mark(n) -                -- -                -- According to Kai we don't need to handle leftkern here but I'm -                -- pretty sure I've run into a case where it was needed so maybe -                -- some day we need something more clever here. -                -- -                -- maybe we need to apply both then -                -- -                if false then -                    -- a mark with kerning (maybe husayni needs it ) -                    local leftkern = pp.leftkern -                    if leftkern then -                        ox = ox - leftkern -                    end -                end -            end -        else -            ox = px - (pn.markx or 0) -            if markdir and markdir < 0 then -                if not pn.markmark then -                    local leftkern = pn.leftkern -                    if leftkern then -                        ox = ox + leftkern -- husayni needs it -                    end -                end -            end -            if pn.checkmark then -                local wn = getwidth(n) -- in arial marks have widths -                if wn and wn ~= 0 then -                    wn = wn/2 -                    if trace_injections then -                        report_injections("correcting non zero width mark %C",getchar(n)) -                    end -                    -- -- bad: we should center -                    -- -                    -- pn.leftkern  = -wn -                    -- pn.rightkern = -wn -                    -- -                    -- -- we're too late anyway as kerns are already injected so we do it the -                    -- -- ugly way (no checking if the previous is already a kern) .. maybe we -                    -- -- should fix the font instead -                    -- -                    -- todo: head and check for prev / next kern -                    -- -                    insert_node_before(n,n,fontkern(-wn)) -                    insert_node_after(n,n,fontkern(-wn)) -                end -            end -        end -        local oy = ny + py + (pn.marky or 0) -        if not pn.markmark then -            local yoffset = pn.yoffset -            if yoffset then -                oy = oy + yoffset -- husayni needs it -            end -        end -ox = ox * getxscale(p) -oy = oy * getyscale(p) -        setoffsets(n,ox,oy) -        if trace_marks then -            showoffset(n,true) -        end -    end      while current do          local next, char, id = isnextchar(current)          if char then @@ -1205,8 +1993,7 @@ oy = oy * getyscale(p)                      else                          local yoffset = i.yoffset                          if yoffset and yoffset ~= 0 then -yoffset = yoffset * getyscale(current) -                            setoffsets(current,false,yoffset) +                            addyoffset(current,yscaled(current,yoffset)) -- or just * sy                          end                          if hascursives then                              local cursivex = i.cursivex @@ -1232,9 +2019,8 @@ yoffset = yoffset * getyscale(current)                                  local nx, ny = getoffsets(current)                                  for i=maxc,minc,-1 do                                      local ti = glyphs[i] -                                    ny = ny + properties[ti].cursivedy -* getyscale(current) -                                    setoffsets(ti,false,ny) -- why not add ? +                                    ny = ny + yscaled(current,properties[ti].cursivedy) -- stepwise increment +                                    setoffsets(ti,false,ny)                                      if trace_cursive then                                          showoffset(ti)                                      end @@ -1249,9 +2035,8 @@ yoffset = yoffset * getyscale(current)                                      local nx, ny = getoffsets(current)                                      for i=maxc,minc,-1 do                                          local ti = glyphs[i] -                                        ny = ny + properties[ti].cursivedy -* getyscale(current) -                                        setoffsets(ti,false,ny) -- why not add ? +                                        ny = ny + yscaled(current,properties[ti].cursivedy) -- stepwise increment +                                        setoffsets(ti,false,ny)                                          if trace_cursive then                                              showoffset(ti)                                          end @@ -1265,9 +2050,10 @@ yoffset = yoffset * getyscale(current)                          local leftkern  = i.leftkern                          local rightkern = i.rightkern                          if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                            if rightkern and leftkern == -rightkern then -                                setoffsets(current,leftkern,false) +                            local opposite = rightkern and leftkern == -rightkern +                            leftkern = xscaled(current,leftkern) +                            if opposite then +                                addxoffset(current,leftkern)                                  rightkern = 0                              elseif prev and getid(prev) == glue_code then                                  if useitalickerns then @@ -1280,7 +2066,7 @@ leftkern = leftkern * getxscale(current)                              end                          end                          if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(current) +                            rightkern = xscaled(current,rightkern)                              if next and getid(next) == glue_code then                                  if useitalickerns then                                      insert_node_after(head,current,italickern(rightkern)) @@ -1302,8 +2088,7 @@ rightkern = rightkern * getxscale(current)                                  if replace then                                      -- error, we expect an empty one                                  else -rightkern = rightkern * getxscale(current) -                                    replace = fontkern(rightkern) +                                    replace = fontkern(xscaled(current,rightkern))                                      done    = true                                  end                              end @@ -1318,8 +2103,7 @@ rightkern = rightkern * getxscale(current)                              if i then                                  local leftkern = i.leftkern                                  if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                    setlink(posttail,fontkern(leftkern)) +                                    setlink(posttail,fontkern(xscaled(current,leftkern)))                                      done = true                                  end                              end @@ -1329,8 +2113,7 @@ leftkern = leftkern * getxscale(current)                              if i then                                  local leftkern = i.leftkern                                  if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                    setlink(replacetail,fontkern(leftkern)) +                                    setlink(replacetail,fontkern(xscaled(current,leftkern)))                                      done = true                                  end                              end @@ -1339,8 +2122,7 @@ leftkern = leftkern * getxscale(current)                              if i then                                  local leftkern = i.leftkern                                  if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(current) -                                    replace = fontkern(leftkern) +                                    replace = fontkern(xscaled(current,leftkern))                                      done    = true                                  end                              end @@ -1356,10 +2138,8 @@ leftkern = leftkern * getxscale(current)                      local nx, ny = getoffsets(current)                      for i=maxc,minc,-1 do                          local ti = glyphs[i] -                        ny = ny + properties[ti].cursivedy -* getyscale(current) -                        local xi, yi = getoffsets(ti) -                        setoffsets(ti,xi,yi + ny) -- can be mark, we could use properties +                        ny = ny + yscaled(current,properties[ti].cursivedy) +                        setoffsets(ti,false,ny) -- can be mark, we could use properties                      end                      maxc = 0                      cursiveanchor = nil @@ -1384,18 +2164,16 @@ leftkern = leftkern * getxscale(current)                          if i then                              local yoffset = i.yoffset                              if yoffset and yoffset ~= 0 then -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(n) -                                pre  = insert_node_before(pre,n,fontkern(leftkern)) +                                pre  = insert_node_before(pre,n,fontkern(xscaled(n,leftkern)))                                  done = true                              end                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(n) -                                insert_node_after(pre,n,fontkern(rightkern)) +                                insert_node_after(pre,n,fontkern(xscaled(n,rightkern)))                                  done = true                              end                              if hasmarks then @@ -1417,19 +2195,17 @@ rightkern = rightkern * getxscale(n)                          if i then                              local yoffset = i.yoffset                              if yoffset and yoffset ~= 0 then -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getsxcale(n) -                                post = insert_node_before(post,n,fontkern(leftkern)) +                                post = insert_node_before(post,n,fontkern(xscaled(n,leftkern)))                                  done = true                              end                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getsxcale(n) -                                insert_node_after(post,n,fontkern(rightkern))                                  done = true +                                insert_node_after(post,n,fontkern(xscaled(n,rightkern)))                              end                              if hasmarks then                                  local pm = i.markbasenode @@ -1450,18 +2226,16 @@ rightkern = rightkern * getsxcale(n)                          if i then                              local yoffset = i.yoffset                              if yoffset and yoffset ~= 0 then -                                setoffsets(n,false,yoffset) +                                addyoffset(n,yscaled(n,yoffset))                              end                              local leftkern = i.leftkern                              if leftkern and leftkern ~= 0 then -leftkern = leftkern * getxscale(n) -                                replace = insert_node_before(replace,n,fontkern(leftkern)) +                                replace = insert_node_before(replace,n,fontkern(xscaled(n,leftkern)))                                  done    = true                              end                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(n) -                                insert_node_after(replace,n,fontkern(rightkern)) +                                insert_node_after(replace,n,fontkern(xscaled(n,rightkern)))                                  done = true                              end                              if hasmarks then @@ -1483,8 +2257,7 @@ rightkern = rightkern * getxscale(n)                              -- glyph|pre glyphs                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(prevglyph) -                                pre  = insert_node_before(pre,pre,fontkern(rightkern)) +                                pre  = insert_node_before(pre,pre,fontkern(xscaled(prevglyph,rightkern)))                                  done = true                              end                          end @@ -1498,8 +2271,7 @@ rightkern = rightkern * getxscale(prevglyph)                              -- glyph|replace glyphs                              local rightkern = i.rightkern                              if rightkern and rightkern ~= 0 then -rightkern = rightkern * getxscale(prevglyph) -                                replace = insert_node_before(replace,replace,fontkern(rightkern)) +                                replace = insert_node_before(replace,replace,fontkern(xscaled(prevglyph,rightkern)))                                  done    = true                              end                          end @@ -1524,8 +2296,8 @@ rightkern = rightkern * getxscale(prevglyph)          local nx, ny = getoffsets(last)          for i=maxc,minc,-1 do              local ti = glyphs[i] -            ny = ny + properties[ti].cursivedy -            setoffsets(ti,false,ny) -- why not add ? +            ny = ny + yscaled(properties[ti].cursivedy) +            setoffsets(ti,false,ny)              if trace_cursive then                  showoffset(ti)              end @@ -1635,8 +2407,7 @@ local function injectspaces(head)      local threshold  = 0      local leftkern   = false      local rightkern  = false - -local xscale = 1 +    local xscale     = 1      local function updatefont(font,trig)          leftkerns  = trig.left @@ -1660,7 +2431,7 @@ local xscale = 1                  if rightkerns then                      rightkern = rightkerns[nextchar]                  end -xscale = getxscale(next) +                xscale = getxscale(next)              end          end          if prevchar then @@ -1673,7 +2444,7 @@ xscale = getxscale(next)                  if leftkerns then                      leftkern = leftkerns[prevchar]                  end -xscale = getxscale(prev) +                xscale = getxscale(prev)              end          end          if leftkern then @@ -1686,8 +2457,8 @@ xscale = getxscale(prev)                          if trace_spaces then                              report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar)                          end -lnew = lnew * xscale -rnew = rnew * xscale +                        lnew = lnew * xscale +                        rnew = rnew * xscale                          head = insert_node_before(head,n,italickern(lnew))                          insert_node_after(head,n,italickern(rnew))                      else @@ -1704,11 +2475,10 @@ rnew = rnew * xscale                          if trace_spaces then                              report_spaces("%C [%p + %p]",prevchar,old,new)                          end -new = new * xscale +                        new = new * xscale                          insert_node_after(head,n,italickern(new)) -- tricky with traverse but ok                      else ---                         local new = old + leftkern * factor -local new = old + leftkern * factor * xscale +                        local new = old + leftkern * factor * xscale                          if trace_spaces then                              report_spaces("%C [%p -> %p]",prevchar,old,new)                          end @@ -1720,16 +2490,14 @@ local new = old + leftkern * factor * xscale          elseif rightkern then              local old = getwidth(n)              if old > threshold then +                local new = rightkern * factor * xscale                  if useitalickerns then -                    local new = rightkern * factor -new = new * xscale                      if trace_spaces then                          report_spaces("[%p + %p] %C",old,new,nextchar)                      end                      insert_node_after(head,n,italickern(new))                  else ---                     local new = old + rightkern * factor -local new = old + rightkern * factor * xscale +                    new = old + new                      if trace_spaces then                          report_spaces("[%p -> %p] %C",old,new,nextchar)                      end @@ -1747,28 +2515,40 @@ local new = old + rightkern * factor * xscale      return head  end --- +-- When advance is found to be okay there will be split functions (which is abit +-- more efficient) but first we need to have scales done (we can also have addoffset +-- and alike then)  function injections.handler(head,where)      if triggers then          head = injectspaces(head)      end -    -- todo: marks only run too      if nofregisteredmarks > 0 or nofregisteredcursives > 0 then          if trace_injections then -            report_injections("injection variant %a","everything") +            report_injections("injection variant %a (%s)","everything","kerns")          end +        -- I will do useadvance here when I am playing with fonts that follow this +        -- injection routem, which is seldom.          return inject_everything(head,where)      elseif nofregisteredpositions > 0 then          if trace_injections then -            report_injections("injection variant %a","positions") +            report_injections("injection variant %a (%s)","positions",useadvance and "margins" or "kerns") +        end +        if useadvance then +            return inject_positions_only_margins(head,where) +        else +            return inject_positions_only_kerns(head,where)          end -        return inject_positions_only(head,where)      elseif nofregisteredkerns > 0 then          if trace_injections then -            report_injections("injection variant %a","kerns") +            report_injections("injection variant %a (%s)","kerns",useadvance and "margins" or "kerns") +        end +        if useadvance then +            return inject_kerns_only_margins(head,where) +--             return inject_positions_only_margins(head,where) +        else +            return inject_kerns_only_kerns(head,where)          end -        return inject_kerns_only(head,where)      else          return head      end diff --git a/tex/context/base/mkxl/lang-hyp.lmt b/tex/context/base/mkxl/lang-hyp.lmt index c2862f536..c356dbf3c 100644 --- a/tex/context/base/mkxl/lang-hyp.lmt +++ b/tex/context/base/mkxl/lang-hyp.lmt @@ -1438,8 +1438,8 @@ featureset.hyphenonly   = hyphenonly == v_yes                              rightchar   = rightchar    or (instance and prehyphenchar   (instance)) -- efficient if needed                              leftexchar  =                 (instance and preexhyphenchar (instance))                              rightexchar =                 (instance and postexhyphenchar(instance)) -                            leftmin     = leftcharmin  or getfield(current,"left") -                            rightmin    = rightcharmin or getfield(current,"right") +                            leftmin     = leftcharmin  or getfield(current,"lhmin") +                            rightmin    = rightcharmin or getfield(current,"rhmin")                              if not leftchar or leftchar < 0 then                                  leftchar = false                              end @@ -1516,8 +1516,8 @@ featureset.hyphenonly   = hyphenonly == v_yes                              rightchar   = rightchar    or (instance and prehyphenchar   (instance)) -- efficient if needed                              leftexchar  =                 (instance and preexhyphenchar (instance))                              rightexchar =                 (instance and postexhyphenchar(instance)) -                            leftmin     = leftcharmin  or getfield(current,"left") -                            rightmin    = rightcharmin or getfield(current,"right") +                            leftmin     = leftcharmin  or getfield(current,"lhmin") +                            rightmin    = rightcharmin or getfield(current,"rhmin")                              if not leftchar or leftchar < 0 then                                  leftchar = false                              end diff --git a/tex/context/base/mkxl/node-nut.lmt b/tex/context/base/mkxl/node-nut.lmt index dbd5c7ef2..296f6f446 100644 --- a/tex/context/base/mkxl/node-nut.lmt +++ b/tex/context/base/mkxl/node-nut.lmt @@ -97,9 +97,12 @@ local nuts = {      getnormalizedline       = direct.getnormalizedline,      getnucleus              = direct.getnucleus,      getoffsets              = direct.getoffsets, + -- getxyoffsets            = direct.getxyoffsets,      getscales               = direct.getscales,      getxscale               = direct.getxscale,      getyscale               = direct.getyscale, +    xscaled                 = direct.xscaled, +    yscaled                 = direct.yscaled,      getxyscales             = direct.getxyscales,      getorientation          = direct.getorientation,      getoptions              = direct.getoptions, @@ -156,7 +159,8 @@ local nuts = {      remove                  = d_remove_node,      reverse                 = direct.reverse,      set_attribute           = direct.set_attribute, -    setadvance              = direct.setadvance, +    addmargins              = direct.addmargins, +    addxymargins            = direct.addxymargins,      setattr                 = direct.set_attribute,      setattrs                = direct.set_attributes,      setattributelist        = direct.setattributelist, @@ -189,6 +193,8 @@ local nuts = {      setnucleus              = direct.setnucleus,      setscales               = direct.setscales,      setoffsets              = direct.setoffsets, +    addxoffset              = direct.addxoffset, +    addyoffset              = direct.addyoffset,      setorientation          = direct.setorientation,      setoptions              = direct.setoptions,      setpenalty              = direct.setpenalty, diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt index 2be9529a9..8c04a0372 100644 --- a/tex/context/base/mkxl/trac-vis.lmt +++ b/tex/context/base/mkxl/trac-vis.lmt @@ -57,6 +57,7 @@ local getwidth            = nuts.getwidth  local getdepth            = nuts.getdepth  local getexpansion        = nuts.getexpansion  local getstate            = nuts.getstate +local getoffsets          = nuts.getoffsets  local isglyph             = nuts.isglyph @@ -878,18 +879,20 @@ local ruledglyph do              local prev = previous              setboth(current)              local linewidth = emwidth/(2*fraction) -            local info -            -- -            info = setlink( -                (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { -                    width  = wd, -                    height = ht, -                    depth  = dp, -                    line   = linewidth, -                    type   = "box", -                }, -                new_kern(-wd) -            ) +            local x_offset, y_offset, l_margin, r_margin, raise = getoffsets(current) +            wd = wd - l_margin - r_margin +            local info = (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { +                width  = wd, +                height = ht, +                depth  = dp, +                line   = linewidth, +                type   = "box", +            } +            if l_margin == 0 then +                info = setlink(info,new_kern(-wd)) +            else +                info = setlink(new_kern(-l_margin),info,new_kern(-wd+l_margin)) +            end              --              local c, f = isglyph(current)              local char = chardata[f][c] diff --git a/tex/context/interface/mkii/keys-cs.xml b/tex/context/interface/mkii/keys-cs.xml index eddd75da9..9765bf47f 100644 --- a/tex/context/interface/mkii/keys-cs.xml +++ b/tex/context/interface/mkii/keys-cs.xml @@ -1137,6 +1137,7 @@  		<cd:constant name='reference' value='odkaz'/>  		<cd:constant name='referencemethod' value='referencemethod'/>  		<cd:constant name='referenceprefix' value='referenceprefix'/> +		<cd:constant name='referencetext' value='referencetext'/>  		<cd:constant name='referencing' value='odkazujici'/>  		<cd:constant name='region' value='region'/>  		<cd:constant name='regionin' value='oblastuvnitr'/> diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index f987a7c06..c1300a71b 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@  -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua  -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date  : 2021-01-08 11:44 +-- merge date  : 2021-01-11 16:28  do -- begin closure to overcome local limits and interference  | 
